谈谈单元测试之

为什么要进行烦人的单元测试?

前言

最近,在网上看到过一个调查,调查的内容是“程序员在项目开发中编写单元测试的情况”。当然,至于调查的结果,我想聪明的你已经可以猜到了。高达 58.3% 的比例,一般情况下不写单元测试,只有偶尔的情况才会写写。16.6% 的程序员从来都不写单元测试。只有很少的一部分程序员才会在自己的代码中进行单元测试,并保证方法测试通过。看到这些,你想到了什么?


现状


虽然,这个调查可能会有些片面性,但这也基本反应了国内程序员的开发现状,很少有程序员能够比较认真的去编写单元测试。而且,甚至有的程序员根本就不知道为什么要写单元测试(这一点让我很郁闷)。他们经常会说,公司里不是有测试人员嘛,测试应该是他们要做的事,我们的工作只是开发(这位仁兄肯定没有学过软件工程)。当然,这些并不是偶然的,正如佛经里边说的“因果循环”,有果必有因。那么,到底是什么原因,导致程序员对单元测试这么不感冒呢?


发现


通过与几个朋友的讨论,以及网上的调查,主要有这几种原因,导致程序员对单元测试很排斥,或许说很不以为意。
  • 不知道怎么编写单元测试
  • 项目没有要求,所以不编写
  • 单元测试价值不高,完全是浪费时间
  • 业务逻辑比较简单,不值得编写单元测试
  • 不管怎样,集成测试将会抓住所有的 bug,用不着进行单元测试
  • 在项目的前期还是尽量去编写单元测试,但是越到项目的后期就越失控
  • 为了完成编码任务,没有足够的时间编写单元测试。编写单元测试会导致不能按时完成编码任务,导致项目延期
很显然,这几种原因归根结底,无外乎就是不了解单元测试,自认为很聪明,自己懒不想去测试,对项目的时间、进度把控不好。下面,我将一 一进行分析,剖析出程序员的开发心理,以此来给朋友们提个醒,最终聪明反被聪明误。


剖析


不知道怎么编写单元测试

这个问题在于,还没有接触过单元测试,同时,也没有体会过企业级的代码开发。不知道同时也不了解单元测试能带给你什么。设想一下,当你开发完一个功能模块的时候,你如何确定你的模块没有 bug 呢?如果涉及到具体的业务,你会执行 debug 模式,然后一点一点的深入到代码中去查看吗?如果你一直都是这样,那么你早就已经 OUT 了。赶快去了解一下单元测试的工具吧,你会收获很大的。


项目没有要求,所以不编写

这个问题反映出了一种现象,同时也是一种习惯。项目有没有要求,只能说明项目的管理上不严格,并不是程序员不编写单元测试的理由。他们在以往的开发中,并没有养成写单元测试的好习惯。可想而知,他们的代码质量,我就不敢恭维了。给个建议,尝试着写漂亮的代码,之所以因为漂亮,是指得健康、简洁、健壮。当然,完成漂亮的代码就离不开单元测试了。


单元测试价值不高,完全是浪费时间

这种说法其实是错误的。为什么这么说呢?在日常的开发中,代码的完工其实并不等于开发的完工。如果没有单元测试,那么如何保证代码能够正常运行呢?测试人员做的只是业务上的集成测试,也就是黑盒测试,对单个的方法是没有办法测试的,而且,测试出的 bug 的范围也会很广,根本不能确定 bug 的范围,还得去花时间来确定 bug 出在什么地方。难道这就不浪费时间了吗?甚至,这样的方式,时间浪费的会更多。


业务逻辑比较简单,不值得编写单元测试

所谓的业务逻辑比较简单,其实是相对的。当你对某一块业务逻辑很熟悉的时候,你自然会认为它很简单。然而,单元测试的必要性并不是仅仅在于测试代码的功能是否正确,还在于,当其他同事在了解你的业务的时候,能够很快的通过单元测试来熟悉代码的功能,甚至不用去读代码,就能够知道它做了哪些事情。因此,写单元测试不仅是解放了自己,更方便了别人。


