进化的测试

关注软件测试,白盒测试,自动化测试,性能测试

Entries Tagged ‘白盒测试’

测试代码重构实例

Martin Fowler的《重构》这本书基本上每个程序员都会看,对于做单元测试的测试工程师来说,测试的代码本身也是程序,也需要重构。最近在看《XUnit Test Patterns》,把以前的做的东西重新梳理了一下,并且落实到新的项目中。
首先来看看一个最原始的单元测试代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
[TestMethod]
public void GetPaymentAccountByOwnerID()
{
int ownerId = 1300100000;
//Delete the account
TestHelper.DeletePaymentAccountByOwnerId(ownerId);
 
//Here should be create an account
PaymentAccount paymentAccount = PaymentGateway.PaymentProvider.GetPaymentAccountByOwnerID(ownerId, AccountOwnerType.NormalUser);
 
//Verify the payment account instance
Assert.IsTrue(paymentAccount.AccountID > 0);
Assert.AreEqual(DateTime.Now.DayOfYear, paymentAccount.CreateTime.DayOfYear);
Assert.AreEqual(DateTime.Now.DayOfYear, paymentAccount.UpdateTime.DayOfYear);
Assert.AreEqual(0, paymentAccount.Balance, 0.0001);
Assert.AreEqual(0, paymentAccount.AvailableBalance, 0.0001);
Assert.AreEqual(0, paymentAccount.FreezeAccount, 0.0001);
}

以上是个很简单的单元测试代码,应用了AAA原则,首先做好准备(删掉原有的数据),然后执行测试,最后再验证返回结果。看起来很好也很清晰。首先发现一个问题,就是那一堆Assert让人觉得迷惑,究竟想干啥?其实那6句Assert都是验证程序返回的PaymentAccount对象是是否符合设计。我把这些Assert语句提取出来,作为一个方法,让测试代码更加容易让人明白。也就有了版本2。

单元测试中三种准备Test Fixture的方法比较

首先说一下Test Fixture,我不知道怎么样翻译这个Test Fixture,没能搜到一个翻译的比较合适的。最让我气愤的是某人翻译的一本书中,直接把Test Fixture翻译成为测试夹具,这明显就是什么词霸词典硬翻译出来的,我强烈鄙视这样不负责任的翻译行为。
The test fixture is everything we need to have in place to exercise the SUT
我觉得这是一个对Test Fixture的一个很清晰明了的定义,就是运行被测软件所需要的一切东西,这个“东西”不单只是数据,同时还包括对被测软件的准备,例如实例化某个被测方法所在的类,准备数据库的ConnectionString等。通常来说,有三种方法来准备Test Fixture。
1. 内联方式:这种方式就是直接在测试方法中编写准备Test Fixture的代码。用这种方法的缺点是很容易造成代码的重复,出现很多复制粘贴的代码。同时,如果这个SETUP的过程比较复杂,也会降低测试代码的可读性,可维护性。另外的一个问题就是,这种方法很容易会带来测试数据Hard code的隐患。既然有那么多缺点,这种方法还有什么生命力呢?首先,可能对于初学者来说,这种方法是最简单的;其次,在一些只需要准备简单的Test Fixture的场合中,这种方法还是给编写测试的人提供了便利。

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

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

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

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

在C#单元测试中使用HttpContext的简单解决办法

场景:最近在测试一个.NET的Http Module,这个Module是用来做URL重写的。刚开始进展的比较顺利,因为该Module里面的方法参数基本上都是String,后来这个Module进行了一下重构,所有参数都变成了HttpContext了,这就直接导致原来的单元测试都跑不起来了,接着就开始了弄HttpContext了。
1. 采用Visual Studio自带的ASP.NET单元测试
刚开始我看了一下被测试的代码,虽然说用到了HttpContext,但是有很多地方我都可以绕过去的,意思就是这个HttpContext只是名以上需要的一个参数,只要它不是NULL就可以了,并不影响我的测试,所以我采用了ASP.NET Unit Test的办法来获取一个HttpContext,这个方法实现起来是最简单的,但是会有一些问题,后面会提及到。

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

单元测试跟软件设计一样,有一些常用的模式,这篇文章是介绍一些常用的模式,其中的示例是C#代码,都比较简单,我想大家都能看懂。下面进入正题:
1. 准备,执行,断言(Arrange, Act, Assert)。这种模式是非常常见的,套用这种模式进行单元测试通常的做法如下:

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

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

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

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