David的测试技术空间,收藏好文档和分享我的技术理解。5年的数通产品测试和安全产品测试经验,3年Web产品测试和多年测试管理和测试工具开发经验。目前关注性能分析调优、Jmeter和TestNG+WebDriver+Hamcrest的培训推广。Welcome沟通交流,请留言或者发邮件到daviwang_2004 at soguo.com。

单元测试模式

上一篇 / 下一篇  2007-12-07 10:57:55 / 个人分类:旧资料

引言

单元测试思想似乎一直引起人们的兴趣,对于那些接收单元测试思想的人来说,一直认同一个观点:要想写一个好的单元测试是很困难的。

面对着开发过程中的效率问题,一直无法避免一个问题:这些测试是否真的值得?也有另一些人在嘲笑着单元测试的思想,特别是“当程序通过单元测试的时候,代码就是好的”这种思想。单元测试有一天也会放入满是灰尘的书架,“它不过是另一个程序工具而已”。

如果要改变这种状况,同行就必须接收单元测试思想。微软Visual Studio将包括自动重构的工具,很明显自动化单元测试工具将着重于维护和成本,获得更广泛的支持。

然 而要使单元测试被广泛接受,单元测试必须被形式化,让它成为一个真正的工程规范而不是一个专门的方法而依赖于程序员个人的不确定性能力。毕竟,单元测试用 来测试程序员写的代码,如果程序员一开始就写坏代码,我们就不能指望在测试中有更好的质量。一个概念是:应该首先写单元测试。在代码被写之前,在某个程度 上,程序员不仅仅要考虑到代码做什么,也要考虑到代码是怎样被设计。很多人畏惧先写单元测试的思想,那是因为需要在设计工作之前进行预先整理,很多人并不 是有意识地认识到他们正在做什么?

到 目前为止,还没有一个形式化的单元测试规程,提供一个指南来确保一些单元测试质量的级别。在任何测试被写之前,设计必须达到某种程度的形式化的这个前提条 件,会导致困难,因为程序员或者没有形式化设计经验,或者不习惯预先的设计工作。更严重的是预先设计会被重构的假相所替代。

我们需要两件事情,一是建立在单元测试模式之上的形式化的单元测试,二是预先采用面向对象的设计模式应用于开发。要满足单元测试,需要融合面向对象,设计模式和重构。

应当设计一个自动产生单元测试的工具集,带有正向反向的工程过程。对于单元测试来说,对于被测试的代码,应该能够自动产生方法桩,给实施者提供一个测试代码的预期结构和行为的一些文档。

模式分类如下:

1.成功/失败模式

2.集合管理模式

3.数据驱动模式

4.性能模式

5.过程模式

6.模拟模式

7.多线程模式

8.压力测试模式

 

1.        成功/失败模式:

这些模式是你第一道防线,但不能保证一个好的代码。

 