项目前期还在尽量写测试,到了后期就失控了

这种问题的原因在于,对项目进度、项目中的技术点研究时间、人员的沟通、业务需求的熟悉程度等没有把控好。这个问题的出现并不是个人的问题,而是反映了项目管理中存在的问题。当然,个人的原因也存在,就是如何在有限的时间里,提高效率。这一点需要大家好好思考一下了。我的建议,多做计划,根据实际情况变更计划。多和项目组长、组成员进行沟通。及时反应项目中存在的问题。


为了完成编码任务,没有足够的时间编写单元测试

这个问题在于,程序员领取的任务较为复杂,或者自己的开发效率有待提高。其实,开发任务是包括编码和单元测试的。在领任务的时候,应该跟据自身的能力,跟组长或经理沟通好,以便留出一定的测试时间。当然,提高自己的编码效率也是很有必要的。至于如何提高开发效率,网上有很多这样的文章,这里就不再赘述了。


重要性


测试常常是程序员十分厌倦的一个活动。测试能给我们带来什么?了解这些是非常重要的,测试不可能保证一个程序是完全正确的,但是测试却可以增强我们对程序完整的信心,测试可以让我们相信程序做了我么期望它做的事情。测试能够使我们尽早的发现程序的 bug 和不足。

一个 bug 被隐藏的时间越长,修复这个 bug 的代价就越大。在《快速软件开发》一书中已引用了大量的研究数据指出:最后才修改一个 bug 的代价是在 bug 产生时修改它的代价的10倍。

当然,我们主要讨论的是单元测试。单元测试是一个方法层面上的测试,也是最细粒度的测试。用于测试一个类的每一个方法都已经满足了方法的功能要求。在开发中,对于自己开发的模块,只有在通过单元测试之后,才能提交到 SVN 库 或者 Git 库。


应用


正是由于测试在开发中的重要地位,才会在IT界刮起了 TDD 的旋风。TDD,也就是测试驱动开发模式。它旨在强调在开发功能代码之前,先编写测试代码。也就是说在明确要开发某个功能后,首先思考如何对这个功能进行测试,并完成测试代码的编写,然后编写相关的代码满足这些测试用例。然后循环进行添加其他功能,直到完成全部功能的开发。


工具


说了这么多,那么都有什么工具(框架)能帮助我们完成可重复的单元测试呢?下面我就介绍几个常用的。这里只介绍 Java 语言的。其他语言的请问谷老师(Google)。
  • JUnit(推荐使用JUnit4)
JUnit 在日常开发中还是很常用的,而且 Java 的各种 IDE (Eclipse、MyEclipse、IntelliJ IDEA)都集成了 JUnit 的组件。当然,自己添加插件也是很方便的。JUnit 框架是 Java 语言单元测试当前的一站式解决方案。这个框架值得称赞,因为它把测试驱动的开发思想介绍给 Java 开发人员并教给他们如何有效地编写单元测试。

  • TestNG
TestNG,即Testing Next Generation,下一代测试技术。是根据JUnit和NUnit思想,采用 jdk 的 annotation 技术来强化测试功能并借助XML 文件强化测试组织结构而构建的测试框架。TestNG 的强大之处还在于不仅可以用来做单元测试,还可以用来做集成测试。


这里仅仅是介绍一下有哪些最常用的 Java 单元测试工具,对于如何使用这些工具,在后续的博客中会有介绍,这里就不再多说了。有兴趣的请关注后续的文章。


结束语


俗话说,一屋不扫,何以扫天下。开发中,我们自己的代码都不能保证功能的正确性,那么还有什么效率可言呢?做再多的任务,写再多的代码也只不过是在搭鸡窝,做着机器一样的重复的工作。IT界有一个原则,DRY原则 —— Don't Repeat Yourself !只有通过对自己的工作不断的检查,不断的测试,才能不断的突破,不断的脱颖而出,当然,你才能不断的提高。

