使用 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.WriteLines
、Trace.WriteLine
和Console.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.Writeline
和Console.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,如何在长时间运行的单元测试期间显示调试输出?的主要内容,如果未能解决你的问题,请参考以下文章
使用 yeoman 的 ReSharper Jasmine AngularJS 单元测试