建议155:随生产代码一起提交单元测试代码

首先提出一个问题:我们害怕修改代码吗?是否曾经无数次面对乱糟糟的代码,下决心进行重构,然后在一个月后的某个周一,却收到来自测试版的报告:新的版本,没有之前的版本稳定,性能也更差了,Bug似乎也变多了。也就是说,重构的代码看上去质量更高了,可实际测试结果却不如人意。

几乎每个程序员都因为此类问题纠结过。我们要修改的代码也许来自某些不负责任或经验欠佳的程序员,也许这些代码是自己一年前写的,但是看上去已经惨不忍睹。我们想要修改这些代码,却担心重构出别的问题。即便是一个开发周期中的产品,也会有这样的选择出现。某个模块可能已经提交测试并确认通过,不过现在发现有更优的算法和逻辑,改还是不改,成了一个问题。

“单元测试”减轻甚至消除了开发者这种恐惧。如果项目没有测试代码,说明我们只是生产“定时炸弹”。很多人将生产代码和测试代码分别对待,这是一种过时的做法。程序员在提交自己的生产代码时,必须同时提交自己的单元测试代码。很多现代化的版本管理工具可以在后台订制项目构建计划,自动运行测试项目,统计代码覆盖率,并生成相应报告。我们应该在早上一边喝咖啡,一边读取这样的报告。

有了测试代码做保证,在很大程度上我们可以放心去重构了。如果某个功能偏离了既有成果,就会有醒目的提醒。

将单元测试放在首要地位的一种开发模式是TDD模式。TDD(Test Driven Development测试驱动开发)有三条严格的定律:

  • 在编写不能通过测试的单元测试前,不要编写任何生产代码。
  • 只编写恰好无法通过的单元测试,不能编译也算不通过。
  • 只编写刚好足以通过当前失败测试的生产代码。

即使我们的团队没有完全采用TDD的开发模式,也可以借鉴这些定律来编写我们自己的测试代码。我们无需一次性编写完全部的测试代码,那没有必要,这跟过度设计一样,也不可能实现。事实上,我们应该逐步地编写测试代码,而且按如下步骤来编写:

测试代码->生产代码->测试代码

下面编写一个单元测试的例子:

先编写一个Add方法:

    public class SampleClass
{
public int Add(int a, int b)
{
return a + b;
}
}

右键创建单元测试:

VS会自动为我们生成一个测试方法:

        /// <summary>
///Add 的测试
///</summary>
[TestMethod()]
public void AddTest()
{
SampleClass target = new SampleClass(); // TODO: 初始化为适当的值
int a = ; // TODO: 初始化为适当的值
int b = ; // TODO: 初始化为适当的值
int expected = ; // TODO: 初始化为适当的值
int actual;
actual = target.Add(a, b);
Assert.AreEqual(expected, actual);
Assert.Inconclusive("验证此测试方法的正确性。");
}

将方法修改成我们需要的方法就可以了:

        /// <summary>
///Add 的测试
///</summary>
[TestMethod()]
public void AddTest()
{
SampleClass target = new SampleClass(); // TODO: 初始化为适当的值
int a = 1; // TODO: 初始化为适当的值
int b = 2; // TODO: 初始化为适当的值
int expected = 3; // TODO: 初始化为适当的值
int actual;
actual = target.Add(a, b);
Assert.AreEqual(expected, actual);
Assert.Inconclusive("验证此测试方法的正确性。");
}

VS这个可视化测试工具太重量级了,导致开发的过程中运行测试代码太繁琐也太耗时。可以考虑用测试工具TestDriven.NET,这里不再介绍。

单元测试要注意一下几点:

首先,单元测试不应引入任何人机交互的内容。如,测试过程中不应该弹出对话框,等待用户输入或确认。单元测试不应该是被阻滞的。

其次,多线程也不属于单元测试范畴,单元测试应该是快速被执行的,而不是需要等待的。

最后,单元测试不应该跨应用程序域,例如,数据访问或者远程通信属于集成测试范畴,而不是单元测试。

转自:《编写高质量代码改善C#程序的157个建议》陆敏技

