37

我将 xUnit 与 ReSharper 测试运行器和xUnitContrib resharper插件一起使用。

当我有一个长时间运行的测试时,我希望能够将一些进度指示器输出到单元测试输出窗口。

我试过了Debug.WriteLinesTrace.WriteLineConsole.WriteLine。所有这些都具有相同的行为 - 在测试完成之前,输出窗口中不会显示任何内容。

例如:

[Fact]
public void Test()
{
    Debug.WriteLine("A");
    Trace.WriteLine("B");
    Console.WriteLine("C");

    Thread.Sleep(10000);
}

在 10 秒过去且测试完成之前,测试不会显示任何输出。我如何一路获得输出?

更新 1

我也尝试过使用 MSTest 和 NUnit。NUnit 是唯一一个一路显示输出的。

在测试完成之前,MSTest 和 XUnit 不会返回任何输出。奇怪的是,虽然 XUnit 和 NUnit 测试输出看起来像这样:

A
B
C

MSTest 输出如下所示:

C


Debug Trace:

A
B

鉴于所有这些变化,我认为答案是由测试运行程序实现来决定如何以及何时输出。有谁知道是否可以配置 XUnit 测试运行器?

更新 2

我认为这一定是 xUnitContrib 的不足之处。发布到他们的CodePlex 问题跟踪器

4

8 回答 8

33

如果您使用 xUnit.net 1.x,您之前可能已经将输出写入控制台、调试或跟踪。当 xUnit.net v2 默认开启并行化时,这种输出捕获机制不再适用;不可能知道可以并行运行的许多测试中的哪些负责写入这些共享资源。将代码从 v1.x 移植到 v2.x 的用户应该改用这两种新方法之一。

在这里查看如何使用 xUnit.net v2 执行日志记录的示例:

http://xunit.github.io/docs/capturing-output.html

这是一个例子:

using Xunit;
using Xunit.Abstractions;

public class MyTestClass
{
    private readonly ITestOutputHelper output;

    public MyTestClass(ITestOutputHelper output)
    {
        this.output = output;
    }

    [Fact]
    public void MyTest()
    {
        var temp = "my class!";
        output.WriteLine("This is output from {0}", temp);
    }
}
于 2015-07-08T12:15:48.310 回答
7

对于 NUnit 这有效:

Console.SetOut(TestContext.Progress);

**迟到的答案是因为我有同样的问题,我刚刚解决了。可以帮助别人

于 2019-02-03T14:31:40.083 回答
6

ReSharper 以某种方式删除了单元测试中的默认侦听器。要在输出窗口中显示文本,只需添加以下行:

Debug.Listeners.Add(new DefaultTraceListener());
于 2014-11-13T09:46:04.633 回答
2

XunitLogger用于AsyncLocal<T>跟踪日志记录上下文,因此调用Trace.WritelineConsole.Writeline可以路由到ITestOutputHelper.

用法:

static class ClassBeingTested
{
    public static void Method()
    {
        Trace.WriteLine("From Trace");
        Console.WriteLine("From Console");
        Console.Error.WriteLine("From Console Error");
    }
}

public class TestBaseSample  :
    XunitLoggingBase
{
    [Fact]
    public void Write_lines()
    {
        WriteLine("From Test");
        ClassBeingTested.Method();

        var logs = XunitLogger.Logs;

        Assert.Contains("From Test", logs);
        Assert.Contains("From Trace", logs);
        Assert.Contains("From Console", logs);
        Assert.Contains("From Console Error", logs);
    }

    public TestBaseSample(ITestOutputHelper output) :
        base(output)
    {
    }
}
于 2019-04-15T20:43:01.607 回答
1

在你问这个问题 8 年后,我对 NUnit 也有同样的问题。:-(

我很确定这是 Resharper 在某些时候默认实现的,因为我不记得我之前必须手动执行此操作。但有时,它停止了工作。

解决方案(对于 NUnit)是在 NUnit 单元测试的顶部添加这一行。

Console.SetOut(TestContext.Progress)

这会使您的所有(现有) Console.Out.WriteLine("") 直接输出到 Resharper Unit Test Runner 输出部分,同时执行单元测试。

于 2021-02-04T22:42:58.423 回答
0

我发现最简单的方法是利用 log4net 并创建一个控制台记录器。一路上,当你跑步时,你会调用 logger.Info("info here"); 或 log.Debug("这里的信息"); - 真的是你喜欢的日志记录级别 - 输出将显示在 Resharper 单元测试会话中。

在 Apache log4net 主页上阅读有关 log4net 框架的更多信息。配置示例也将非常宝贵。

于 2013-02-26T15:19:52.670 回答
0

您也可以考虑使用xunit.NLogwhich 是一种非常好且干净的方式来注入ITestOutputhelper您的 SUT。

http://www.tomdupont.net/2015/06/capture-xunit-test-output-with-nlog-and.html

于 2019-06-20T15:20:22.683 回答
0

因为Console.WriteLine,这是一种方法(可能有更好的方法,但这对我有用):

public class ConsoleOutputHelper : TextWriter, ITestOutputHelper
{
    private readonly ITestOutputHelper _helper;

    public ConsoleOutputHelper(ITestOutputHelper helper) => _helper = helper;

    public override void WriteLine(string? message)
    {
        try
        {
            _helper.WriteLine(message);
        }
        catch (InvalidOperationException ex) when (ex.Message.Contains("no currently active test"))
        {
        }
    }

    public override void WriteLine(string format, params object?[] args) => 
        _helper.WriteLine(format, args);

    public override Encoding Encoding => new UTF8Encoding();
}

...然后,在您的测试构造函数中:

public MyTests(ITestOutputHelper helper) => 
    Console.SetOut(new ConsoleOutputHelper(helper));

...然后,在您正在测试的代码中

Console.Out.WriteLine("Beginning something...");

更新

Trace.WriteLine在生产代码中可能更好。

设置看起来像这样(需要添加和删除跟踪侦听器):

public class MyTests : IDisposable
{
    private readonly TraceOutputHelper _traceOutputHelper;

    public MyTests(ITestOutputHelper helper)
    {
        _traceOutputHelper = new TraceOutputHelper(helper);
        Trace.Listeners.Add(_traceOutputHelper);
    }

    public void Dispose() => Trace.Listeners.Remove(_traceOutputHelper);

...并且与上面TraceOutputHelper非常相似ConsoleOutputHelper

public class TraceOutputHelper : TextWriterTraceListener, ITestOutputHelper
{
    private readonly ITestOutputHelper _helper;

    public TraceOutputHelper(ITestOutputHelper helper) => _helper = helper;

    public override void WriteLine(string? message)
        => _helper.WriteLine(message);

    public void WriteLine(string format, params object[] args) => _helper.WriteLine(format, args);
}
于 2021-12-18T07:19:41.120 回答