测试驱动开发(Test Driven Development,简称TDD)是一种软件开发方法,它强调先编写测试用例,再编写能够通过这些测试用例的代码。本文以一个简单的阶乘计算器应用为例,介绍TDD的基本概念和实践方法。
最初接触测试驱动开发时,认为这是一种不必要的做法。但随着对TDD的深入了解,发现它能有效预防错误和问题,提高代码的可靠性,并能显示代码覆盖率。这些优势促使开始尝试TDD。
在编写代码之前,需要确定应用程序的需求。本文将开发一个阶乘计算器,因此需要确定阶乘的需求,并据此确定测试方法。当然,也可以直接开始编写测试,跳过这些步骤,但事先规划是值得的。
阶乘计算器的核心需求是计算一个非负整数n的所有小于或等于n的正整数的乘积。
以下是几个基本的测试用例:
首先,创建一个名为FactorialApplication
的解决方案,并在其中添加一个名为FactorialCalculatorTests
的测试项目和一个名为FactorialCalculator
的类库。
测试1:0的阶乘是1
[TestMethod]
public void ZeroFactorialIsOne()
{
Factorial calculator = new Factorial();
float result = calculator.GetFactorialOf(0);
Assert.AreEqual(1, result);
}
在上述代码中,创建了一个名为calculator
的对象,并调用了GetFactorialOf(0)
方法。但此时Factorial
类中还没有这个方法,因此会有很多红色波浪线提示错误。
Factorial
类接下来,需要创建Factorial
类,并实现GetFactorialOf
方法。
public class Factorial
{
public float GetFactorialOf(int p)
{
throw new NotImplementedException();
}
}
现在,可以尝试运行测试方法,看看结果如何。
测试失败是因为创建了GetFactorialOf(int p)
方法,但没有实现它。现在需要进行最小的修改以通过测试。
public class Factorial
{
public float GetFactorialOf(int p)
{
return 1;
}
}
现在测试方法可以通过了,因为断言已经验证通过。
接下来,可以编写更多的测试方法,例如:
[TestMethod]
public void OneFactorialIsOne()
{
Factorial calculator = new Factorial();
float result = calculator.GetFactorialOf(1);
Assert.AreEqual(1, result);
}
这个测试方法也通过了,因为GetFactorialOf(int p)
方法仍然支持断言。
GetFactorialOf
方法随着测试的进行,需要逐步完善GetFactorialOf
方法,以确保所有测试都能通过。
public class Factorial
{
public float GetFactorialOf(int p)
{
if (p < 2)
return 1;
return p * GetFactorialOf(p - 1);
}
}
现在,已经完成了阶乘计算器的基本功能。
TDD最令人印象深刻的一点是,最初没有代码,随着测试方法的编写,所需的代码自动生成。不需要规划类,不需要规划变量等。只实现需求规范中需要的内容。一切都在测试期间确定。
另一个要点是,任何测试都不应影响其他测试。方法的实现不应影响测试结果。例如,如果一个方法对一个测试正确,但对其他测试错误,那么这是一个不希望的结果。