简单测试模式(Pass/Fail Patterns

成功/失效模式是最简单的模式。它着重于单元测试的效率,当单元测试通过一个简单测试的时候,它告诉我们被测试的代码运做了。在这种单元测试中,我们给它一个同样的输入,程序给出一样的输出。促发错误的单元测试也一样,给同样一个测试条件,代码正确地陷入了一个错误。

但是在这种情况下,我们没有自信在其它的条件下,代码是否同样工作正常。在其它错误条件下,我们也不能肯定一定进入错误陷阱。

代码通路模式(Code-Path Patten

简单测试被典型地叫做“黑盒测试”,不检查代码,你能做的是——揣测代码在测试下会面对什么,通过成功和失效用例,来验证那些揣测。

更好的测试保证至少所有的代码通路被执行,这属于白盒测试的一部分,要知道代码的内部工作。这里优先集不是设置条件测试成功/失败,而是设置条件测试代码的路径。对于给定的路径,比较预期输入输出。

怎 样我们写白盒测试来测试路径?这样我们就接触到“开始你的代码前进行设计”这种思想。规程是通过强迫预先设计,单元测试能够测试代码路径,实施者不需要做 特别考虑。进一步,单元测试文档精确描述代码路径被指望是什么样子的。反过来说,实施期间需要规程,当发现单元测试还有没有被预见到的代码通路,这时就要 修正单元测试。

 

参数域模式(Parameter-Range Pattern

为了改善简单测试模式,确保处理各种各样的通过/失效模式,应该使用条件域进行测试。通过让代码通过多个参数域集合。现在我们有自信代码可以在各种环境和条件下工作。

 

2.数据驱动模式(Data Drivern Test Pattern):

在某种测试下,构造参数域单元测试是可行的,但当测试带有复杂排列的代码时就变得复杂和效率低下,数据驱动测试模式通过分割测试数据以减少这种复杂性。但这本身可能就是复杂的工作。要使用改进的数据之间独立性。

简单测试数据模式(Simple-Data-Test-Pattern

在最简单的情况下,一个测试数据集反复通过测试代码,得到一个直接的结果(通过/失效)。单元测试本身能够计算结果,或者由数据集本身提供,不允许测试结果的不一致。

典型的例子是:码流的效验和计算,数学算法,简单的业务算法计算。更复杂的例子是加密算法和无损编码或压缩算法。

数据转换测试模式(Data-Transformation-Test Pattern):

适用于结果的定性度量。例如有损转换算法,例如单元测试考虑到算法的性能:压缩比和数据丢失。单元测试可能需要效验数据能够在容忍的范围内被转换。另一个例子是精度,比如税金的计算,

 

3.数据事务模式(Data Tranaction Pattern):

围绕数据持久性和通讯问题。更多的主题体现在模拟模式,这些模式故意忽略压力测试模式,例如服务器上的负荷,将在压力测试模式上讨论

简单数据输入/输出模式模式(Simple-Data-I/O Pattern)

这是简单数据事务模式,和效验一个服务的读写功能一样。可以和简单测试模式一起,以便一个数据集合能被一个服务处理和反馈,注意使事务测试加一点健壮性。

约束数据模式:(Consitraint-Data_Pattern)

通过测试一个服务的各个方面和服务可能的规则,该模式增加了简单数据模式的健壮性,约束典型的包括:

是否为空

必须唯一

默认值

外建关系,级联更新,级联删除

如何在数据库服务这些约束被模式化,面向写,单元测试面向效验服务本身,不管是一个数据库模式、web服务,或其它模式,使用这些约束改善数据的完整整体性。

回滚模式:(Roolback Patter)

回滚模式附属于另一个事务测试模式。当假设单元测试不考虑有序,当和数据库或另一个持久存储服务运作的时候。一个单元测试改变了数据集会促使另一个单元测试不正确的失败。

大 部分单元测试将拥有回滚到数据集到一个已知状态的能力。这可能在单元测试开始的时候,需要设置数据集到一个已知的状态。为了性能原因,可以在测试套件开始 的时候,配置一个数据集到一个已知的状态,而不是在每个测试使用服务回滚功能,以便恢复每个测试的状态。(假设事务提供回滚能力)。

 

4集合管理模式:Collection Management Patterns

许多应用管理信息集合,有各种各样的级别供程序员利用,效验代码是否使用正确的集合,这影响到有序和约束。

集合有序模式:(Collection-Order Pattern

这是一个简单模式,当给定一个无序列表时效验期望的结果,测试效验以下的结果:

无序

有序

和输入顺序一样

这给实施者一个关键的信息,期望容器怎样去管理代码。

 

枚举模式(The Enumeration Pattern)

该模式效验枚举问题或集合往返移动例如一个集合需要正向反向穿越当集合是一个非线性的时候这是一个重要的测试例如树节点的集合。边缘条件也是重要的测试,当一个或几个枚举量被枚举通过第一个和最后一个项目时会发生什么?

集合约束模式:(The Collection-Contraint Patter)

这个模式效验容器处理约束违例,空值和插入重复键。这个模式典型应用于一个键值对集合。

集合索引模式:(The Coloection-Index-Pattern

索引测试效验和文档化索引方法,集合容器必须支持通过与或关键字的方法。此外,效验更新和删除事务,利用索引正确工作和索引保护来防止索引的缺失。

5.性能模式:

单元测试不仅只关心函数还关心形式,代码怎样有效地的执行功能,有多快?使用多少内存?为了有效的数据检索,代码交替使用数据插入(散列)?正确释放了资源?这些也在单元测试的范围内,通过性能测试模式,实施者要达到一个目标,这导致一个好的代码,好的应用和使客户高兴。

性能测试模式;(The Performance Test Pattern)

基本的性能测试模式可以度量:

内存使用(物理,cache,虚拟)

资源(句柄)的使用

磁盘的使用(物理,cache

算法性能(插入,获取,索引和操作)

一些语言和操作系统使这些信息很难获取。如自己带有垃圾收集器的语言,这样很难度量内存使用。这个模式经常和简单测试数据模式联系在一起,以便标准能度量整个数据集。注意即时编译使性能度量困难,环境还可能不稳定,如网络状态。

 

6.过程(进程)模式

单元测试应用的基本函数。一个过程是不同的单元类型,测试过程如同其它的单元测试一样,有一样的优点,它记录(文档化)线路(过程执行的)。通过测试无序的过程,循序识别潜在的用户接口问题。过程的含义是包括状态转换和业务规则。两者都必须效验。

过程有序模式(The-Process-Sequence-Patttern

通过顺序执行的代码,该模式效验预期的行为,当代码执行无序的时候效验是否进入陷阱。过程有序模式也应用于数据事务模式而不是强迫一个回滚,重置一个数据集,或者完全装载一个完全的数据集,一个过程可以被构造在前一个步骤工作的基础之上,提高单元测试的性能和可维护性。

过程状态模式(The Process-state Pattern

状态的概念不可能被从过程剥离开来。通过执行任何需要的活动,管理状态的关键点是过程能从一个状态平滑地变迁到另一个状态。特别是无状态系统,例如Web应用,状态的概念对测试来说是重要的(在整个会话状态),为了在不需要使用一个复杂的客户—服务器系统,人工动作需要测试者能理解状态和可允许的变迁,可能需要和假对象一起模拟复杂的客户—服务器环境下,以便完成这种测试。

 

过程规则模式:The Process-Role Pattern

此 测试类似于代码路径模式,效验系统的每一个规则。要实施这样一个测试,业务规则需要从周围的代码分离,它们不能被应用于表示层和数据访问层。它是最简洁的 好的代码,大量的代码违背的这一个规则,导致在离散的单元测试中测试非常困难。单元测试另一个优点“迫使更高级别的模块化和解偶。

7.模拟模式:

数据事务测试是困难的,因为需要预设配置,打开一个连接,或一个在线服务。模拟对象通过模式一个数据库,Web服务,用户事件,连接,硬件,代码去处理它们。假对象也有能力构造失效条件,某些条件很难被再现出来,比如连接丢失,很慢的服务器,失效的HUB等等。然而,要正确的使用假对象,代码必须利用某种工厂模式,展示正确的实例,或者是一个真正的东西,或者是一个模拟。比如,如果将数据库连接和SQL语句写在一起,并被内嵌到表示层和业务层,这种代码就很难被模拟,需要有一个预先配置的数据库,数据库服务器和一个连接。而且,测试数据事务的结果需要另一个事务,创建一个失效点。尽可能的,单元测试不应该依赖于以被测试代码外部的失效为条件。

假对象模式:Mock-Object Patter

为了正确使用假对象模式,必须要使用工厂模式,示例一个服务连接,必须使用一个基类,以便于通过虚方法管理所有的有服务特性的交互。(面向方面的编程可以通过使用建立切点,但大多数语言无法利用AOP。)

为了达到这种结构,在编码的过程中需要许多的预见和规程,在工厂中需要建立一个抽象类,而不是直接在代码中展示,外观和桥接模式需要被使用以便支持这一种抽象,数据事务需要从表示层和业务层抽象出来。通过模拟对象,这样可以更灵活模拟测试复杂事务和失效条件。

服务模拟模式:Service-smulation Pattern

测试模拟连接和一个服务的I/O方法。此外模拟一个存在的服务。当开发一个大规模的应用,应用中有大量的功能性代码时,模式非常有用。

位错误模拟模式(the Bit-Error-Simulation Pattern

例如在气象卫星通讯中的传输。在数据流中,要考虑哪儿需要处理错误,在传输层还是在更高层去处理。该模式在传输层中是相关的。

组件模拟模式(The Component-Simulation Pattern

模拟对象模拟一个组件失效,例如一个网络电缆,HUB或一个服务。模拟对象可以效验许多东西:

抛出一个异常

返回完全的或不完全的丢失数据

返回一个耗时错误

单元测试需要处理这些错误条件

 

8.多线程模式:

单元测试多线程的应用是非常困难的,要建立一个条件,因为多线程的本质是异步的和非确定性的。这是一个非常通用的模式。要正确地执行多线程测试,测试者必需在各个独立的在多个线程中测试,以便当一个线程结束等待状态并激活它。

 

通知模式(The Signalled pattern

测试工作线程最终通过主线程或另一个线程,当完成这个任务后。这个可以是独立于其它服务(模拟对象地一个好地应用)。两个线程操作同一个数据,也可以调用其它的模式。

死锁解决模式(The Deadlock-Resolution Pattern

可能这种测试非常复杂,因为它需要彻底理解工作线程,效验死锁解决方案

 

9.压力测试模式:

大部分的应用在理想环境下测试,比如,不考虑网络通讯问题,使用小的数据集,但现时世界不一样。在完全崩溃之前,一个应用可能性能下降,反映迟缓或偶尔有一些错误。单元测试效验在压力下代码的性能,而不仅仅是在理想的条件下。

批数据压力测试模式(The Bulk-Data-stress-test Pattern

被设计用来效验数据操纵的性能,在大数据集的情况下,经常能揭露插入、访问、删除过程的效率问题,可通过索引、约束和数据模型的结构,包括数据是否在客户机还是服务器中运行。

资源压力测试模式:(The Resource-Stress-Test Pattern

资源消耗压力测试模式依赖于操作系统的性能,通过模拟对象可能更好。如果操作系统支持模拟低内存,低的磁盘空间和其它资源,可以用一个简单测试模式执行。此外,模拟对象用来模拟在低资源的条件下操作系统的响应。

负荷测试模式(The Loading Test Pattern

测试度量代码的行为,当另一个机器,应用和线程在系统中时,例如,高CPU的使用率和网络通讯。这是一个模拟(不使用假对象),是一个不确定的值。理想的情况下,单元测试用一个线程创建模拟高的网络通讯,该线程往网络中发大量的包。

 

10.表示层模式:

单元测试一个最具有挑战性的是:效验信息,例如在表示层获得用户权利信息,内部应用改变表示层的状态。经常性的,表示层和业务对象、数据对象及控制对象捆绑在一起。解决方案是MVC体系结构。

SUNWeb有象这样的MVC结构:

 

模型使用事件通知改变和用户姿态,例如单击按钮。没有事件,对象乱作一团。

视图状态测试模式

测试效验模型状态的改变,视图在合适的时候改变状态。

此测试仅仅是一半的MVC模式,模型事件通知视图,视图管理事件影响表示层的内容和状态。控制器不是一个主要的因素。

模型状态测试模式

一旦我们用视图状态效验应用的性能,我们可以处理更复杂的。测试中,单元测试直接在表示层模拟用户的姿态和内容,如果需要,直接调用状态事件,比如按下键,单击等。

文章描述了24个测试模式,希望能够使单元测试成为一个更工程化的规程。当写单元测试的时候,参照某种单元测试模式,将能更好的识别哪个单元测试更有效,哪个有缺点。

我们需要一些工具自动产生单元测试。将能有效的降低成本提高效率,可以使用应用程序产生工具,给定单元测试的信息,能够自动创建类,结构和桩等。



Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=383103


TAG: 与目前工作有关的杂项

 

评分:0

我来说两句

Open Toolbar