C# 单元测试 测试代码-优秀单元测试
二、优秀单元测试的支柱
要编写优秀的单元测试,它们应该同时具有 可靠性、可维护性 及 可读性。
2.1 编写可靠的测试
一个可靠的测试能让你觉得自己对事态了如指掌,能够从容应对。以下是一些指导原则和技术:
(1)决定何时删除或修改测试
一旦测试写好并通过,通常我们不应该修改或删除这些测试,因为它们是我们得绿色保护网。但是,有时候我们还是需要修改或者删除测试,所以需要理解什么情况下修改或删除测试会带来问题,什么情况下又是合理的。一般来说,如果有产品缺陷、测试缺陷、语义或者API更改或者是由于冲突或无效测试,我们需要修改和删除测试代码。
(2)避免测试中的逻辑
随着测试中逻辑的增多,出现测试缺陷的几率就会呈现指数倍的增长。如果单元测试中包含了下列语句就是包含了不应该有的逻辑:
- switch、if或else语句;
- foreach、for或while循环;
这种做法不值得推荐,因为这样的测试可读性较差,也比较脆弱。通常来说,一个单元测试应该是一系列方法的调用和断言,但是不包含控制流程语句,甚至不应该将断言语句放在try-catch中。
(3)只测试一个关注点
如果我们的单元测试对多个对象进行了断言,那么这个测试有可能测试了多个关注点。在一个单元测试中验证多个关注点会使得事情变得复杂,却没有什么价值。你应该在分开的、独立的单元测试中验证多余的关注点,这样才能发现真正失败的地方。
(4)把单元测试和集成测试分开
掐面讨论了测试的绿色安全区,我们需要的就是准备一个单独的单元测试项目,项目中仅包含那些在内存中运行,结果稳定,可重复执行的测试。
(5)用代码审查确保代码覆盖率
如果覆盖率低于20%,说明我们缺少很多测试,我们不会知道下一个开发人员将怎么修改我们得代码。如果没有回失败的测试,可能就不会发现这些错误。
2.2 编写可维护性的测试
可维护性是大多数开发者在编写单元测试时面对的核心问题之一。为此我们需要:
(1)只测试公共契约
(2)删除重复测试(去除重复代码)
(3)实施测试隔离
测试隔离的基本概念是:一个测试应该总是在它自己的小世界中运行,与其他类似或不同的工作的测试隔离,甚至不知道其他测试的存在。
2.3 编写可读性的测试
不可读的测试几乎没有任何意义,它是我们向项目的下一代开发者讲述的故事,帮助开发者理解一个应用程序的组成及其开端。
(1)单元测试命名
这个前面我们讨论过,应该包括三部分:被测试方法名_测试场景_预期行为,如果开发人员都是用这种规范,其他的开发人员就能很容易进入项目,理解测试。
(2)变量命名
通过合理命名变量,你可以确保阅读测试的人可以尽快地理解你要验证什么(相对于理解产品代码中你想要实现什么)。请看下面的一个例子:
[Test] public void BadlyNameTest() { LogAnalyzer log = new LogAnalyzer(); int result = log.GetLineCount("abc.txt"); Assert.AreEqual(-100, result); } [Test] public void GoodNameTest() { LogAnalyzer log = new LogAnalyzer(); int result = log.GetLineCount("abc.txt"); const int COULD_NOT_READ_FILE = -100; Assert.AreEqual(-COULD_NOT_READ_FILE, result); }
经过改进后,我们会很容易理解这个返回值的意义。
(3)有意义的断言
只有当测试确实需要,并且找不到别的办法使测试更清晰时,你才应该编写定制的断言信息。编写好的断言信息就像编写好的异常信息,一不小心就会犯错,使读者产生误解,浪费他们的时间。
(4)断言和操作分离
为了可读性,请不要把断言和方法调用写在同一行。
// 断言和操作写在了同一行 Assert.AreEqual(-COULD_NOT_READ_FILE, log.GetLineCount("abc.txt"));
出处:http://edisonchou.cnblogs.com