Test Day Day Up!  Experience Day Day Up!  And Money Day Day Up Too!

哎呀妈呀,中国式英语又出来了!

测试工具 JUnit 3


前言


上一篇文章《 为什么要进行烦人的单元测试?》讨论了一下现阶段软件开发中,程序员们测试情况的现状。这篇文章中,我打算介绍一下单元测试的工具(插件),并且推荐大家以后在开发中,真正的用上单元测试,用好单元测试。


说明


这篇文章的主题,主要是介绍一下 JUnit 3,虽然 JUnit 3 已经不推荐使用了,但它也曾是风靡一时。这里旨在讨论一下 JUnit 3 的使用,以及它的内部构造,就当是为下一篇文章介绍 JUnit 4 做铺垫吧。之前已经把单元测试的重要性都讲出来了,这里就不再赘述了,直接进入正题。


介绍


JUnit 是由 Erich Gamma 和 Kent Beck 编写的一个回归测试框架(regression testing framework)。JUnit 测试是程序员测试,即所谓白盒测试。它是一个 Java 语言的测试框架,多数 Java 的开发环境都已经集成了 JUnit 作为单元测试的工具。


特性

  • 用于测试期望结果的断言(Assertion)
  • 用于共享共同测试数据的测试工具
  • 用于方便的组织和运行测试的测试套件
  • 图形和文本的测试运行器

使用


下载



加入项目

  • 把压缩包中的 junit3.8.1.jar 文件,加入到项目的 classpath 中。


基本流程

  • 写测试类并继承 TestCase 类
  • 写测试方法 testXXX()
  • 写测试套件类,将 test case 加入到 test suite
  • 运行JUnit Test 进行测试

演示代码


  1. <span style="font-family:Microsoft YaHei;">package com.tgb.test;  
  2.   
  3. import junit.framework.Assert;  
  4. import junit.framework.Test;  
  5. import junit.framework.TestCase;  
  6. import junit.framework.TestSuite;  
  7.   
  8. // 1. 继承 TestCase 类  
  9. public class CalculatorTest extends TestCase {  
  10.     // 2. 测试方法必须以 test 开头  
  11.     public void testAdd() {  
  12.         int result = new Calculator().add(12);  
  13.         Assert.assertEquals(3, result);  
  14.     }  
  15.       
  16.     // 3. 将 testcase 加入 testsuite,可以同时测试多个用例  
  17.     public static Test suite() {  
  18.         return new TestSuite(CalculatorTest.class);  
  19.     }  
  20. }</span>  


剖析概念

  • TestCase(测试用例)
当一个类继承 JUnit 的 TestCase 类,即成为一个测试类,而且,测试类中的方法必须以 test 开头,比如:testAdd() 等。

  • TestSuite(测试套件)
TestSuite 是一组测试,目的在于将相关的测试用例归入一组。当执行一个 Test Suite 时,就会执行组内所有的测试方法,这就避免了繁琐的测试步骤。当然,如果没有为 test case 写 test suite 的话,系统会默认为每个 test case 生成一个 test suite。

  • Assert(断言)
Assert 用于检查条件是否成立,当条件成立则 Assert 方法通过,否则会抛出异常。例如,Assert.assertEquals(3, result); 判断 result 是否跟期望的3想等,如果想等则通过,否则测试失败。

主要有如下几个断言方法:

assertTrue/False():判断一个条件是 true 还是 false。

fail():失败,可以有消息,也可以没有消息。

assertEquals():判断是否想等,可以指定输出错误信息。注意不同数据类型所使用的 assertEquals 方法参数有所不同。

assertNotNull/Null():判断一个对象是否为空。

assertSame/NotSame():判断两个对象是否指向同一个对象。

failNotSame/failNotEquals():当不指向同一个内存地址或者不相等的时候,输出错误信息。错误信息为指定的格式。

  • setUp
每次测试方法执行之前,都会执行 setUp 方法,此方法用于进行一些固定的准备工作,比如,实例化对象,打开网络连接等。

  • tearDown
