精华帖 (0) :: 良好帖 (1) :: 新手帖 (0) :: 隐藏帖 (0)
|
|
---|---|
作者 | 正文 |
发表时间:2006-12-01
本文翻译自IBM DeveloperWorks上的一篇文章,该文讲述了测试分类(test categorization)的概念,本身这个概念很简单,但是却实际的解决我们常见的问题,在我们的测试庞大到一定地步的时候,测试的运行时间过长,维护成本很高,我们如何能够保证持续集成(CI)的正常运行?那就是通过测试分类。所以我翻译了这片文章,希望对大家有所帮助。
尝试测试分类(test categorization) 你需要的是一个让你的build转变到更敏捷状态的策略。你需要一种解决方案来允许你在一天内多次运行测试,让那些已经需要三个小时完成的测试回到原先的状态。 三种分类 形象的将你的测试套件整理为三层,每一层代表开发人员进行的不同类型的测试,它们是根据运行时间的长短划分的。如图1所示,每一层将花费更多的总build时间,无论是运行时间还是编写它们所需的时间。 图1 测试分类的三层 最下面一层测试运行时间最短,如你所想,他们也是最容易写的。他们也覆盖最少量的代码。顶层是有高层次的测试组成,它们检测应用程序的很大一部分。这些测试相对难写,同时也需要更多时间来执行。中间一层测试介于两个极端之间。
1、单元测试 单元测试隔离的确认一个或者多个对象。单元测试不处理数据库、文件系统或者任何可能带来测试不能保证长期可运行的因素;顺序上,测试可以从(项目)第一天就开始写。事实上,这就是JUnit的设计目标。单元测试的隔离概念是在很多mock对象库隔离特定对象的外在依赖的基础上的。进一步说,单元测试可以在实际代码编写前就开始写——也就是测试先行开发TDD的概念。 2、组件测试 组件测试保证多个对象的交互,但是它们突破了代码隔离的概念。因为组件测试处理多层架构,他们经常要处理数据库、文件系统、网络元素等。而且组件测试一般很难在(项目)前编写,所以将它们加入到一个实际的测试先行/测试驱动的场景中是个很大的挑战。 3、系统测试 系统测试从端到端保证软件应用。因此,他们提出了高度的架构复杂性:整个应用必须在进行系统测试时运行。如果是一个Web应用程序,你需要访问数据库,从Web服务器、(应用程序)容器、任何相关的配置都要配合系统测试的运行。系统测试总是在软件开发周期的最后阶段撰写的。 什么是接受测试? 我应该使用jWebUnit或者Selenium? 使用TestNG进行测试分类 实现测试分类 创建不同的套件 你可以使用JUnit的TestSuite类(它也是一种Test)定义一组同类测试的集合。你要创建一个TestSuite的实例并添加相关的测试类到test方法中。你可以在TestSuite实例中通过定义一个叫做suite()的public static方法告诉JUnit这个套件包括哪些测试。所有包括的测试将会一次全部执行。因此你可以通过创建TestSuite来实现测试分类,一个单元测试的TestSuite、一个组件测试的TestSuite,有一个系统测试的TestSuite。 清单1 单元测试的TestSuite package test.org.acme.widget;
import junit.framework.Test; import junit.framework.TestSuite; import test.org.acme.widget.*; public class ComponentTestSuite { public static void main(String[] args) { junit.textui.TestRunner.run(ComponentTestSuite.suite()); } public static Test suite(){ TestSuite suite = new TestSuite(); suite.addTestSuite(DefaultSpringWidgetDAOImplTest.class); suite.addTestSuite(WidgetDAOImplLoadTest.class); suite.addTestSuite(WidgetReportTest.class); return suite; } }
清单2 运行组建测试的一个Ant任务 < target name ="component-test"
if ="Junit.present" depends ="junit-present,compile-tests" > < mkdir dir ="${testreportdir}" /> < junit dir ="./" failureproperty ="test.failure" printSummary ="yes" fork ="true" haltonerror ="true" > < sysproperty key ="basedir" value ="." /> < formatter type ="xml" /> < formatter usefile ="false" type ="plain" /> < classpath > < path refid ="build.classpath" /> < pathelement path ="${testclassesdir}" /> < pathelement path ="${classesdir}" /> classpath > < batchtest todir ="${testreportdir}" > < fileset dir ="test" > < include name ="**/ComponentTestSuite.java" /> fileset > batchtest > junit > target > 理想情况下,你还需要一个触发单元测试的任务和系统测试的任务。最后,还有希望运行所有测试的情况,你需要创建第四个任务来运行其它三个任务,就像清单3里面那样: 清单3 运行所有测试的任务 < target name ="test-all" depends ="unit-test,component-test,system-test" />
创建单独的TestSuite是一个迅速实现测试分类的解决方案。缺点是这个方法需要你创建新的测试,你必须编成式的将它们添加到合适的TestSuite里面,这可能有点痛苦。给每个测试类型创建单独的目录可能是一种更加有弹性的方法,它允许你添加新的测试分类但无需重新编译。
创建单独的目录 我发现最简单的通过JUnit实现测试分类的方法是逻辑上将不同类型的测试放到不同的目录中。使用这个方法,所有的单元测试都放在unit目录,所有的组建测试都放在component目录,等等。 清单4 实现测试分类的目录结构 acme-proj/
test/ unit/ component/ system/ conf/ 运行这些测试,你需要定义至少四个Ant任务:一个给单元测试,另外的给组建测试,还有系统测试。第四个任务是一个方便运行其它三个测试类型的任务(就像清单3种展示的那种方式)。 < batchtest todir ="${testreportdir}" >
< fileset dir ="test/unit" > < include name ="**/**Test.java" /> fileset > batchtest > 注意这个任务运行test/unit目录下的所有测试,当创建了新的单元测试(或者其它分类的其它测试),你只需要把它们放到这个目录里面就可以了!这比添加一行到TestSuite中并重新编译它要方便多了。
问题解决了! 回到最初的场景,我认为你和你的团队会决定使用单独的目录这种弹性的解决方案来解决你们的build时间过长的问题。这个任务最难的一个方面是检查和分清测试类型。你重构你的Ant build文件创建四个新的任务(三个单独的测试分类还有一个运行它们三个)。甚至,你修改CuiresControl只在check-in的时候运行单元测试,而组建测试按小时运行。更进一步的检查后,系统测试也可以几个小时运行一次,也许你会创建一个新的任务来同时运行组建测试和系统测试。 最后的结果是每天测试运行很多次,你的团队可以快速的发现集成错误——一般在几个小时内。 创建敏捷构建不是为了赶时髦,它实际上是保证代码质量的重要因素。测试运行的更加频繁,开发人员的测试的价值就能直接转化为钱。并且,希望你们的公司能够在2006取得广泛的成功! 资源
Get products and technologies
Discuss
定义TestSuite的过程需要你察看你当前的所有测试并将它们加入到相应的类里面(例如,所有的单元测试加入到UnitTestSuite)。这也就意味着你在相应的分类里面创建了新的测试,你必须编程式的将它们添加到合适的TestSuite中,当然还需要重新编译它们。 运行单独的TestSuite需要单独的Ant任务来运行正确的测试组。你可以定义一个component-test任务来执行ComponentTtestSuite,就像清单2中的样子: 声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|
返回顶楼 | |
发表时间:2006-12-01
麻烦休整字体下先
|
|
返回顶楼 | |
浏览 5210 次