183

我在 Visual Studio 中有一个测试项目。我使用Microsoft.VisualStudio.TestTools.UnitTesting

我在我的一个单元测试中添加了这一行:

Console.WriteLine("Some foo was very angry with boo");
Console.ReadLine();

当我运行测试时,测试通过了,但控制台窗口根本没有打开。

有没有办法让控制台窗口可以通过单元测试进行交互?

4

12 回答 12

204

有人评论了 Visual Studio 2013 中这个明显的新功能。起初我不确定他的意思,但现在我知道了,我认为它应该得到自己的答案。

我们可以正常使用 Console.WriteLine 并显示输出,只是不在输出窗口中,而是在测试详情中单击“输出”后在新窗口中显示。

在此处输入图像描述

于 2016-07-14T14:15:34.617 回答
139

注意:下面的原始答案应该适用于从 Visual Studio 2012 开始的任何版本的 Visual Studio。Visual Studio 2013 似乎不再有测试结果窗口。相反,如果您需要特定于测试的输出,您可以使用@Stretch 的建议Trace.Write()将输出写入输出窗口。


Console.Write方法不写入“控制台”——它写入连接到正在运行进程的标准输出句柄的任何内容。同样,Console.Read从连接到标准输入的任何内容中读取输入。

通过 Visual Studio 2010 运行单元测试时,标准输出由测试工具重定向并存储为测试输出的一部分。您可以通过右键单击“测试结果”窗口并将名为“Output (StdOut)”的列添加到显示中来看到这一点。这将显示写入标准输出的任何内容。

可以使用P/Invoke手动打开控制台窗口,如sinni800 所说。通过阅读AllocConsole文档,该函数似乎将重置stdinstdout处理以指向新的控制台窗口。(我对此不是 100% 确定;如果我已经重定向stdout到 Windows 以从我这里窃取它,这对我来说似乎有点错误,但我没有尝试过。)

不过,总的来说,我认为这是一个坏主意。如果您只想使用控制台转储有关单元测试的更多信息,那么输出就在那里。继续使用Console.WriteLine您的方式,并在完成后检查“测试结果”窗口中的输出结果。

于 2012-06-26T14:39:18.993 回答
48

您可以使用此行写入Visual Studio 的输出窗口

System.Diagnostics.Debug.WriteLine("Matrix has you...");

必须在调试模式下运行。

于 2012-06-26T16:55:50.573 回答
31

如前所述,单元测试旨在无需交互即可运行。

但是,您可以调试单元测试,就像任何其他代码一样。最简单的方法是使用Debug“测试结果”选项卡中的按钮。

能够调试意味着能够使用断点。因此,能够使用断点意味着能够使用Tracepoints,我发现它在日常调试中非常有用。

本质上,跟踪点允许您写入输出窗口(或更准确地说,写入标准输出)。或者,您可以继续运行,也可以像常规断点一样停止。这为您提供了您所要求的“功能”,而无需重新构建代码或用调试信息填充它。

只需添加一个断点,然后右键单击该断点。选择“当命中...”选项:

点击选项时

这带来了对话框:

遇到断点时

需要注意的几点:

  1. 请注意,断点现在显示为菱形,而不是球体,表示跟踪点
  2. 您可以通过像 {this} 一样将其括起来来输出变量的值。
  3. 取消选中“继续执行”复选框以在此行中断代码,就像任何常规断点一样
  4. 您可以选择运行宏。请小心 - 你可能会导致有害的副作用。

有关更多详细信息,请参阅文档。

于 2012-06-26T15:03:27.903 回答
26

有几种方法可以在 C# 中编写 Visual Studio 单元测试的输出:

  • Console.Write - 当您在测试资源管理器中选择测试并单击输出链接时,Visual Studio 测试工具将捕获并显示它。在运行或调试单元测试时不会显示在 Visual Studio 输出窗口中(可以说这是一个错误)
  • Debug.Write - Visual Studio 测试工具将捕获此内容并将其显示在测试输出中。调试单元测试时会出现在 Visual Studio 输出窗口中,除非将 Visual Studio 调试选项配置为将输出重定向到即时窗口。如果您只是在没有调试的情况下运行测试,则输出(或立即)窗口中不会出现任何内容。默认情况下,仅在 Debug 构建中可用(即定义 DEBUG 常量时)。
  • Trace.Write - Visual Studio 测试工具将捕获此内容并将其显示在测试输出中。调试单元测试时会出现在 Visual Studio 输出(或立即)窗口中(但在没有调试的情况下仅运行测试时不会出现)默认情况下在 Debug 和 Release 版本中都可用(即,在定义 TRACE 常量时)。

在 Visual Studio 2013 Professional 中确认。

于 2016-03-08T19:33:14.153 回答
14

您可以使用

Trace.WriteLine()

在调试单元测试时写入输出窗口。

于 2014-03-25T16:22:15.847 回答
7

在 Visual Studio 2017 中,“TestContext”不会在测试资源管理器中显示输出链接。

但是, Trace.Writeline() 显示输出链接。

于 2017-07-13T15:31:50.673 回答
4

首先,根据设计,单元测试应该在没有交互的情况下完全运行。

除此之外,我认为没有考虑过这种可能性。

您可以尝试使用AllocConsole P/Invoke进行破解,即使您当前的应用程序是 GUI 应用程序,它也会打开一个控制台。然后该Console课程将发布到现在打开的控制台。

于 2012-06-26T14:34:54.823 回答
3

Debug.WriteLine() 也可以使用。

于 2014-08-21T07:23:35.903 回答
2

恕我直言,在大多数情况下,输出消息仅与失败的测试用例相关。我制作了以下格式,您也可以自己制作。这显示在 Visual Studio 测试资源管理器窗口本身中。

我们如何在 Visual Studio 测试资源管理器窗口中抛出此消息?

像这样的示例代码应该可以工作:

if(test_condition_fails)
    Assert.Fail(@"Test Type: Positive/Negative.
                Mock Properties: someclass.propertyOne: True
                someclass.propertyTwo: True
                Test Properties: someclass.testPropertyOne: True
                someclass.testPropertyOne: False
                Reason for Failure: The Mail was not sent on Success Task completion.");

您可以为您专门开设一个单独的课程。

于 2018-12-10T19:57:57.977 回答
1

我有一个更简单的解决方案(出于许多懒惰的原因,我最近使用了自己)。将此方法添加到您正在使用的类中:

public static void DumbDebug(string message)
{
    File.WriteAllText(@"C:\AdHocConsole\" + message + ".txt", "this is really dumb. I wish Microsoft had more obvious solutions to its solutions problems.");
}

然后...打开目录 AdHocConsole,并按创建时间排序。确保在添加“打印声明”时。虽然它们是不同的,否则会有杂耍。

于 2020-06-16T21:11:52.373 回答
0

适用于 Mac 的 Visual Studio

其他解决方案均不适用于 Visual Studio for Mac

如果您使用的是NUnit,您可以将一个小型.NET 控制台项目添加到您的解决方案中,然后在该新控制台项目的引用中引用您希望测试的项目。

无论您在[Test()]方法中做什么,都可以在Main控制台应用程序中以这种方式完成:

class MainClass
{
    public static void Main(string[] args)
    {
        Console.WriteLine("Console");

        // Reproduce the unit test
        var classToTest = new ClassToTest();
        var expected = 42;
        var actual = classToTest.MeaningOfLife();
        Console.WriteLine($"Pass: {expected.Equals(actual)}, expected={expected}, actual={actual}");
    }
}

在这些情况下,您可以自由使用Console.WriteConsole.WriteLine在您的代码中。

于 2018-07-02T23:34:33.037 回答