使用 ReSharper,如何在长时间运行的单元测试期间显示调试输出?

Posted

技术标签:

【中文标题】使用 ReSharper,如何在长时间运行的单元测试期间显示调试输出?【英文标题】:Using ReSharper, how to show debug output during a long-running unit test? 【发布时间】:2013-02-12 02:24:02 【问题描述】:

我将 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 issue tracker。

【问题讨论】:

当我处于调试模式时,Debug.WriteLine() 对我来说工作得很好。因此,如果您想以一般方式登录,我建议您使用 brenton's answer @derape - 不,它不适用于 xunit。在测试完成之前不会出现任何输出。 我明白了,我没有玩过 XUnit - 只有 NUnit。 NUnit 日志记录确实在调试线程中工作...... 是的,NUnit 确实可以解决这个问题。查看我的更新。 【参考方案1】:

如果您使用 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);
    

【讨论】:

这正是我想要的。谢谢! 这对于在测试中编写输出很有用,但是当您需要从测试调用的代码中实时输出信息时,您必须修改被测试的代码以传递并利用 @ 987654323@。我理解并发问题使得处理代码输出变得困难,我只是想向其他人指出这个解决方案确实有一个限制。利用跟踪侦听器或劫持Debug.Write* 方法的默认输出流之类的东西会很好。【参考方案2】:

对于 NUnit,这是可行的:

Console.SetOut(TestContext.Progress);

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

【讨论】:

这对我来说不适用于 .net core linux + nunit 3.11 感谢更新。抱歉,没有尝试修复它的环境。【参考方案3】:

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

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

【讨论】:

这对我不起作用,在单元测试会话窗口或输出窗口(使用 MSTest)中。【参考方案4】:

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)
    
    

【讨论】:

【参考方案5】:

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

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

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

Console.SetOut(TestContext.Progress)

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

【讨论】:

【参考方案6】:

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

阅读更多关于 log4net 框架的信息on the Apache log4net homepage。 configuration examples 也将非常宝贵。

【讨论】:

不。添加了 log4net,这些消息甚至根本没有进入单元测试输出。我使用了一个简单的控制台附加程序——示例中的附加程序。【参考方案7】:

您也可以考虑使用xunit.NLog,这是一种将ITestOutputhelper 注入您的SUT 的非常好且干净的方法。

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

【讨论】:

【参考方案8】:

对于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);

【讨论】:

以上是关于使用 ReSharper,如何在长时间运行的单元测试期间显示调试输出?的主要内容,如果未能解决你的问题,请参考以下文章

Resharper 单元测试未运行

使用 yeoman 的 ReSharper Jasmine AngularJS 单元测试

如何找到长时间运行的查询?

jmeter长时间压测

如何使用在后端执行的长时间运行的 C/C++ 代码杀死 python 解释器?

如何使用 .Net 库管理对 Snowflake 的长时间运行过程调用