Skip to main content
dotnet-testing-test-output-logging xUnit 測試輸出與記錄完整指南。當需要在 xUnit 測試中實作測試輸出、診斷記錄或 ILogger 替代品時使用。涵蓋 ITestOutputHelper 注入、AbstractLogger 模式、結構化輸出設計。包含 XUnitLogger、CompositeLogger、效能測試診斷工具實作。
Make sure to use this skill whenever the user mentions ITestOutputHelper, test output, test logging, XUnitLogger, AbstractLogger, or ILogger testing in xUnit, even if they don't explicitly ask for test output guidance.
Keywords: ITestOutputHelper, ILogger testing, test output xunit, 測試輸出, 測試記錄, AbstractLogger, XUnitLogger, CompositeLogger, testOutputHelper.WriteLine, 測試診斷, logger mock, 測試日誌, 結構化輸出, Received().Log
Zur Installation springen Skills Marktplatz Entdecken und erkunden Sie KI-Skills, die von der Community erstellt wurden.
Mit Codex oder Claude installieren Kopieren Sie diesen Prompt, fügen Sie ihn in Codex, Claude oder einen anderen Assistant ein und lassen Sie die Skill-Seite prüfen und installieren.
Prompt kopierenPrompt-Details anzeigen Ein direkter Befehl überspringt den Prüf-Prompt. Prüfen Sie die Quelle, bevor Sie ihn ausführen.
npx skills add https://github.com/kevintsengtw/dotnet-testing-agent-skills --skill dotnet-testing-test-output-loggingDer Befehl bleibt in einer Zeile. Scrollen Sie horizontal, um ihn vor dem Kopieren vollständig zu prüfen.
Sie bevorzugen eine lokale Kopie? Laden Sie die Dateien herunter, die SkillsMP derzeit vorliegen.
ZIP herunterladen Herunterladen... Mehr aus diesem Repository
Verwandte Berufe SOC
Basierend auf der SOC-Berufsklassifikation
dotnet-testing-advanced-aspire-testing .NET Aspire Testing 整合測試框架完整指南。當需要測試 .NET Aspire 分散式應用程式、設定 AppHost 測試或從 Testcontainers 遷移至 Aspire 測試時使用。涵蓋 DistributedApplicationTestingBuilder、容器生命週期管理、多服務編排、Respawn 配置與時間可測試性設計。
Make sure to use this skill whenever the user mentions .NET Aspire, AppHost testing, DistributedApplicationTestingBuilder, cloud-native testing, or migrating from Testcontainers to Aspire, even if they don't explicitly ask for Aspire testing guidance.
Keywords: aspire testing, .NET Aspire, DistributedApplicationTestingBuilder, AppHost testing, 分散式測試, AspireAppFixture, IAsyncLifetime, ContainerLifetime.Session, 雲原生測試, 多服務整合, Aspire.Hosting.Testing, Respawn
dotnet-testing-advanced-aspnet-integration-testing ASP.NET Core 整合測試的專門技能。當需要測試 Web API 端點、HTTP 請求/回應、中介軟體、依賴注入時使用。涵蓋 WebApplicationFactory、TestServer、HttpClient 測試、記憶體資料庫配置等。
Make sure to use this skill whenever the user mentions ASP.NET Core integration testing, WebApplicationFactory, TestServer, HTTP endpoint testing, or middleware testing, even if they don't explicitly ask for integration testing guidance.
Keywords: integration testing, 整合測試, web api testing, WebApplicationFactory, TestServer, HttpClient testing, controller testing, endpoint testing, 端點測試, RESTful API testing, Microsoft.AspNetCore.Mvc.Testing, CreateClient, ConfigureWebHost, AwesomeAssertions.Web, Be200Ok, Be404NotFound, middleware testing, 中介軟體測試, dependency injection testing
.NET 進階測試技能總覽與引導中心。當使用者詢問「整合測試」、「API 測試」、「容器化測試」、「微服務測試」、「測試框架遷移」、「Testcontainers」、「Aspire 測試」等進階測試需求時觸發。會根據具體需求推薦適合的子技能組合,涵蓋整合測試、Testcontainers、Aspire 測試、框架升級等 8 個進階技能。
Make sure to use this skill whenever the user mentions integration testing, API testing, Testcontainers, .NET Aspire testing, WebApplicationFactory, or xUnit/TUnit migration, even if they don't explicitly ask for advanced testing guidance.
Keywords: integration testing, 整合測試, API testing, advanced testing, 進階測試, testcontainers, aspire testing, WebApplicationFactory, TestServer, database test, 資料庫測試, EF Core test, MongoDB test, Redis test, Docker test, 容器測試, microservice test, 微服務測試, .NET Aspire, xUnit upgrade, TUnit, framework migration
name dotnet-testing-test-output-logging description xUnit 測試輸出與記錄完整指南。當需要在 xUnit 測試中實作測試輸出、診斷記錄或 ILogger 替代品時使用。涵蓋 ITestOutputHelper 注入、AbstractLogger 模式、結構化輸出設計。包含 XUnitLogger、CompositeLogger、效能測試診斷工具實作。
Make sure to use this skill whenever the user mentions ITestOutputHelper, test output, test logging, XUnitLogger, AbstractLogger, or ILogger testing in xUnit, even if they don't explicitly ask for test output guidance.
Keywords: ITestOutputHelper, ILogger testing, test output xunit, 測試輸出, 測試記錄, AbstractLogger, XUnitLogger, CompositeLogger, testOutputHelper.WriteLine, 測試診斷, logger mock, 測試日誌, 結構化輸出, Received().Log
測試輸出與記錄專家指南
本技能協助您在 .NET xUnit 測試專案中實作高品質的測試輸出與記錄機制。
核心原則
1. ITestOutputHelper 使用原則
正確的注入方式
透過建構式注入 ITestOutputHelper
每個測試類別的實例與測試方法綁定
不可在靜態方法或跨測試方法間共用
public class MyTests
{
private readonly ITestOutputHelper _output;
public MyTests (ITestOutputHelper testOutputHelper )
{
_output = testOutputHelper;
}
}
常見錯誤
靜態存取:private static ITestOutputHelper _output
在非同步測試中未等待即使用
嘗試在 Dispose 方法中使用
2. 結構化輸出格式設計
建議的輸出結構
private void LogSection ( title )
{
_output.WriteLine( );
}
{
_output.WriteLine( );
}
{
_output.WriteLine( );
}
string
$"\n=== {title} ==="
private void LogKeyValue (string key, object value )
$"{key} : {value } "
private void LogTimestamp (DateTime time )
$"執行時間: {time:yyyy-MM-dd HH:mm:ss.fff} "
測試開始時:記錄測試設置與輸入資料
執行過程中:記錄重要的狀態變化
斷言前:記錄預期值與實際值
測試結束時:記錄執行時間與結果摘要
3. ILogger 測試策略 ILogger.LogError() 是擴充方法,NSubstitute 無法直接攔截。需要攔截底層的 Log<TState> 方法:
logger.Received().LogError(Arg.Any<string >());
logger.Received().Log(
LogLevel.Error,
Arg.Any<EventId>(),
Arg.Is<object >(o => o.ToString().Contains("預期訊息" )),
Arg.Any<Exception>(),
Arg.Any<Func<object , Exception, string >>()
);
建立 AbstractLogger<T> 來簡化測試:
public abstract class AbstractLogger <T > : ILogger <T >
{
public IDisposable BeginScope <TState >(TState state )
=> null ;
public bool IsEnabled (LogLevel logLevel )
=> true ;
public void Log <TState >(
LogLevel logLevel,
EventId eventId,
TState state,
Exception exception,
Func<TState, Exception, string > formatter )
{
Log(logLevel, exception, state?.ToString() ?? string .Empty);
}
public abstract void Log (LogLevel logLevel, Exception ex, string information ) ;
}
var logger = Substitute.For<AbstractLogger<MyService>>();
logger.Received().Log(LogLevel.Error, Arg.Any<Exception>(), Arg.Is<string >(s => s.Contains("錯誤訊息" )));
4. 診斷工具整合 public class XUnitLogger <T > : ILogger <T >
{
private readonly ITestOutputHelper _testOutputHelper;
public XUnitLogger (ITestOutputHelper testOutputHelper )
{
_testOutputHelper = testOutputHelper;
}
public void Log <TState >(LogLevel logLevel, EventId eventId, TState state,
Exception exception, Func<TState, Exception, string > formatter )
{
var message = formatter(state, exception);
_testOutputHelper.WriteLine($"[{DateTime.Now:HH:mm:ss.fff} ] [{logLevel} ] [{typeof (T).Name} ] {message} " );
if (exception != null )
{
_testOutputHelper.WriteLine($"Exception: {exception} " );
}
}
}
CompositeLogger:同時支援驗證與輸出
public class CompositeLogger <T > : ILogger <T >
{
private readonly ILogger<T>[] _loggers;
public CompositeLogger (params ILogger<T>[] loggers )
{
_loggers = loggers;
}
public void Log <TState >(LogLevel logLevel, EventId eventId, TState state,
Exception exception, Func<TState, Exception, string > formatter )
{
foreach (var logger in _loggers)
{
logger.Log(logLevel, eventId, state, exception, formatter);
}
}
}
var mockLogger = Substitute.For<AbstractLogger<MyService>>();
var xunitLogger = new XUnitLogger<MyService>(_output);
var compositeLogger = new CompositeLogger<MyService>(mockLogger, xunitLogger);
var service = new MyService(compositeLogger);
實作指南
效能測試中的時間點記錄 [Fact ]
public async Task ProcessLargeDataSet_效能測試()
{
var stopwatch = Stopwatch.StartNew();
var checkpoints = new List<(string Stage, TimeSpan Elapsed)>();
_output.WriteLine("開始處理大型資料集..." );
await processor.LoadData(dataSet);
checkpoints.Add(("資料載入" , stopwatch.Elapsed));
_output.WriteLine($"資料載入完成: {stopwatch.Elapsed.TotalMilliseconds:F2} ms" );
await processor.ProcessData();
checkpoints.Add(("資料處理" , stopwatch.Elapsed));
_output.WriteLine($"資料處理完成: {stopwatch.Elapsed.TotalMilliseconds:F2} ms" );
stopwatch.Stop();
_output.WriteLine("\n=== 效能報告 ===" );
foreach (var (stage, elapsed) in checkpoints)
{
_output.WriteLine($"{stage} : {elapsed.TotalMilliseconds:F2} ms" );
}
}
診斷測試基底類別 public abstract class DiagnosticTestBase
{
protected readonly ITestOutputHelper Output;
protected DiagnosticTestBase (ITestOutputHelper output )
{
Output = output;
}
protected void LogTestStart (string testName )
{
Output.WriteLine($"\n=== {testName} ===" );
Output.WriteLine($"執行時間: {DateTime.Now:yyyy-MM-dd HH:mm:ss.fff} " );
}
protected void LogTestData (object data )
{
Output.WriteLine($"測試資料: {JsonSerializer.Serialize(data, new JsonSerializerOptions { WriteIndented = true } )}" );
}
protected void LogAssertionFailure (string field, object expected, object actual )
{
Output.WriteLine("\n=== 斷言失敗 ===" );
Output.WriteLine($"欄位: {field} " );
Output.WriteLine($"預期值: {expected} " );
Output.WriteLine($"實際值: {actual} " );
}
}
最佳實踐
適當使用 ITestOutputHelper
在複雜測試中記錄重要步驟,幫助追蹤失敗原因
採用一致的結構化輸出格式(章節標題、時間戳記),讓輸出易於閱讀
在效能測試中記錄時間點,提供量化數據
Logger 測試策略
使用抽象層(AbstractLogger)簡化測試,因為 ILogger 擴充方法無法直接 Mock
驗證記錄層級而非完整訊息,避免測試因訊息文字微調而失敗
使用 CompositeLogger 結合 Mock 與實際輸出,同時達成驗證與診斷
常見誤區
過度使用輸出 — 大量輸出會拖慢測試執行速度,且雜訊會淹沒有用資訊。只在複雜或易失敗的測試中加入輸出即可。記錄敏感資訊(密碼、金鑰)也是常見的安全風險。
硬編碼記錄驗證 — 驗證完整的記錄訊息字串容易因訊息微調而失敗,驗證呼叫次數則過度指定了內部實作。改為驗證記錄層級和關鍵字即可。
忽略生命週期 — ITestOutputHelper 的實例與測試方法綁定,在靜態方法或跨測試方法中使用會拋出例外。非同步測試中遺漏 await 也可能導致輸出遺失。
範例參考
itestoutputhelper-example.cs - ITestOutputHelper 使用範例
ilogger-testing-example.cs - ILogger 測試策略範例
diagnostic-tools.cs - XUnitLogger 與 CompositeLogger 實作
輸出格式
產生含 ITestOutputHelper 注入的測試類別
提供 AbstractLogger/XUnitLogger/CompositeLogger 實作程式碼
包含結構化輸出的 helper 方法
ILogger 驗證使用底層 Log 方法而非擴充方法
參考資源
原始文章 本技能內容提煉自「老派軟體工程師的測試修練 - 30 天挑戰」系列文章:
Day 08 - 測試輸出與記錄:xUnit ITestOutputHelper 與 ILogger
官方文件
相關技能
unit-test-fundamentals - 單元測試基礎
xunit-project-setup - xUnit 專案設定
nsubstitute-mocking - 測試替身與模擬
範例檔案
測試清單