你应该在单元测试运行时显示正在发生的事情吗?

时间:2008-10-06 17:34:47

标签: unit-testing

当我编写单元测试代码时,我倾向于发现插入以下行:

Console.WriteLine("Starting InteropApplication, with runInBackground set to true...");
try
{
    InteropApplication application = new InteropApplication(true);
    application.Start();
    Console.WriteLine("Application started correctly");
}
catch(Exception e)
{
    Assert.Fail(string.Format("InteropApplication failed to start: {0}", e.ToString()));
}

//test code continues ...

我的所有测试都是完全相同的。他们正在显示他们失败原因的信息,或者他们正在显示他们正在做什么的信息。我还没有任何正式的方法来说明单元测试应该如何编码。他们应该显示他们在做什么的信息吗?或者测试应该是静默的,并且根本不显示任何信息,只显示失败消息?

注意:语言是C#,但我不关心语言特定的答案。

16 个答案:

答案 0 :(得分:4)

我不确定你为什么会这样做 - 如果你的单元测试得名,你已经知道它在做什么了。如果失败,您就知道哪个测试失败(以及断言失败)。如果它没有失败,你就会知道它成功了。

这似乎是完全主观的,但对我而言,这似乎是完全冗余的信息,只会增加噪音。

答案 1 :(得分:2)

我个人建议您只输出错误,并输出运行测试次数和传递次数的摘要。这是一个完全主观的观点。展示适合您需求的产品。

答案 2 :(得分:2)

我建议反对它 - 我认为单元测试应该适用于Unix工具理念 - 当事情进展顺利时不要说任何事情。 我发现构建测试以在失败时提供有意义的信息是最好的 - 这样当你的工作正常时你可以得到很好的短输出,并且当出现问题时很容易看出出了什么问题 - 滚动失明不会丢失错误。

答案 3 :(得分:2)

我实际上会反对它(尽管不是激进的)。它将测试的用户界面与测试实现相结合(如果测试是通过GUI查看器运行的话)。作为替代方案,我建议使用以下方法之一:

  1. 我不熟悉NUnit,但是PyUnit允许您添加测试的描述,并且使用详细选项运行测试时,将打印描述。我会查看NUnit文档,看看这是否是你可以做的。
  2. 扩展您继承的TestCase类,以添加一个函数,您可以从该函数中记录测试尝试执行的操作。这样,不同的实现可以以不同的方式处理消息。

答案 4 :(得分:2)

我会说你应该输出任何适合你需要的东西,但是显示太多会稀释测试跑步者的输出 顺便说一句,您的示例代码看起来不像unit test,更像是集成/系统测试。

答案 5 :(得分:1)

我喜欢缓冲详细日志(约20行左右),但在出现错误之前我不显示它。当错误发生时,有一些上下文很好。

OTOH,单元测试应该是具有特定输入和输出要求的小块无关代码。在大多数情况下,显示导致错误的输入(即输出错误)足以将问题追溯到其根源。

答案 6 :(得分:1)

这可能有点过于特定于语言,但是当我编写NUnit测试时,我倾向于这样做,只是我使用System.Diagnostics.Trace库而不是控制台,这样信息只会在我显示时显示决定观看追踪。

答案 7 :(得分:1)

如果测试以静默方式运行,则不需要,这意味着没有错误。除了测试失败之外,通常没有理由进行测试以提供任何输出。如果它正在运行,那么它正在由测试运行器指示测试已通过,即它是“绿色”。通过IDE中的测试运行器运行测试(连同控制台输出的许多测试),您将使用无人关心的消息向控制台日志发送垃圾邮件。

您编写的测试不是单元测试,但看起来更像是集成/系统测试,因为您似乎正在运行整个应用程序。单元测试将测试类中的公共方法,最好使类尽可能隔离。

答案 8 :(得分:1)

使用控制台i / o有点无视单元测试框架的全部目的。你也可以手动编写整个测试代码。如果您使用的是单元测试框架,那么您的测试应该具有可塑性,与尽可能少的事情相关联

答案 9 :(得分:1)

显示信息非常有用;如果你试图找出测试失败的原因,那么能够看到的不仅仅是堆栈跟踪,以及在程序到达失败点之前发生了什么,这可能很有用。

然而,在一切都成功的“正常”情况下,这些消息是不必要的混乱,分散了你真正想做的事情 - 即。查看哪些测试成功并失败的概述。

我建议将调试消息重定向到日志文件。您可以通过编写所有日志消息代码来调用特殊的“日志打印”功能,或者如果您正在编写控制台程序,您应该能够将stdout重定向到另一个文件(我知道的事实是你可以在Unix和Windows上做到这一点)。通过这种方式,您可以获得高级概述,但如果您需要,则可以获得详细信息。

答案 10 :(得分:1)

我会避免在单元测试中添加额外的Try / Catch语句。首先,单元测试中的预期异常将导致测试失败。这是NUnit的默认行为。此外,测试工具已经使用该代码将每次调用包装到您的测试函数中。另外,通过使用e.ToString()来显示发生的事情,我相信你丢失了很多信息。默认情况下,我相信NUnit不仅会显示Exception类型,还会显示Call Stack,我不相信你会看到你的方法。

其次,有时候它是必要的。例如,您可以使用[ExpectedException]属性实际说明何时发生。只需确保在测试非异常相关的断言(例如断言列表计数> 0等)时,您将良好的描述作为断言的参数。这很有用。

通常不需要其他所有东西。如果您的单元测试如此之大,以至于您开始使用您正在进行的测试的“步骤”放入WriteLines,这通常表明您的测试应该真正分解为多个较小的测试。换句话说,您不是在进行单元测试,而是进行集成测试。

答案 11 :(得分:1)

您是否看过单元测试框架的xUnit样式? 请参阅Ron Jeffries网站以获取相当大的列表。

这些框架的原则之一是它们在测试运行期间产生很少或没有输出,并且实际上只是最终成功的指标。在失败的情况下,可以获得更具描述性的失败原因输出 这种模式的原因是,虽然一切都很好,但你不想被额外的输出困扰,当然如果出现故障,你也不想因为其他输出的噪音而错过它。

答案 12 :(得分:0)

嗯,你应该只知道测试何时失败以及失败的原因。知道发生了什么是没有用的,除非,例如,你有一个循环,你想知道测试在循环中的确切位置。

答案 13 :(得分:0)

我认为你为自己做了更多的工作。测试通过或失败,失败应该是规则的例外,你应该让单元测试运行器处理并抛出异常。你正在做的是添加cruft,测试运行器记录的异常会告诉你同样的事情。

答案 14 :(得分:0)

我唯一一次展示正在发生的事情是,如果有一些方面更容易非自动测试。例如,如果您的代码需要一段时间才能运行,并且可能会陷入无限循环,那么您可能希望每隔一段时间打印一条消息,以表明它仍在取得进展。

然而,始终确保故障信息在其他输出中明显突出。

答案 15 :(得分:0)

您可以像这样编写测试方法。这取决于你的代码鼻子你更喜欢哪种测试方式。我不想写额外的try-catch和Console.WriteLines。

public void TestApplicationStart()
{
  InteropApplication application = new InteropApplication(true);
  application.Start();
}

我使用的测试框架会将任何未处理(和意外)的异常解释为失败的测试。

考虑一下你参加此次考试所需的时间,以及你当时可以编写多少有意义的考试。