控制反转有助于提高程序的可测试性

控制反转,英文是Inversion of Control,简称IoC。这个概念在JAVA的Spring框架中比较常见,在.NET的开发中,Ioc或者其的变种依赖注入DI(Dependency Injection)是不太常见的。一般来说,类A要使用类B,类A会在其内部对类B进行控制,比较典型的做法就是在类A中创建一个类B的实例;而控制反转,就是把一个已经创建好的类B实例交给类A去控制。
例子:
Continue reading “控制反转有助于提高程序的可测试性”

自动化单元测试要点

用单元测试的框架MSTEST,做单元测试,集成测试快1年了,总结一下工作中学到都东西。

单元测试,集成测试有什么用?

1. 改进产品质量

软件测试,很多时候围绕着两个问题:

Verification和Validation,常说的双V。前面的Verification就是Is the software built correctly?。后面的Validation就是Have we built the right software?

单元测试,更多的是Verification。所以有时候经过我单元测试和集成测试以后的功能模块,在交给其他同事做功能测试的时候,依然会有一些BUG,这时候开发可能会埋怨我测试得不够完全,诸如此类。但是其实很多时候,我的关注点是单个方法的功能、行为,没有站到更高的位置来测试这个模块。对于这样的问题,开发和测试应该互相体谅,我本人也会提高自身的水平。希望在单元测试和集成测试中也加入更多关于Validation的思考。
Continue reading “自动化单元测试要点”

自动化白盒测试工具PEX应用实例 – 发现ZUNE死机的BUG

在12月的时候,我在博客里面介绍了一个自动化单元测试工具–PEX。在上一篇博客中,又讲述了微软ZUNE在闰年最后一天死机的原因。现在把这两篇文章串起来,跟大家分享一下如何用PEX帮助改善代码的质量。

首先来看一下用PEX测试ZUNE处理日期的方法的结果,如图:


Continue reading “自动化白盒测试工具PEX应用实例 – 发现ZUNE死机的BUG”

微软ZUNE死机原因–单元测试百分百语句覆盖率是不够的

微软的30GB版本Zune在08年的最后一天出现了大规模死机的现象,原因其实就是一行代码原本应该写为大于等于,但是实际上写成了大于。下面来看看具体的代码,第5行就是导致死机的代码。

while (days > 365)
{
	if (DateTime.IsLeapYear(year))
	{
		if (days > 366)
		{
			days -= 366;
			year += 1;
		}
	}
	else
	{
		days -= 365;
		year += 1;
	}
}

Continue reading “微软ZUNE死机原因–单元测试百分百语句覆盖率是不够的”

在ASP.NET单元测试中进行调试

在前一篇关于在单元测试中使用HttpContext的文章中,本人提到了用ASP.NET单元测试的一个缺点是不能调试,今天我推翻我自己错误的论调,其实在ASP.NET单元测试中也是能调试的。

以前我以为ASP.NET单元测试就运行于WEB服务器上,所以我用Debug来运行,那么ASP.NET单元测试就自动Attach到Web服务器,就能调试了。但是实际上要让ASP.NET单元测试可以调试的话,正确的做法应该是:

  1. 在Web.config中,找到<compilation debug=”false”/>这个节点,然后把debug属性改为true
  2. 在ASP.NET单元测试代码的最开始处添加这样一句话“System.Diagnostics.Debugger.Break()”
  3. 运行该ASP.NET单元测试

在运行单元测试的时候,会有一个提示框出来,说程序遇到一个断点,是否进入调试,当然是选择调试啦。如图:
Continue reading “在ASP.NET单元测试中进行调试”

单元测试中的常用测试模式

单元测试跟软件设计一样,有一些常用的模式,这篇文章是介绍一些常用的模式,其中的示例是C#代码,都比较简单,我想大家都能看懂。下面进入正题:

1. 准备,执行,断言(Arrange, Act, Assert)。这种模式是非常常见的,套用这种模式进行单元测试通常的做法如下:

  1. 准备测试环境,测试数据等
  2. 执行被测试方法
  3. 用断言来验证执行结果