每次测试方法执行之后,都会执行 tearDown 方法,此方法用于进行一些固定的善后工作,比如,关闭网络连接等。


结束语


JUnit 3 就介绍到这,可以看出,JUnit 3 还是很简单的,只不过在每次编写测试类时,都需要继承 TestCase 类,这就无形之中给测试类增加了一些牵绊。下一篇文章中,我们一起来讨论一下 JUnit 4 的一些新特性,以及是如何简化测试用例的。

不要着急哦,下一篇马上就到。。。

测试工具 JUnit 4

前言


上一篇文章《测试工具 JUnit 3》简单的讨论了 JUnit 3 的使用以及内部的方法。这篇文章将会在 JUnit 3 的基础上,讨论一下 JUnit 4 的新特性。同时,与 JUnit 3 做一个简单的对比。那么,废话就不多说了,直接进入正题。


介绍


JUnit 4.x 是利用了 Java 5 的特性(Annotation)的优势,使得测试比起 3.x 版本更加的方便简单,JUnit 4.x 不是旧版本的简单升级,它是一个全新的框架,整个框架的包结构已经彻底改变,但 4.x 版本仍然能够很好的兼容旧版本的测试用例。


使用


先来点实在的,看看代码中是怎么使用的。其余的待会再说。

下载



加入项目

  • 把 junit4.8.1.jar 文件,加入到项目的 classpath 中。

对比


在代码之前,先让我们看一下 JUnit 4 和 JUnit 3 的区别,看看 JUnit 4 到底简化了哪些东西。




演示代码

  1. <span style="font-family:Microsoft YaHei;">package com.tgb;  
  2.   
  3. import static org.junit.Assert.*;  
  4.   
  5. import org.junit.Ignore;  
  6. import org.junit.Test;  
  7.   
  8.   
  9. public class TestWordDealUtil {  
  10.     // 测试 wordFormat4DB 正常运行的情况  
  11.     @Test  
  12.     public void testWordFarmat4DBNormal() {  
  13.         String target = "employeeInfo";  
  14.         String result = WordDealUtil.wordFormat4DB(target);  
  15.           
  16.         assertEquals("employee_info", result);  
  17.     }  
  18.       
  19.     // 测试 null 时的处理情况  
  20.     @Test(expected=NullPointerException.class)  
  21.     public void testWordFormat4DBNull() {  
  22.         String target = null;  
  23.         String result = WordDealUtil.wordFormat4DB(target);  
  24.           
  25.         assertNull(result);  
  26.     }  
  27.       
  28.     // 测试空字符串的处理情况  
  29.     @Test  
  30.     public void testWordFormat4DBEmpty() {  
  31.         String target = "";  
  32.         String result = WordDealUtil.wordFormat4DB(target);  
  33.           
  34.         assertEquals("", result);  
  35.     }  
  36.       
  37.     // 测试当首字母大写时的情况  
  38.     //@Ignore  
  39.     @Test  
  40.     public void testWordFormat4DBBegin() {  
  41.         String target = "EmployeeInfo";  
  42.         String result = WordDealUtil.wordFormat4DB(target);  
  43.           
  44.         assertEquals("_employee_info", result);  
  45.     }  
  46.       
  47.     // 测试当尾字母大写时的情况  
  48.     @Test  
  49.     public void testWordFormat4DBEnd() {  
  50.         String target = "employeeInfoA";  
  51.         String result = WordDealUtil.wordFormat4DB(target);  
  52.           
  53.         assertEquals("employee_info_a", result);  
  54.     }  
  55.       
  56.     // 测试多个相连字母字母大写时的情况  
  57.     @Test  
  58.     public void testWordFormat4DBTogether() {  
  59.         String target = "employeeAInfo";  
  60.         String result = WordDealUtil.wordFormat4DB(target);  
  61.           
  62.         assertEquals("employee_a_info", result);  
  63.     }  
  64. }  
  65. </span>  


