xUnit.net不捕获控制台输出

kfu*_*ang 35 xunit.net

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

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

Jos*_*her 39

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");
  }
}
Run Code Online (Sandbox Code Playgroud)

您可以选择将日志记录框架连接到此接口,可能是通过注入ILog转发所有调用的实现ITestOutpuHelper.

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

  • 运行`dotnet test`时我没有看到输出.在运行.NET Core测试运行器时使用此接口是否有秘密?(编辑:看起来只有在断言失败后才会显示日志,所以意图似乎是只能通过调试失败来查看日志,我可以忍受,不情愿.) (4认同)
  • [官方示例代码](https://github.com/xunit/samples.xunit/blob/master/TestOutputExample/Example.cs)。它仍然适用于 .NET 核心项目。 (3认同)
  • 顺便说一句,ITestOutputHelper位于Xunit.Abstractions命名空间中. (2认同)
  • @乔纳森B。使用 `dotnet test --logger "console;verbosity=detailed"` 运行 (2认同)

Ben*_*jol 12

如果您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);
        }
    }
Run Code Online (Sandbox Code Playgroud)

  • 不,恰恰相反。重写 Write(char) 将使 WriteLine(string) 工作,但反之则不然。请参阅/sf/ask/1239882521/ (2认同)

kaa*_*aah 7

我使用 Console.SetOut 将 Console.Writes 输出到 .NET 测试日志(在 Visual Studio Code 中)。

using System;
using System.IO;
using Xunit;
using Xunit.Abstractions;

namespace UnitTest
{
    public class TestClass
    {
        private ITestOutputHelper output;
        public TestClass(ITestOutputHelper output)
        {
            this.output = output;
        }

        public class ConsoleWriter : StringWriter
        {
            private ITestOutputHelper output;
            public ConsoleWriter(ITestOutputHelper output)
            {
                this.output = output;
            }

            public override void WriteLine(string m)
            {
                output.WriteLine(m);
            }
        }

        [Fact]
        public void TestName()
        {
            Console.SetOut(new ConsoleWriter(output));
            Assert.True(ToBeTested.Foo());
        }



        public class ToBeTested
        {
            public static bool Foo()
            {
                Console.WriteLine("Foo uses Console.WriteLine!!!");
                return true;
            }
        }

    }

}
Run Code Online (Sandbox Code Playgroud)

但通过控制台运行测试更容易

dotnet test 
Run Code Online (Sandbox Code Playgroud)

输出将在没有对测试类进行任何修改的情况下显示。

这是不同的,因为 .NET 测试日志窗口使用 TRX 格式(Visual Studio 测试结果文件),请参阅

dotnet test -h | grep logger
Run Code Online (Sandbox Code Playgroud)

有关 TRX 的更多信息。


Rub*_*ink -14

一般来说,依赖日志记录测试是一条糟糕的道路。通过/失败应该是测试的结果。他们根本不应该达到这样的阶段:有足够多的事情正在发生,以至于有必要查看痕迹。

显示xunit.gui.exe控制台和跟踪输出,xunit.console.exe但不显示。如果它很重要,您可以连接一个 TraceListener,它通过创建适当的标准 .NET 配置条目来重定向到文件(FileWriterTraceListener如果您用 google 搜索,您应该能够连接到该文件)。


更新:正如在他的博客文章中所讨论的,Damian Hickey 有一个可能的替代品的很好的例子 - 将日志记录连接到 xUnit 2,ITestOutputHelperhttps://github.com/damianh/CapturingLogOutputWithXunit2AndParallelTests/blob/master/src/Lib.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
Run Code Online (Sandbox Code Playgroud)

此方法与使用日志上下文的区别在于,Logger不会记录到全局[上下文化] Serilog。

  • “总的来说,依赖日志记录和测试是一条糟糕的道路。” - 是的,但是在我设置测试时使用 Console.Writeline 输出内容非常有帮助。有时我正在测试一个方法,需要查看该方法的输出(例如,在执行自定义序列化时是否正确序列化了某些内容)以插入回测试中以进行比较。 (49认同)
  • 那么 xUnit 作者认为,让测试失败而没有任何关于“为什么”的信息是一个很好的设计吗? (33认同)
  • 我强烈不同意你关于“依赖日志记录和测试是一条糟糕的道路”的评论。我们运行集成测试(除了单元测试),如果出现问题,在进一步调查之前查看日志信息以了解到底失败的原因非常有帮助。 (30认同)
  • 切换到 NUnit,它捕获标准输出。如果测试失败,了解生产代码中发生的情况非常重要,在这种情况下,日志记录就变得很重要。将任何测试框架特定的依赖项注入到生产代码中,以便我可以在运行测试时看到输出,这是荒谬的。我发现,当人们开始告诉你“xxx 是一个坏主意......”时,虽然听起来很酷,但这通常是你遇到问题的工具无能的借口。 (19认同)