下面是一段测试代码,被测方法的功能是把字符串中每个单词的首字母转为大写,特殊字符用下划线替代。
Continue reading “单元测试中的常用测试模式”

PEX-.NET自动化白盒测试工具的介绍(1)

PEX的全称是(Program EXploration),是一款在.NET下可应用的自动化白盒测试工具,来自于微软研究院。PEX通过分析代码来自动生成测试用例。对于程序里面的每一行代码,PEX都会尽可能地生成合适的输入值来达到提高覆盖率的目标。同时PEX还会分析代码中的分支,生成覆盖更多分支的测试代码(输入数据);PEX在执行代码的同时会监控和分析代码的控制流和数据流,了解程序的行为。每运行完单一个测试以后,PEX会选择一条在前面的测试中没有覆盖到的路径,并且尝试执行它。这一切都是约束求解算法来实现的,官方文档中提到的是一个叫Z3的约束求解器。因为PEX了解被测代码内部结构和行为,所以它不是一个简单地输入随机参数的黑盒测试工具。PEX不会尝试枚举所有可能的输入,事实上也不可能枚举完所有的可能输入。
Continue reading “PEX-.NET自动化白盒测试工具的介绍(1)”

在测试中使用正确的方法创建唯一的测试数据

在测试的过程中,我们经常需要创建一些唯一的值来进行测试,例如测试注册模块的时候,需要有唯一的邮件地址,那么什么样的方法才是正确地生成随机数,或者唯一数的好方法呢?我们下面来看看

很多语言的公共库都会有生成随机数的类,例如在C#里面我们或许可以这样子来生成一些随机的string。

string uniqeName = “MyTests” + DateTime.Now.ToString();//

用时间是个比较的选择,但是,如果是自动化脚本,那么会因为执行的速度太快,这有可能使得生成的string会有重复。
Continue reading “在测试中使用正确的方法创建唯一的测试数据”

单元测试的边界

这里说的边界不是说测试中常常看到的边界值,而是说明哪些事情应该是一个单元测试应该做的,哪些是单元测试不应该做的。
如果“单元测试”里面出现了以下的情况,那么它就不是一个单元测试应该做的

  • 需要跟数据库打交道
  • 访问了网络
  • 跟文件系统有交互
  • 它不能像你其他的单元测试那样运行
  • 你必须要经过一些特殊的配置才能使它运行起来

但是不是说如果测试代码里面包含以上行为就不是一个好的测试;相反,这些行为对于测试来说都是非常有意义的。但是,我们需要把这些测试和“真正的”单元测试区分开来,那些真正的单元测试可以“独立”地运行,而不会依赖于其他外部的组件。这样的单元测试才是真正的对被测软件的测试,而不是对数据库是否连同并且运行正常,或者是网络环境是否良好的检测。这就是所谓的“正交性”。

这样做的好处是,单元测试不需要访问数据库,这样测试运行的速度会更加快;使得单元测试更加健壮,因为它与其他系统之间的耦合度降低了!

在单元测试中应用数据驱动

作为自动化测试的一种脚本技术,数据驱动技术在10几年前已经有人提出,并且沿用到现在。Nunit作为C#开发下的一种常用的单元测试框架,也是被广泛使用。但是对于单元测试,很多时候都是硬编码,虽然说用Nunit编写单元测试代码是挺廉价的,但是为什么不让自己的工作更加轻松,脚本更加灵活呢?

我把单元测试的数据放到单独的XML文件里面,测试运行的时候就读取XML数据然后进行测试。由于我想做一个轻量级的单元测试,所以并没有把很多判断控制的语句写到一个单元测试里面,而是把有不同行为的测试写到一个脚本里面。例如期望结果都是成功的一类测试就写到一个脚本,包含同样错误的测试就写到另外一个脚本,尽管这样看起来并不是很高明,但是对于我的工作来说这是足够的了。
Continue reading “在单元测试中应用数据驱动”