从图中可以看出,TestWordDealUtil 测试类中,有6个测试方法,其中有5个测试方法都已经通过,另外一个抛出了 NullPointerException (空指针)异常,需要注意的是,这里并不是单元测试的失败(Failure),而是测试出现了错误(Error)。那么,这两种有什么区别呢?下面就讨论一下这两者的区别。

JUnit 将测试失败的情况分为两种:Failure 和 Error 。 Failure 一般是由单元测试使用的断言方法判断失败引起的,它表示在测试点发现了问题(程序中的 bug);而 Error 则是有代码异常引起的,这是测试目的之外的发现,它可能产生于测试代码本身的错误(也就是说,编写的测试代码有问题),也可能是被测试代码中的一个隐藏 bug 。不过,一般情况下是第一种情况。


深入


常用注解

  • @Before
初始化方法,在任何一个测试方法执行之前,必须执行的代码。对比 JUnit 3 ,和 setUp()方法具有相同的功能。在该注解的方法中,可以进行一些准备工作,比如初始化对象,打开网络连接等。

  • @After
释放资源,在任何一个测试方法执行之后,需要进行的收尾工作。对比 JUnit 3 ,和 tearDown()方法具有相同的功能。

  • @Test
测试方法,表明这是一个测试方法。在 JUnit 中将会自动被执行。对与方法的声明也有如下要求:名字可以随便取,没有任何限制,但是返回值必须为 void ,而且不能有任何参数。如果违反这些规定,会在运行时抛出一个异常。不过,为了培养一个好的编程习惯,我们一般在测试的方法名上加 test ,比如:testAdd()。

同时,该 Annotation(@Test) 还可以测试期望异常和超时时间,如 @Test(timeout=100),我们给测试函数设定一个执行时间,超过这个时间(100毫秒),他们就会被系统强行终止,并且系统还会向你汇报该函数结束的原因是因为超时,这样你就可以发现这些 bug 了。而且,它还可以测试期望的异常,例如,我们刚刚的那个空指针异常就可以这样:@Test(expected=NullPointerException.class)。再来看一下测试结果。



  • @Ignore
忽略的测试方法,标注的含义就是“某些方法尚未完成,咱不参与此次测试”;这样的话测试结果就会提示你有几个测试被忽略,而不是失败。一旦你完成了相应的函数,只需要把 @Ignore 注解删除即可,就可以进行正常测试了。当然,这个 @Ignore 注解对于像我这样有“强迫症”的人还是大有意义的。每当看到红色条(测试失败)的时候就会全身不舒服,感觉无法忍受(除非要测试的目的就是让它失败)。当然,对代码也是一样,无法忍受那些杂乱不堪的代码。所以,建议大家都写漂亮的代码。这样人人都喜欢看你的代码。哎,有强迫症的人伤不起啊!

  • @BeforeClass
针对所有测试,也就是整个测试类中,在所有测试方法执行前,都会先执行由它注解的方法,而且只执行一次。当然,需要注意的是,修饰符必须是 public static void xxxx ;此 Annotation 是 JUnit 4 新增的功能。

  • @AfterClass
针对所有测试,也就是整个测试类中,在所有测试方法都执行完之后,才会执行由它注解的方法,而且只执行一次。当然,需要注意的是,修饰符也必须是 public static void xxxx ;此 Annotation 也是 JUnit 4 新增的功能,与 @BeforeClass 是一对。


执行顺序


所以,在 JUnit 4 中,单元测试用例的执行顺序为:



每一个测试方法的调用顺序为:





规范


最后,在来说说关于测试的规范,这些规范是从编程规则,以及日常的实践中,由那些大牛们总结出来的。作为后人的我们,在大树下乘凉的同时,更要遵守这些规则,使得大树更加茁壮成长。
  • 单元测试代码应位于单独的 Source Folder 下
此 Source Folder 通常为 test ,这样可以方便的管理业务代码与测试代码。其实,在项目管理工具 Maven 上已经做了这种规范了。在我们自己写代码时,注意一下即可。



  • 测试类应该与被测试类位于同一 package 下
