2

好的,我知道什么是单元测试,但我在某些项目中使用它,而不是在其他项目中使用它……有些客户不知道它是如何完成的,并遵循一个约定……等等。

所以我在这里问,单元测试过程是如何创建的?我听说并读到,您首先编写测试,然后编写功能并为该功能编写测试,并且还使用代码覆盖率来识别没有对尚未覆盖的代码进行测试的任何“失误”。

所以,让我们用一个简单的例子:

要求:“应用程序必须返回 2 个数字组合的结果。”

你我都知道我们会有一个类,比如“Addition”和一个返回整数的方法“Add”,如下所示:

public class Addition
{
   public int Add(int num1, int num2)
   {
      return num1 + num2;
   }
}

但即使在写这门课之前,你如何先写测试?你的流程是什么?你做什么工作?当您拥有该规范文档并进入开发阶段时,流程是什么?

非常感谢,

4

1 回答 1

5

您所指的过程称为测试驱动开发。想法很简单,和你描述的很接近;给定功能,您可以通过为此功能编写测试来开始编写代码。在您的添加示例中,编写任何工作代码之前,您应该有一个简单的测试 - 一个失败的测试。

未通过测试

[Test]
public void TestAdd()
{
     var testedClass = new Addition();

     var result = testedClass.Add(1, 2);

     Assert.AreEqual(result, 3);
}

这是对您的方法的一个简单测试.Add,说明您对即将发布的代码的期望。由于您还没有任何代码,因此该测试自然会失败(正如它应该的那样 - 这很好)。

通过测试

下一步是编写使测试通过的最基本的代码(当然,最基本的代码是return 3;,但对于这个简单的例子,这个级别的细节是不必要的):

public int Add(int num1, int num2)
{
    return num1 + num2;
}

这有效并且测试通过。您此时所拥有的基本证明,您的方法按照您在假设/期望(测试)中陈述的方式起作用。

但是,您可能会注意到这个测试不是一个好的测试。它只测试许多简单的输入数据。更不用说,在某些情况下,一个测试可能还不够,即使您有最初的需求,测试也可能表明还需要更多(例如参数验证或日志记录)。这是您返回审查需求和编写测试的部分,这导致我们...

重构

此时,您应该重构刚刚编写的代码。我说的是单元测试方法代码和测试实现。由于Add方法相当简单,并且在添加两个数字方面没有太多可以改进的地方,因此您可以专注于使测试更好。例如:

  • 添加更多测试用例(或考虑数据驱动测试)
  • 使测试名称更具描述性
  • 改进变量命名
  • 将幻数提取为常量

像这样:

[TestCase(0, 0, 0)]
[TestCase(1, 2, 3)]
[TestCase(1, 99, 100)]
public void Add_ReturnsSumOfTwoNumbers(int first, int second, int expectedSum)
{
     var testedClass = new Addition();

     var actualSum = testedClass.Add(first, second);

     Assert.That(actualSum, Is.EqualTo(expectedSum));
}

重构是值得一书的主题(而且有很多),所以我不会详细介绍。我们刚刚经历的过程通常被称为Red-Green-Refactor(红色表示测试失败,绿色 - 通过),它是 TDD 的一部分。请记住再次重新运行测试,以确保重构不会意外破坏任何内容。

这就是基本循环的方式。您从需求开始,为其编写失败的测试,编写代码以使测试通过,重构代码和测试,审查需求,继续下一个任务。

然后去哪儿?

一旦您了解了 TDD 背后的想法(即使从本文中提供的如此简短的解释中),很少有有用的资源可以很好地自然跟进:

于 2012-04-19T11:42:11.370 回答