编写高质量代码改善C#程序的157个建议——建议155:随生产代码一起提交单元测试代码的更多相关文章

  1. 编写高质量代码改善C#程序的157个建议[1-3]

    原文:编写高质量代码改善C#程序的157个建议[1-3] 前言 本文主要来学习记录前三个建议. 建议1.正确操作字符串 建议2.使用默认转型方法 建议3.区别对待强制转换与as和is 其中有很多需要理 ...

  2. 读书--编写高质量代码 改善C#程序的157个建议

    最近读了陆敏技写的一本书<<编写高质量代码  改善C#程序的157个建议>>书写的很好.我还看了他的博客http://www.cnblogs.com/luminji . 前面部 ...

  3. 编写高质量代码改善C#程序的157个建议——建议157:从写第一个界面开始,就进行自动化测试

    建议157:从写第一个界面开始,就进行自动化测试 如果说单元测试是白盒测试,那么自动化测试就是黑盒测试.黑盒测试要求捕捉界面上的控件句柄,并对其进行编码,以达到模拟人工操作的目的.具体的自动化测试请学 ...

  4. 编写高质量代码改善C#程序的157个建议——建议156:利用特性为应用程序提供多个版本

    建议156:利用特性为应用程序提供多个版本 基于如下理由,需要为应用程序提供多个版本: 应用程序有体验版和完整功能版. 应用程序在迭代过程中需要屏蔽一些不成熟的功能. 假设我们的应用程序共有两类功能: ...

  5. 编写高质量代码改善C#程序的157个建议——建议154:不要过度设计,在敏捷中体会重构的乐趣

    建议154:不要过度设计,在敏捷中体会重构的乐趣 有时候,我们不得不随时更改软件的设计: 如果项目是针对某个大型机构的,不同级别的软件使用者,会提出不同的需求,或者随着关键岗位人员的更替,需求也会随个 ...

  6. 编写高质量代码改善C#程序的157个建议——建议153:若抛出异常,则必须要注释

    建议153:若抛出异常,则必须要注释 有一种必须加注释的场景,即使异常.如果API抛出异常,则必须给出注释.调用者必须通过注释才能知道如何处理那些专有的异常.通常,即便良好的命名也不可能告诉我们方法会 ...

  7. 编写高质量代码改善C#程序的157个建议——建议152:最少,甚至是不要注释

    建议152:最少,甚至是不要注释 以往,我们在代码中不写上几行注释,就会被认为是钟不负责任的态度.现在,这种观点正在改变.试想,如果我们所有的命名全部采用有意义的单词或词组,注释还有多少存在的价值. ...

  8. 编写高质量代码改善C#程序的157个建议——建议151:使用事件访问器替换公开的事件成员变量

    建议151:使用事件访问器替换公开的事件成员变量 事件访问器包含两部分内容:添加访问器和删除访问器.如果涉及公开的事件字段,应该始终使用事件访问器.代码如下所示: class SampleClass ...

  9. 编写高质量代码改善C#程序的157个建议——建议150:使用匿名方法、Lambda表达式代替方法

    建议150:使用匿名方法.Lambda表达式代替方法 方法体如果过小(如小于3行),专门为此定义一个方法就会显得过于繁琐.比如: static void SampeMethod() { List< ...

随机推荐

  1. 十六.jQuery源码解析之Sizzle设计思路.htm

    为了便于后面的叙述,需要了解一些相关术语和约定. 并列选择器表达式:"div,p,a"====>div,p,a是并列的. 块表达式:"div>p"中 ...

  2. 卷积神经网络之VGG网络模型学习

    VGG:VERY DEEP CONVOLUTIONAL NETWORKS FOR LARGE-SCALE IMAGE RECOGNITION 牛津大学 visual geometry group(VG ...

  3. 【UVA】1594 Ducci Sequence(纯模拟)

    题目 题目     分析 真的快疯了,中午交了一题WA了好久,最后发现最后一个数据不能加\n,于是这次学乖了,最后一组不输出\n,于是WA了好几发,最后从Udebug发现最后一组是要输出的!!!   ...

  4. PHP mysql client封装

    config1.inc.php $CONFIG_DATABASE_TXL = array( #array('127.0.0.1', 'root', '', 'he_txl','3306') array ...

  5. mysql和php的内存问题

    最近给一个客户把他以前的数据转换到PHPSMC里去,因为他的数据太大出现一些问题,首先出现的是php内存问题,刚导时空白,我就在该也面的头部加上 error_reporting(E_ALL);打印所有 ...

  6. Django timezone问题

    今天用django做个blog碰到了问题,提交内容后浏览提示Database returned an invalid value in QuerySet.datetimes(). Are time z ...

  7. Java安全框架 Apache Shiro学习-1-ini 配置

    简单登录流程: 1.  SecurityManager   2.  SecurityUtils.setSecurityManager 3.  SecurityUtils.getSubject     ...

  8. VS Code 在新Tabs打开文件

    添加如下设置即可 "workbench.editor.enablePreview": false

  9. iOS开发基础控件--UIButton

    01 //这里创建一个圆角矩形的按钮 02     UIButton *button1 = [UIButton buttonWithType:UIButtonTypeRoundedRect]; 03 ...

  10. href 和src 的区别

    转载地址:http://www.58maisui.com/2016/08/03/30/?utm_source=tuicool&utm_medium=referral href和src的区别: ...