便于进行管理,同时减少引入带测试类的麻烦。



  • 选择有意义的测试方法名
无论是 JUnit 4 ,还是 JUnit 3 ,单元测试方法名均需使用 test<待测试方法名称>[概要描述] ,如 public void testDivideDivisorIsZero() ,很容易知道测试方法的含义。

  • 保存测试的独立性
每项单元测试都必须独立于其他所有单元测试而运行,因为单元测试需能以任何顺序运行。

  • 为暂时未实现的测试代码忽略(@Ignore)或抛出失败(fail)
在 JUnit 4 中,可以在测试方法上使用注解 @Ignore 。在 JUnit 3 中,可以在未实现的测试方法中使用 fail("测试方法未实现"); 以告知失败是因为测试方法未实现。

  • 在调用断言(assert)方法时给出失败的原因
在使用断言方法时,请使用带有 message 参数的 API ,并在调用时给出失败时的原因描述,如 assertNotNull("对象为空", new Object())。


结束语


请牢记:测试任何可能的错误。单元测试不是用来证明您是对的,而是为了证明您没有错。

JUnit 4 到这里就差不多了,如果文章中有什么不对的地方,还希望各位大牛拍砖。说了这么多,能真正用上才是王道,当然,希望以我这篇文章为契机,IT 界的精英们,之前没有用单元测试的,能够唤醒你们体内的小宇宙;之前已经在用的,也能够再体会一番,提高开发的效率,写出 漂亮 的代码。

测试工具 TestNG

前言


上一篇文章《测试工具 JUnit 4》中提到了 JUnit 4,并对 JUnit 4 做了简单的讨论,这篇文章我们将要围绕另一款测试工具讨论 —— TestNG。其实,这篇文章应该写在《测试工具 JUnit 3》之后,和《测试工具 JUnit 4》之前,为什么这么说呢?

那是因为,TestNG 是在 JUnit 3 之后出来了,而 JUnit 4 是在 TestNG 推出之后,综合 JUnit 3 的优点,并且借鉴了 TestNG 的优势,才推出的。但是,考虑到,JUnit 3 、4 都是 JUnit 系列的,所以就放到一块了,而没有把他们分开。所以,大家知道这里的关系就好了。


简介


TestNG是一个用来简化广泛的测试需求的测试框架,从单元测试(隔离测试一个类)到集成测试(测试由多个类多个包甚至多个外部框架组成的整个系统,例如应用服务器)。


步骤

  • 编写测试的业务逻辑并在代码中插入 TestNG Annotation
  • 将测试信息添加到 testng.xml 文件或者 build.xml 中
  • 运行 TestNG


一些概念

  • suite(套件)
由 xml 文件描述,它包含一个或多个测试并被定义为 <suite> 标签。

  • test(测试)
由 <test> 描述,并包含一个或者多个 TestNG 类。

  • class(类)
由一个或多个方法组成。


注解

  • @BeforeSuite
被注解的方法,会在当前 suite 中所有测试方法执行之前被调用。

  • @AfterSuite
被注解的方法,会在当前 suite 中所有测试方法执行之后被调用。

  • @BeforeTest
被注解的方法,会在测试(原文就是测试,不是测试方法)运行之前被调用。

  • @AfterTest
被注解的方法,会在测试(原文就是测试,不是测试方法)运行之后被调用。

  • @BeforeGroups
被注解的方法,会在执行组列表中之前被调用。这个方法会在每个组中第一次测试方法调用之前被调用。

  • @AfterGroups
被注解的方法,会在执行组列表中之后被调用。这个方法会在每个组中最后一个测试方法调用之后被调用。

  • @BeforeClass
被注解的方法,会在当前类第一个测试方法运行之前被调用。

  • @AfterClass
被注解的方法,会在当前类所有测试方法运行之后被调用。

  • @BeforeMethod
