web-dev-qa-db-ja.com

xUnit.netがコンソール出力をキャプチャしない

XUnit.netのテストを開始したばかりですが、期待どおりに、出力(コンソール、デバッグ、トレース)をキャプチャしていません。

それは可能ですか?私はxUnit.net 1.8でサンプルの.NET 4.0クラスライブラリを使用しています。

36
kfuglsang

一般に、ロギングおよびテストに依存するように下るのは悪い道です。合格/不合格はテストの結果である必要があります。そして、彼らは、痕跡を見ることが必要になるであろう十分なものが起こっている段階に到達すべきではありません。

xunit.gui.exeはコンソールとトレースの出力、xunit.console.exe ではない。それが重要な場合は、適切な標準.NET構成エントリを作成することにより、ファイルにリダイレクトするTraceListenerを接続できます(グーグルで接続できるFileWriterTraceListenerがあります)。


更新: 彼のブログ投稿 で説明されているように、Damian Hickeyは可能な代替の良い例を持っています- https://で示されているようにxUnit 2 ITestOutputHelperへのロギングの配線github.com/damianh/CapturingLogOutputWithXunit2AndParallelTests/blob/master/src/Lib.Tests/Tests.cs

更新2:場合によっては、次のように単純なアダプターを使用して、ロギングを追加し、ITestOutputHelperに関与せずにLogContextにフィードすることができます(F#にしかありません、申し訳ありません)。

// Requirement: Make SUT depend on Serilog NuGet
// Requirement: Make Tests depend on Serilog.Sinks.Observable

type TestOutputAdapter(testOutput : Xunit.Abstractions.ITestOutputHelper) =
    let formatter = Serilog.Formatting.Display.MessageTemplateTextFormatter(
        "{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} [{Level}] {Message}{NewLine}{Exception}", null);
    let write logEvent =
        use writer = new System.IO.StringWriter()
        formatter.Format(logEvent, writer);
        writer |> string |> testOutput.WriteLine
    member __.Subscribe(source: IObservable<Serilog.Events.LogEvent>) =
        source.Subscribe write

let createLogger hookObservers =
    LoggerConfiguration()
        .WriteTo.Observers(Action<_> hookObservers)
        .CreateLogger()
let createTestOutputLogger (output: ITestOutputHelper) =
    let adapter = TestOutputAdapter testOutputHelper
    createLogger (adapter.Subscribe >> ignore)

type Tests(testOutputHelper) =
    let log = createTestOutputLogger testOutputHelper

    [<Fact>] let feedToSut () =
        // TODO pass log to System Under Test either as a ctor arg or a method arg

このアプローチとログコンテキストの使用の違いは、グローバル[コンテキスト化] Serilog Loggerへのロギングが取得されないことです。

0
Ruben Bartelink

XUnit.net 2で状況が少し変わりました。以前のバージョンに関する質問であることはわかっていますが、アップグレードを実行して人々がここに到着するので、これを指摘する価値があると思いました。

バージョン2のテスト出力にある種の出力を表示するには、Xunit.Abstractions.ITestOutputHelperのインスタンスに対する(コンストラクター引数を介して)テストクラスの依存関係を取得し、このインターフェイスでWriteLineメソッドを使用する必要があります。例えば。:

public class MyTestSpec
{
  private readonly ITestOutputHelper _testOutputHelper;

  public MyTestSpec(ITestOutputHelper testOutputHelper)
  {
    _testOutputHelper = testOutputHelper;
  }

  [Fact]
  public void MyFact()
  {
    _testOutputHelper.WriteLine("Hello world");
  }
}

おそらく、ILogへのすべての呼び出しを転送するITestOutpuHelper実装をインジェクトすることによって、ロギングフレームワークをこのインターフェイスに接続することを選択できます。

デフォルトではこれを実行する必要はありませんが、診断の目的で時々それは非常に便利です。これは、一部のクラウドベースのビルドおよびテストサーバーでのみテストが失敗する場合に特に当てはまります。

43
Josh Gallagher

これは、Console.Writeは、リファクタリングしたくないクラス階層の深いところに埋め込まれています。

    public MyTestClass(ITestOutputHelper output)
    {
        var converter = new Converter(output);
        Console.SetOut(converter);
    }

    private class Converter : TextWriter
    {
        ITestOutputHelper _output;
        public Converter(ITestOutputHelper output)
        {
            _output = output;
        }
        public override Encoding Encoding
        {
            get { return Encoding.Whatever; }
        }
        public override void WriteLine(string message)
        {
            _output.WriteLine(message);
        }
        public override void WriteLine(string format, params object[] args)
        {
            _output.WriteLine(format, args);
        }
    }
15
Benjol

ここにあるような解決策があります: https://xunit.codeplex.com/discussions/211566

これを、デバッグ出力が必要なコンストラクターまたはメソッドに追加するだけです。

Debug.Listeners.Add(new DefaultTraceListener());
1
pixelshaded

私は同じ質問でここに上陸しました。これが私が最終的に得たものです。それが他の誰かの役に立つことを願っています。

カスタムターゲットの記述方法

    /// <summary>
    ///     Use this to output NLog information when running test cases.
    /// </summary>
    [Target("XUnit")]
    public class XUnitTarget : TargetWithLayout
    {
        [RequiredParameter] public ITestOutputHelper OutputHelper { get; set; }

        protected override void Write(LogEventInfo logEvent)
        {
            var logMessage = Layout.Render(logEvent);
            OutputHelper.WriteLine(logMessage);
        }

        /// <summary>
        /// Call this in the test where you wish to enable logging.
        /// </summary>
        /// <param name="testOutputHelper">The xUnit output helper from the test.</param>
        public static void Configure(ITestOutputHelper testOutputHelper)
        {
            var config = new LoggingConfiguration();
            var xUnitTarget = new XUnitTarget
            {
                OutputHelper = testOutputHelper
            };
            config.AddTarget("xUnit", xUnitTarget);
            config.AddRule(LogLevel.Trace, LogLevel.Fatal, xUnitTarget);
            LogManager.Configuration = config;
        }
    }
0
Gabe Cook