代码之家  ›  专栏  ›  技术社区  ›  MagicKat

你应该在单元测试运行时显示它发生了什么吗?

  •  4
  • MagicKat  · 技术社区  · 16 年前

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

    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 回复  |  直到 16 年前
        1
  •  4
  •   Philip Rieck    16 年前

    我不知道你为什么要这么做-如果你的单元测试命名的很好,你已经知道它在做什么了。如果失败了,您就知道什么测试失败了(以及什么断言失败了)。如果它没有失败,你就知道它成功了。

    这似乎完全是主观的,但对我来说,这似乎是完全多余的信息,只是增加了噪音。

        2
  •  2
  •   David Arno    16 年前

    我个人建议您只输出错误以及运行的测试数和通过的测试数的摘要。不过,这是一个完全主观的观点。展示适合你需要的东西。

        3
  •  2
  •   Blair Conrad    16 年前

    我建议不要这样做-我认为单元测试应该遵循Unix工具的理念-事情进展顺利时不要说任何话。 我发现,构建测试以在失败时提供有意义的信息是最好的——这样,当工作正常时,您可以获得很短的输出,当出现问题时,很容易看到哪里出错了——错误不会因为滚动盲而丢失。

        4
  •  2
  •   Blair Conrad    16 年前

    我建议反对(虽然不是好战的)。它将测试的用户界面与测试实现相结合(如果测试是通过GUI查看器运行的呢?)。作为替代方案,我建议您选择以下选项之一:

    1. 我不熟悉NUnit,但是PyUnit允许您添加测试的描述,当使用verbose选项运行测试时,将打印描述。我会查一下修女的文件,看看你能不能做点什么。
    2. 扩展要继承的TestCase类,以添加一个函数,从该函数调用该函数来记录测试尝试执行的操作。这样,不同的实现可以以不同的方式处理消息。
        5
  •  2
  •   Sergey Volegov    16 年前

    我认为您应该输出任何适合您需要的内容,但是显示太多内容可能会稀释来自测试运行器的输出。
    顺便说一句,你的示例代码看起来不像 unit test ,更多的集成/系统测试。

        6
  •  1
  •   Milan BabuÅ¡kov    16 年前

    我喜欢缓冲详细的日志(大约最后20行左右),但直到出现错误时才会显示它。当错误发生时,最好有一些上下文。

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

        7
  •  1
  •   chills42    16 年前

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

        8
  •  1
  •   Spoike Otávio Décio    16 年前

    您不需要这样做,如果测试是静默运行的,那么这意味着没有错误。除了测试失败之外,测试通常没有理由给出任何输出。如果它正在运行,则它正在运行,由测试运行程序指示测试已通过,即它是“绿色”。通过IDE中的测试运行器运行测试(以及许多带有控制台输出的测试),您将在控制台日志中散布无人关心的消息。

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

        9
  •  1
  •   Midhat    16 年前

    使用控制台i/o有点违背了单元测试框架的全部目的。您不妨手动编写整个测试的代码。如果您使用的是单元测试框架,那么您的测试应该是可扩展的,与尽可能少的东西相关

        10
  •  1
  •   Simon Howard    16 年前

    显示信息可能很有用;如果您试图找出测试失败的原因,则可以看到的不仅仅是堆栈跟踪,还有在程序到达失败点之前发生的事情。

    然而,在一切都成功的“正常”情况下,这些消息是不必要的混乱,分散了您真正要做的事情的注意力——例如,查看哪些测试成功或失败的概述。

    我建议将调试消息重定向到日志文件。您可以通过编写所有日志消息代码来调用特殊的“日志打印”功能,或者如果您正在编写控制台程序,则应该能够将stdout重定向到其他文件(我知道您可以在Unix和Windows中都这样做)。这样,您就可以得到高层次的概述,但如果需要的话,细节就在那里。

        11
  •  1
  •   Nick    16 年前

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

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

    一般不需要其他任何东西。如果您的单元测试太大,以至于您开始在测试的“步骤”中输入writeline,这通常表明您的测试应该真正分解为多个较小的测试。换句话说,你不是在做一个单元测试,而是一个集成测试。

        12
  •  1
  •   quamrana Ryuzaki L    16 年前

    你看过单元测试框架的xUnit风格吗?
    Ron Jeffries 一个相当大的列表的网站。

    这些框架的一个原则是,它们在测试运行期间很少或根本不产生输出,并且在最后只是一个真正的成功指标。在失败的情况下,它有可能得到一个更具描述性的失败原因的输出。
    这种模式的原因是,虽然一切正常,你不想被额外的输出打扰,当然,如果有一个失败,你不想错过它,因为其他输出的噪音。

        13
  •  0
  •   dguaraglia    16 年前

    好吧,你应该只知道测试什么时候失败,为什么失败。知道发生了什么是没有用的,除非,举例来说,你有一个循环,你想知道测试在循环中的确切死在哪里。

        14
  •  0
  •   erlando    16 年前

    我认为你为自己做了更多的工作。测试要么通过要么失败,失败应该是规则的异常,您应该让单元测试运行器处理并抛出异常。您所做的是添加cruft,测试运行程序记录的异常将告诉您同样的事情。

        15
  •  0
  •   Illandril    16 年前

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

    但是,请始终确保故障消息明显地从其他输出中脱颖而出。

        16
  •  0
  •   Amy B    16 年前

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

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

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

    想想你花了多少时间准备这次测试,以及用这段时间你可以写多少更有意义的测试。