被注解的方法,会在运行每个测试方法之前被调用。

  • @AfterMethod
被注解的方法,会在每个测试方法运行之后被调用 。


配置


调用 TestNG 有几种不同的方法,使用 testng.xml 文件,使用 ant ,从命令行敲命令。当然,使用 Java IDE的话,可以不用写 testng.xml 文件,不过不代表用不到,只不过是 IDE 会自动生成一个 testng.xml 文件,不用你再手动的写了。 如果从学习的角度来看,testng.xml 文件的配置,我们还是要学的,最起码要了解它是怎么配置的,以便看到它了不会感到陌生。

testng.xml 文件可以到  testng 的官网去 copy ,官网介绍的很详细(如果你英文还说的过去,建议去官网)。

  1. <span style="font-family:Microsoft YaHei;"><!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd" >  
  2.     
  3. <suite name="Suite1" verbose="1" >  
  4.   <test name="Nopackage" >  
  5.     <classes>  
  6.        <class name="NoPackageTest" />  
  7.     </classes>  
  8.   </test>  
  9.    
  10.   <test name="Regression1">  
  11.     <classes>  
  12.       <class name="test.sample.ParameterSample"/>  
  13.       <class name="test.sample.ParameterTest"/>  
  14.     </classes>  
  15.   </test>  
  16. </suite></span>  

当然,你还可以指定包名替代类名,就像这样:

  1. <span style="font-family:Microsoft YaHei;"><!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd" >  
  2.   
  3. <suite name="Suite1" verbose="1" >  
  4.   <test name="Regression1"   >  
  5.     <packages>  
  6.       <package name="test.sample" />  
  7.    </packages>  
  8.  </test>  
  9. </suite></span>  

不止这些,你同样可以指定包含或不包含的组和方法,Such as:

  1. <span style="font-family:Microsoft YaHei;"><test name="Regression1">  
  2.   <groups>  
  3.     <run>  
  4.       <exclude name="brokenTests"  />  
  5.       <include name="checkinTests"  />  
  6.     </run>  
  7.   </groups>  
  8.     
  9.   <classes>  
  10.     <class name="test.IndividualMethodsTest">  
  11.       <methods>  
  12.         <include name="testMethod" />  
  13.       </methods>  
  14.     </class>  
  15.   </classes>  
  16. </test></span>  

你同样可以在 testng.xml 中定义新的组,指定属性的额外详细情况,比如:是否并行运行测试,使用多少线程,是否运行 JUnit 测试,等等。。。

至于,运行 TestNG 的那些命令,官网上已经说的很清楚了,如果你需要中文的资料,那么我不会告诉你去找 Goo哥 或者 Baidu,这里就不再赘述了。需要注意一点的是,TestNG 需要的 JDK 版本是 1.5 以上的。为什么这样,想想 JDK 1.5 的新特性,我想你已经知道了,这里就不再废话了。


生命周期


使用 TestNG,不仅可以指定测试方法,还可以用专门的标注 @Configuration指定类中的其他特定方法,这些方法叫做 配置方法。配置方法有四种类型:
  • beforeTestClass 方法在类实例化之后,但是在测试方法运行之前执行。
  • afterTestClass 方法在类中的所有测试方法执行之后执行。
  • beforeTestMethod 方法在类中的任何测试方法执行之前执行。
  • afterTestMethod 方法在类中的每个测试方法执行之后执行。




结束语


本篇文章,主要是介绍了 TestNG 的基本功能,当然,TestNG 是非常强大的,这里没有时间细说,最后分享一个小例子,想学 TestNG 的可以下载下来运行一下。例子非常简单,可以通过与 JUnit 4 的例子进行对比,你就会发现,其实,他们还是都差不多的。毕竟,JUnit 4 也借鉴了 TestNG 的设计。

学好测试,编写健壮、漂亮的代码,节省下更多的时间学学新技术,陪陪家人,不也都挺好嘛。干嘛非要跟自己过不去,让那些混乱的代码逼着自己加班,你说是吧?




  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值