Microsoft.Testing.Platform ile Test Raporlama Rehberi
CI ortamında bir test kırıldığında “build kırmızı” yalnızca başlangıç noktasıdır. Sorulacaklar şunlar: Bu değişiklik mi hataya yol açtı, aynı test daha önce de kırılmış mıydı, kanıtlara nereden ulaşılabilir? Bu soruların cevabı için iş loglarını taramak, artifact indirmek ve testin geçmişini hatırlayan bir ekip arkadaşını bulmak gerekiyorsa, rapor işini tam yapmıyor demektir.
Microsoft.Testing.Platform (MTP); dotnet test, Visual Studio ve Visual Studio Code’daki Test Explorer ile CI test koşumlarının arkasındaki motordur. Son bir yılda raporlama tarafı belirgin biçimde gelişti: Hatalar geliştiricinin ve reviewer’ın çalıştığı yere taşındı, koşum çöktüğünde kanıt korunur hale geldi. Bu yetenekler MSTest, NUnit, xUnit.net, TUnit ve Expecto gibi mevcut test framework’lerinizle çalışır.
Yazıdaki örneklerin büyük çoğunluğu MTP 2.3.0 veya sonrasını gerektirir. Kaynaktaki doğrulamalar MSTest.Sdk 4.3.3 ve MTP 2.3.3 ile yapıldı; GitHub Actions, JUnit ve CTRF raporlayıcıları şu an preview olarak dağıtılıyor.
GitHub Actions ve Azure DevOps desteği ne kadar?
Anlatılan özelliklerin çoğu sağlayıcıdan bağımsız çalışır. Ancak build geçmişini okuyan iki güçlü özellik şu an yalnızca Azure DevOps’ta var.
- Satır içi hata anotasyonları ve iş özeti: GitHub Actions ve Azure DevOps için mevcut.
- Koşum sürerken canlı sonuç yayınlama: Yalnızca Azure DevOps.
- Flaky/regresyon geçmişi, karantina ve yavaş test geçmişi: Yalnızca Azure DevOps.
- Çökmeye dayanıklı raporlar, rapor formatları ve JSON keşfi: Sağlayıcıdan bağımsız.
Her iki sağlayıcıda da öncelikli adım satır içi raporlamayı açmaktır; tek başına bu bile bir sonraki hatayı ham logun dışına çıkarır. Azure DevOps kullanıyorsanız sıradaki adım geçmişe dayalı triyajı devreye almaktır.
Hatayı geliştiricinin baktığı yere taşıyın
Artifact içine düşen bir raporu birinin gidip indirmesi gerekir. MTP artık her iki CI sağlayıcısının kendi anlayacağı anotasyon formatını üretebiliyor.
GitHub Actions’ta --report-gh etkinleştirildiğinde başarısız bir test doğrudan ilgili kod satırında anotasyon olarak görünür. Atlanan testler warning olarak işaretlenir, her assembly kendi log grubuna toplanır ve aynı koşum workflow sayfasına bir özet yazar. Anotasyonlar, log grupları, özet ve yavaş test bildirimleri bağımsız olarak yapılandırılabilir.
Azure DevOps tarafında --report-azdo aynı yapıyı sağlar. GitHub Actions’ta henüz olmayan bir özelliği daha vardır: --publish-azdo-test-results ile sonuçlar koşum sürerken Tests sekmesine akmaya başlar; ayrı bir publish adımının koşumun sonuna kadar hayatta kalmasına gerek kalmaz. İki bayrak birbirinden bağımsızdır: --report-azdo anotasyon ve loglama, --publish-azdo-test-results ise Tests sekmesi ile ilgilenir.
Azure DevOps: Regresyonu bilinen flaky’den ayırt etmek
Build geçmişinin açtığı asıl karar noktası şudur: yalnızca hangi testin kırıldığı değil, mevcut değişikliğin bu hatanın sebebi olma olasılığı. Büyük test setlerinde aralıklı hata veren testler, reviewer’ları kırmızıyı arka plan gürültüsü olarak okumaya alıştırır. “Muhtemelen flaky’dir” birinci varsayım olduğunda gerçek regresyonlar da aynı umursamazlıkla karşılanır.
Raporlayıcıya 14 günlük bir pencere verildiğinde pipeline geçmişi sorgulanır ve her hataya ilgili bağlam eklenir:
dotnet test --report-azdo --report-azdo-flaky-history 14
İki haftadır aralıklı hata veren bir test [flaky: failed 3/20 in last 14d] etiketi alırken, geçmişi bulunmayan bir hata [REGRESSION] olarak işaretlenir. Bu, “bir gün birisi bakmalı” cümlesini “bu pull request bir şeyi kırdı” cümlesine dönüştürür.
CI’ın yalnızca söylemesi değil davranış değiştirmesi isteniyorsa --report-azdo-demote-known-flaky ile bilinen flaky hatalar warning’e düşürülür, regresyonlar error olarak kalır. Kaynağa göre testfx pipeline’ı geçmiş anotasyonlarını kullanır ancak otomatik düşürmeyi kapalı tutar; her hata bloklayıcı kalır ve geçmiş yalnızca triyaja rehberlik eder. Açıkça verilmesi gereken karar şu: Geçmiş reviewer’ı bilgilendirsin mi, yoksa CI ciddiyetini kendiliğinden değiştirsin mi?
Aynı geçmiş yavaş test tespitini de besler. Her proje için yanlış olan tek bir eşik yerine --report-azdo-slow-test-history, her testi kendi geçmişiyle karşılaştırır. Eşik, minimum bir koşum sayısı üzerinde yapılandırılabilir bir katsayı olduğu için tek bir soğuk başlangıç yanlış alarm üretmez.
Koşum çöktüğünde kanıtı korumak
Geçmiş, hatanın yeni olup olmadığını belirlemeye yardımcı olur; ancak koşum kanıtı kaybederse triyaj yine tıkanır. Raporuna en çok ihtiyaç duyulan koşum genellikle çöken koşumdur. Eskiden sonuçlar sona doğru serileştirildiği için bu koşumlar hiçbir çıktı üretmezdi.
Artık TRX sonuçları üretildikçe diske akıtılıyor; sert bir çökme tüm raporu beraberinde götürmüyor. --report-trx crash-dump uzantısıyla birlikte kullanıldığında koşum, host çöktüğünde parçalı raporu sonlandıran bir controller süreci tarafından denetlenir:
dotnet test --report-trx --crashdump
Sonuçta tamamlanan her testi içeren geçerli bir TRX ve tamamlanamayanların konsol listesi elde edilir:
The following tests were still running when the test host crashed:
[00:00:00] D_crash_the_host
Bu, süreci düşüren testi tüm testleri tekrar çalıştırmadan adlandırır. Uzantı ayrıca her test başlangıç ve bitişini kaydeden bir *.crash.sequence.log yazar; böylece paralel koşumlarda başlayıp bitmeyen bir test net biçimde ayırt edilir.
Ek dosyalar (attachment) da benzer davranışa kavuştu. Crash dump’ları, hang dump’ları ve uzantı artifact’leri artık.NET Framework üzerinde Windows MAX_PATH sınırı aşıldığında sessizce düşürülmüyor; kopyalanamayan bir ek yalnızca TRX içinde değil konsolda da bildiriliyor. Eksik bir koşum artık görünür şekilde eksik.
Tek koşum, insanlar ve araçlar için farklı raporlar
Çıktıyı kimin tükettiğine göre seçmek gerekir..NET araçları için TRX, doğrudan inceleme için HTML, dashboard ve çapraz platform otomasyon için JUnit veya CTRF uygundur. Tek bir koşum bu formatların herhangi bir kombinasyonunu üretebilir; pipeline’a sıkça eklenen format dönüştürme adımı ortadan kalkar.
| Format | Bayrak | Paket | Durum |
|---|---|---|---|
| TRX | --report-trx |
Microsoft.Testing.Extensions.TrxReport | Stable |
| HTML | --report-html |
Microsoft.Testing.Extensions.HtmlReport | Stable |
| JUnit XML | --report-junit |
Microsoft.Testing.Extensions.JUnitReport | Preview |
| CTRF JSON | --report-ctrf |
Microsoft.Testing.Extensions.CtrfReport | Preview |
CTRF, farklı dillerdeki sonuçları toplulaştıranlar için özellikle ilgi çekicidir: Paylaşımlı bir JSON şeması olduğu için.NET raporları çok dilli bir yığındaki diğer raporlarla aynı şekle sahip olur.
CI sistemlerinin sonuç görünümüne parse ettiği yalnızca TRX ve JUnit’tir. HTML ve CTRF insanlar ve dashboard’lar içindir; bu nedenle indirilebilir artifact olarak sunulurlar. Azure DevOps tarafında --report-azdo-upload-artifacts files bu dosyaları otomatik toplar. Aşağı akışta bir şey sonuçları okuyacaksa TRX veya JUnit tercih edin; ekibinizin gözüyle bakması gereken bir çıktı gerekiyorsa HTML veya CTRF ekleyin.
Rapor isim çakışmaları da giderildi. Her raporlayıcı, {asm} ve {tfm} gibi build’e özel yer tutucuları kabul eden --report-<format>-filename parametresini destekler:
dotnet test --report-trx --report-trx-filename "reports/{asm}_{tfm}_{time}.trx"
Varsayılan bırakıldığında TRX, HTML ve JUnit artık deterministik bir <asm>_<tfm>_<arch> adı kullanır. Çoklu hedefleme durumunda net8.0 ve net8.0-windows aynı dosyayı ezmek yerine ayrı dosyalar yazar; matrix build’lerde göz kaçırılabilecek sessiz bir veri kaybı hatası bu sayede engellenir.
Otomasyon için stabil çıktı
İnsanlar pull request içinde eyleme geçirilebilir bağlam ister; otomasyon aynı bağlamı stabil ve yapılandırılmış bir formatta ister. Script’ler, dashboard’lar, IDE entegrasyonları ve kodlama ajanları terminal metnini güvenilir biçimde tüketemez.
--list-tests json, keşfedilen her testi kaynak konumuna kadar tanımlayan şema versiyonlu bir belge üretir:
{
"schemaVersion": 1,
"tests": [
{
"uid": "11a3aade-7a31-8389-89ce-eab6ff0db7f3",
"displayName": "Total_includes_shipping",
"location": { "file": "CheckoutTests.cs", "lineStart": 13, "lineEnd": 13 }
}
]
}
Bu şema; test seçimi, etki analizi veya IDE entegrasyonu için sürümler arasında değişebilen konsol metnini kazımaya kıyasla stabil bir girdi sunar.
MTP kendi çıktısını da bu tüketicilere göre uyarlar. Ajan veya LLM ortamında banner, ANSI escape ve ilerleme animasyonlarını bastırır; --show-stdout ve --show-stderr için varsayılan olarak failed değerini kullanır. Aynı davranış manuel olarak da ayarlanabilir; platform NO_COLOR‘a saygı gösterir ve --ansi ile --progress bayraklarını sunar.
Depo genelinde ölçeklemek
Raporlama politikası belirlendiğinde, bu politikayı herkesin kabuk geçmişinde değil depoda tutmak gerekir. MTP CLI referansındaki her seçenek, test projenizin yanındaki bir testconfig.json içinde commandLineOptions altında yer alabilir:
{
"commandLineOptions": {
"report-trx": true,
"report-html": true,
"report-azdo": true,
"report-azdo-flaky-history": 14
}
}
Böylece yerel ve CI koşumları varsayılan olarak aynı raporları üretir; geliştirici komut satırından yine geçersiz kılabilir. Yanlış yazılmış ayarlar başlangıçta dosyanın adını da veren bir hata mesajı ile başarısız olur:
In testconfig.json under 'commandLineOptions': Unknown option '--report-trxx'
Depo çapında uygulama için birkaç öneri:
- Kararlı olduğunuzda merkezileştirin.
MSTest.Sdkile her raporlayıcı bir MSBuild özelliğidir; tek birDirectory.Build.propspolitikayı depodaki tüm test projelerine uygular:<Project> <PropertyGroup> <EnableMicrosoftTestingExtensionsHtmlReport>true</EnableMicrosoftTestingExtensionsHtmlReport> <EnableMicrosoftTestingExtensionsAzureDevOpsReport>true</EnableMicrosoftTestingExtensionsAzureDevOpsReport> </PropertyGroup> </Project>Özellikler tek bir kalıbı izler (
EnableMicrosoftTestingExtensions+ raporlayıcı adı) ve<TestingExtensionsProfile>AllMicrosoft</TestingExtensionsProfile>stabil kümeyi tek satırda etkinleştirir: TRX, HTML, Azure DevOps, GitHub Actions, crash dump, hang dump ve retry. JUnit ve CTRF opt-in olarak kalır. - Farklı framework’lerde sürümü kontrol edin.
MSTest.Sdkdışında raporlayıcı paketi doğrudan referanslanır ve framework’ünüzün hedeflediği MTP sürümüyle eşleşmesi gerekir. Bu raporlayıcılar MTP 2.x üzerinde derlendiği için eski bir framework sürümünde kullanıldığında başlangıçtaMissingMethodExceptionile hata verir. MTP 2.x desteği kaynak yazıda şu sürümlerle geldi:MSTest.TestAdapter4.0.0,NUnit3TestAdapter6.0.1,TUnit1.7.16,YoloDev.Expecto.TestSdk0.16.0 vexunit.v34.0 prerelease’leri. - Runner opt-in’i depo seviyesinde bir kez ayarlayın.
dotnet test‘in projenizi MTP üzerinden çalıştırıp çalıştırmaması tek bir anahtardır;Directory.Build.props‘a koymak yeni bir projenin bu ayardan sapmasını engeller. MTP ve VSTest projelerini aynı solution içinde karıştırmak desteklenmez;.NET 10 SDK’da MTP projesini eski VSTest yolundan çalıştırmak build’i başarısız yapar ve opt-in bağlantısına yönlendirir. - Azure DevOps geçmiş seçenekleri token gerektirir.
--report-azdo-flaky-historyve--report-azdo-slow-test-historyAzure DevOps REST API’sini çağırır; adımaSYSTEM_ACCESSTOKEN: $(System.AccessToken)geçilmelidir. Token olmadan koşum devam eder ama geçmiş anotasyonları atlanır.
Mevcut publish görevlerini değiştirmek
Bir Azure DevOps pipeline’ınız varsa, hangi publish görevlerinin yerine geçilebileceği kaynakta şöyle özetlenmiştir. Canlı yayınlama, sonuçları zaten bellekte tutup doğrudan REST API’ye gönderir; TRX okumaz, dolayısıyla üretilecek veya glob edilecek bir rapor dosyası yoktur. --report-azdo-upload-artifacts files ile birleştirildiğinde çoğu pipeline’ın bugün taşıdığı görevlerin yerine geçer:
| Klasik görev | Yerine geçen |
|---|---|
| PublishTestResults@2 | --publish-azdo-test-results |
| PublishBuildArtifacts@1 / PublishPipelineArtifact@1 | --report-azdo-upload-artifacts files |
| PublishCodeCoverageResults@2 | Değiştirilmedi, pipeline’ın Code Coverage sekmesi için korunmalı |
Coverage konusunda dikkat gerekiyor. Canlı yayınlama .coverage, .cobertura.xml ve .opencover.xml dosyalarını test koşumuna ek olarak iliştirir; başarısız testler kendi ek dosyalarını (dump’lar, yakalanan stdout ve stderr) taşır. Ancak buradaki hiçbir şey pipeline’ın Code Coverage sekmesini doldurmaz; bu görevi bugün yapan adımı korumak gerekir.
PublishTestResults@2 görevi bağımsız iki yayıncıdır; tek koşumun iki görünümü değildir. Her ikisi de etkinleştirilirse Azure DevOps build için iki ayrı test koşumu oluşturur, bu yüzden birini seçmek gerekir.
Bugün denemek için adımlar
- Bir test projesinin MTP 2.3 veya sonrasını çalıştırdığını doğrulayın.
- CI sağlayıcınıza uygun raporlayıcıyı
MSTest.Sdküzerinden veya doğrudan paket referansıyla etkinleştirin. - GitHub Actions’ta
dotnet test --report-gh, Azure DevOps’tadotnet test --report-azdoekleyin. - Bir sonraki hatayla, raporun logları arama süresini gerçekten azaltıp azaltmadığını ölçün.
Raporlama, MTP’yi değerlendirmek için pratik bir başlangıç noktasıdır çünkü geliştiriciler, reviewer’lar ve build sahipleri farkı ilk günden görür. En küçük haliyle başlayın: Bir test projesinde --report-gh veya --report-azdo‘yu açın ve bir sonraki hatanın nerede göründüğüne bakın.
Kaynaklar ve İleri Okuma
- Test reporting in Microsoft.Testing.Platform: from red build to root cause — Amaury Levé,.NET Blog
- Microsoft.Testing.Platform genel bakış
- .NET ile
dotnet testkullanımı - MTP’nin test framework’lerinde benimsenmesi
- MTP test raporları belgeleri
- MTP crash ve hang dump belgeleri
- MTP CLI seçenekleri referansı
testconfig.jsonyapılandırma referansı- Microsoft.Testing.Extensions.TrxReport (NuGet)
- Microsoft.Testing.Extensions.HtmlReport (NuGet)
- Microsoft.Testing.Extensions.JUnitReport (NuGet)
- Microsoft.Testing.Extensions.CtrfReport (NuGet)
- CTRF (Common Test Report Format)







Yorum gönder