xUnit.net不捕获控制台输出

问题描述 投票:32回答:5

我刚刚开始测试xUnit.net,但它似乎没有像我期望的那样捕获任何输出(控制台,调试,跟踪)。

那可能吗?我正在使用带有xUnit.net 1.8的示例.NET 4.0类库。

xunit.net
5个回答
3
投票

总的来说,依靠日志记录和测试是一条糟糕的道路。通过/失败应该是测试的结果。而且他们根本不应该进入有足够的东西进行的阶段,因此需要查看跟踪。

xunit.gui.exe显示控制台和跟踪输出,xunit.console.exe没有。如果它很重要,你可以通过制作适当的标准.NET配置条目来连接一个TraceListener,它重定向到一个文件(如果你谷歌它,你应该可以挂钩的Theres'a FileWriterTraceListener)。


更新:正如在his blog post中所讨论的那样,Damian Hickey有一个可能的替代品的好例子 - 如ITestOutputHelper所示,在xUnit 2 https://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

与使用日志上下文相比,这种方法的不同之处在于,登录到全局[contextualized] Serilog Logger将无法获取。


38
投票

xUnit.net 2的情况发生了一些变化。我知道问题是关于早期版本的问题,但是由于人们将在这里进行升级,我认为值得指出这一点。

为了在版本2的测试输出中看到某种输出,您需要在ITestOutputHelper的实例上对测试类(通过构造函数参数)进行依赖,然后在此接口上使用WriteLine方法。例如。:

public class MyTestSpec
{
  private readonly ITestOutputHelper _testOutputHelper;

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

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

你可以选择将你的日志框架连接到这个接口,也许是通过注入一个将所有调用转发到ILogITestOutpuHelper实现。

我承认您默认情况下不会这样做,但为了诊断目的,它可能会非常有用。如果您的测试仅在某些基于云的构建和测试服务器上失败,则尤其如此!


7
投票

如果您的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);
        }
    }

2
投票

这里有一个解决方案:https://xunit.codeplex.com/discussions/211566

只需将其添加到您想要调试输出的构造函数或方法中:

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

0
投票

我带着同样的问题来到这里。这就是我最终的结果。我希望它可以帮助别人。

How to write a custom target

    /// <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;
        }
    }
© www.soinside.com 2019 - 2024. All rights reserved.