我在Visual Studio中有一个测试项目。我使用Microsoft.VisualStudio.TestTools.UnitTesting。
我在我的一个单元测试中添加了这一行:
Console.WriteLine("Some foo was very angry with boo");
Console.ReadLine();
当我运行测试时,测试通过,但控制台窗口根本没有打开。
有没有办法让控制台窗口可以通过单元测试进行交互?
答案 0 :(得分:142)
有人在VS2013中评论了这个显然是新的功能。我一开始并不确定他的意思,但现在我知道,我认为它应该得到自己的答案。
我们可以正常使用Console.WriteLine并显示输出,但不是在输出窗口中,而是在我们点击"输出"之后在新窗口中显示。在测试细节中。
答案 1 :(得分:109)
注意:以下原始答案适用于通过VS2012的任何版本的VS. VS2013似乎不再具有“测试结果”窗口。相反,如果您需要特定于测试的输出,可以使用@ Stretch的Trace.Write()
建议将输出写入“输出”窗口。
Console.Write
方法不会写入“控制台” - 它会写入连接到正在运行的进程的标准输出句柄的任何内容。类似地,Console.Read
从连接到标准输入的任何内容读取输入。
当您通过VS2010运行单元测试时,标准输出将被测试工具重定向并存储为测试输出的一部分。您可以通过右键单击“测试结果”窗口并将名为“输出(StdOut)”的列添加到显示中来查看。这将显示写入stdout的任何内容。
你可以手动打开一个控制台窗口,使用P / Invoke,如@ sinni800所说。通过阅读AllocConsole
文档,该函数似乎将重置stdin
和stdout
句柄以指向新的控制台窗口。 (我不是百分百肯定的;如果我已经重定向stdout
用于从我那里窃取它,我似乎有点不对,但我还没有尝试过。)
总的来说,我认为这是一个坏主意;如果您只想使用控制台来转储有关单元测试的更多信息,那么输出就在那里。继续使用Console.WriteLine
,并在完成后在“测试结果”窗口中检查输出结果。
答案 2 :(得分:30)
您可以使用此行写入Visual Studio的Output Window:
System.Diagnostics.Debug.WriteLine("Matrix has you...");
希望有所帮助
答案 3 :(得分:27)
如上所述,单元测试旨在无需交互即可运行。
但是,您可以调试单元测试,就像任何其他代码一样。最简单的方法是使用“测试结果”选项卡中的“调试”按钮。
能够调试意味着能够使用断点。因此,能够使用断点意味着能够使用 Tracepoints ,这在我每天调试中都非常有用。
基本上,Tracepoints允许您写入“输出”窗口(或更准确地说,写入标准输出)。 (可选)您可以继续运行,也可以像常规断点一样停止运行。这为您提供了"功能"您要求的,无需重建代码,或填写调试信息。
只需添加断点,然后右键单击该断点即可。选择"何时击中..."选项:
这会打开对话框:
有几点需要注意:
有关详细信息,请参阅文档。
答案 4 :(得分:6)
您可以使用
Trace.WriteLine()
在调试unittest时写入Output窗口。
答案 5 :(得分:4)
在Visual Studio 2017中," TestContext"没有显示输出链接到测试资源管理器。 但是,Trace.Writeline()显示了输出链接。
答案 6 :(得分:3)
首先,单元测试是通过设计,完全没有交互运行。
除此之外,我认为没有人想到这种可能性。
您可以尝试使用AllocConsole P/Invoke进行攻击,即使您当前的应用程序是GUI应用程序,也会打开控制台。然后Console
类将发布到现在打开的控制台。
答案 7 :(得分:3)
也可以使用Debug.WriteLine()。
答案 8 :(得分:2)
这不是一个解决方案,而是来自书中的方法
Roy Osherove的单元测试艺术
我们需要存根来破坏这些依赖关系,比如写入FileSystem或写入事件日志或写入控制台 -
Stub可以传入Main Class,如果stub不为null,则写入Stub。但是它可以改变api(就像现在构造函数有一个stub作为参数)。另一种方法是继承和创建Mock对象。如下所述。
namespace ClassLibrary1
{
// TO BE TESTED
public class MyBusinessClass
{
ConsoleStub myConsoleForTest;
public MyBusinessClass()
{
// Constructor
}
// This is test stub approach - 2
public MyBusinessClass(ConsoleStub console)
{
this.myConsoleForTest = console;
}
public virtual void MyBusinessMethod(string s)
{
// this needs to be unit tested
Console.WriteLine(s);
// Just an example - you need to be creative here
// there are many ways
if (myConsoleForTest !=null){
myConsoleForTest.WriteLine(s);
}
}
}
public class ConsoleStub
{
private string textToBeWrittenInConsole;
public string GetLastTextWrittenInConsole
{
get
{
return this.textToBeWrittenInConsole;
}
}
public void WriteLine(string text)
{
this.textToBeWrittenInConsole = text;
}
}
public class MyBusinessClassMock :MyBusinessClass
{
private ConsoleStub consoleStub;
public MyBusinessClassMock()
{
// Constructor
}
public MyBusinessClassMock(ConsoleStub stub)
{
this.consoleStub = stub;
}
public override void MyBusinessMethod(string s)
{
// if MOCK is not an option then pass this stub
// as property or parameter in constructor
// if you do not want to change the api still want
// to pass in main class then , make it protected and
// then inherit it and make just a property for consoleStub
base.MyBusinessMethod(s);
this.consoleStub.WriteLine(s);
}
}
[TestClass]
public class ConsoleTest
{
private ConsoleStub consoleStub;
private MyBusinessClassMock mybusinessObj
[TestInitialize]
public void Initialize()
{
consoleStub = new ConsoleStub();
mybusinessObj = new MyBusinessClassMock(consoleStub);
}
[TestMethod]
public void TestMyBusinessMethod()
{
mybusinessObj.MyBusinessMethod("hello world");
Assert.AreEqual(this.consoleStub.GetLastTextWrittenInConsole,"hello world" );
}
}
}
// Approach - 2
[TestClass]
public class ConsoleTest
{
private ConsoleStub consoleStub;
private MyBusinessClass mybusinessObj
[TestInitialize]
public void Initialize()
{
consoleStub = new ConsoleStub();
mybusinessObj = new MyBusinessClass(consoleStub);
}
[TestMethod]
public void TestMyBusinessMethod()
{
mybusinessObj.MyBusinessMethod("hello world");
Assert.AreEqual(this.consoleStub.GetLastTextWrittenInConsole,"hello world" );
}
}
答案 9 :(得分:2)
在大多数情况下,IMHO输出消息仅与失败的测试用例相关。我编造了以下格式,您也可以自己制作。这显示在VS Test Explorer窗口本身中。
如何在VS Test Explorer窗口中抛出此消息? 这样的示例代码应该可以工作。
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.");
您可以为此设置一个单独的班级。希望对您有帮助!
答案 10 :(得分:1)
其他解决方案均未在Mac上的VS上运行
如果您使用的是 NUnit ,则可以在解决方案中添加一个小型.NET
控制台项目,然后在<该新 Console Project 的strong>参考。
您在[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.Write
和Console.WriteLine
。
答案 11 :(得分: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,并按创建时间排序。确保在添加“打印报表”时。尽管它们是截然不同的,否则会杂耍。