JUnit之TestCase和TestSuite详解

Android Studio下单元测试的本质其实是根据通过书写JAVA测试代码,通过模拟用户调用相应的方法,或者使用者按下相应的按键来验证我们的代码的逻辑是否能达到预期的要求,如果所有的用例都能通过,则证明我们的逻辑满足要求,否则,可以通过fail()函数(或使用Assert)进行输出错误信息。

在进行测试前我们首先需要了解一下几个基本的概念:TestCase,TestSuite:

(图1)

如图1所示,TestSuite和TestCase都是继承自Test接口,同时,TestSuite的建立和使用依赖于TestCase实例,TestCase继承自Assert类,因此TestCase中可以直接使用Assert中的相关方法,Assert类提供了几个常用的判断方法,Assert的类图可以参照图2:

(图2)

TestCase:

在进行单元测试的时候,在JUNIT4之前,我们需要测试的代码所在的类一般都需要直接或者间接继承自TestCase,对于我们创建的这个TestCase的子类,我们需要注意在我们这个类的测试流程,假设我们创建的TestCase子类中有两个测试用例testMethod1和testMethod2,则执行顺序可以如图3所示:

(图3)

对于我们类中的两个测试用例testMethod1和testMethod2,都会分别创建一个新的TestCase子类对象,并引起TestCase中的setUp和tearDown函数分别执行一遍,因此,在进行单元测试的过程中,我们可以在setUp当中进行一些初始化操作(如类的某些属性的赋值操作),在tearDown中进行一些扫尾工作(如类中某些对象所持有资源的释放)。

一个简单的Demo:

import junit.framework.TestCase;

public class TestDemo extends TestCase{

@Override

protected void setUp() throws Exception {

// TODO Auto-generated method stub

super.setUp();

System.out.println("setUp , hashCode = "+hashCode());

}

@Override

protected void tearDown() throws Exception {

// TODO Auto-generated method stub

super.tearDown();

System.out.println("tearDown,hashCode = "+hashCode());

}

public void testMethod1(){

System.out.println("testMethod1 , hashCode = "+hashCode());

}

public void testMethod2(){

System.out.println("testMethod2 , hashCode = "+hashCode());

}

}

运行结果,如图4所示:

(图4)

有两个test函数,testMethod1和testMethod2,在生命周期的开始函数setUp以及结尾函数tearDown中分别产生了两次不同的hashCode,根据Java语言中HashCode的概念我们可以知道这分别导致了我们的TestDemo类型的对象创建了两次。因此如果测试的case增多,我们的TestDemo对象也会创建和case相同的个数。

对于测试用例testMethod1和testMethod2的函数声明,在我们书写用例函数的时候需要注意他们有一个共同的特点:

1).访问权限都是public;

2).返回类型都是void;

3).没有参数;

4).方法名以“test”开头。

在使用单元测试的时候必须注意用例方法的生命格式,否则该用例将不会被执行的到。

TestSuite:

对于suite这个英文单词,从字面上可以理解为组合或者集合的意思,再加上通过图1,我们发现TestSuite和TestCase都是实现自Test接口,这很容易让我们想起JAVA设计模式中的合成模式的概念:即TestSuite可以认为合成模式中的组,是一组TestCase对象的集合;而TestCase对象时这个合成模式中的叶子对象,并且,这些TestCase对象(叶子对象)和TestSuite(组对象)拥有共同的行为(run方法);这样,可以保证当用户调用组对象TestSuite的run方法的时候,也会调用到TestCase对象的run方法。而事实上也确实是这样,在使用JUnit3执行测试的过程中,会首先创建TestSuite对象,在TestSuite对象的构造方法中,会扫描TestCase子类的所有方法,并调用addTestMethod方法,在该方法中调用isPublicTestMethod方法判断是否是待测的方法,若是会调用createTest方法,创建一个Test对象,并调用addTest方法加入到自己的集合中去,因此执行过程中的TestCase子类都会以具体的test方法个数创建自身实例的个数,并加入到TestSuite中,TestSuite的相对详细的类图如图5所示:

(图5)

一个简单的例子了解一下TestSuite:

import junit.framework.Test;

import junit.framework.TestCase;

import junit.framework.TestSuite;

public class TestSuiteDemo extends TestSuite{

public static Test suite(){

//创建TestSuite对象

TestSuite suite = new TestSuite();

//为TestSuite添加一个测试用例集合,参数为:ClasstestClass

//通过参数可以知道,其实该参数就是TestCase的子类

suite.addTestSuite(TestDemo.class);

//创建具体的测试用例

Test test = TestSuite.createTest(TestDemo.class, "testMethod1");

//添加一个具体的测试用例

suite.addTest(test);

return suite;

}

}

执行结果如图6:

(图6)

通过代码和运行结果,我们可以看出testMethod1执行了两次而testMethod2只执行了一次,通过分析上述代码得出testMethod1执行两次的原因是:第一次是在addTestSuite的时候将其作为一个测试用例传入到TestSuite中,第二次是通过addTest方法将用例加入到TestSuite中,因此在执行的时候将其执行了两遍,通过比较hashCode得出总共创建了三个TestCase对象的结论。

通过上述代码,我们需要强调一下,如果我们想一次执行一组TestCase实现类的测试,这个时候可以自定义TestSuite对象,将需要测试的TestCase实现类加入到TestSuite中去。我们需要了解TestSuite如何使用,其实TestSuite的使用也很简单,在TestSuite的使用的时候,我们必须在TestSuite的实现类中,自定义suite方法,由于suite方法会通过反射调用,反射调用代码如下:

public static Test testFromSuiteMethod(Classklass) throws Throwable {

Method suiteMethod= null;

Test suite= null;

try {

suiteMethod= klass.getMethod("suite");

if (! Modifier.isStatic(suiteMethod.getModifiers())) {

throw new Exception(klass.getName() + ".suite() must be static");

}

suite= (Test) suiteMethod.invoke(null); // static method

} catch (InvocationTargetException e) {

throw e.getCause();

}

return suite;

}

所以suite方法命名规则如下:

1).必须以“suite”方法命名;

2).suite方法的访问修饰权限必须为static;

3).suite方法必须为静态方法;

4).suite方法必须没有参数。

总结:

TestCase和TestSuite类是JUNIT中比较重要的两个类,TestCase和TestSuite可以认为是JAVA的合成设计模式在单元测试中的应用,其实即便我们没有自己声明和创建TestSuite的子类,而且运行的TestCase子类的过程中也会创建TestSuite类,并将要执行的TestCase子类的实例对象添加到TestSuite中去执行,其执行过程可以如图7所示:

(图7)

在选择JUnit执行引擎的时候,便创建了TestSuite对象,并通过上面介绍TestSuite介绍过的addTestMethod,creatTest,addTest方法,将要测的TestCase类中的所有测试用例给扫描出来,并添加到待测列表中去。在执行JUnit测试引擎的run方法时会调用TestSuite的的run方法,TestSuite在执行自身run方法时会遍历所有TestCase对象的run方法,同一个TestCase子类的run方法会根据自身所包含的测试用例个数被执行相应的次数。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,332评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,508评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,812评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,607评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,728评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,919评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,071评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,802评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,256评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,576评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,712评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,389评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,032评论 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,798评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,026评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,473评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,606评论 2 350

推荐阅读更多精彩内容

  • 1. Java基础部分 基础部分的顺序:基本语法,类相关的语法,内部类的语法,继承相关的语法,异常的语法,线程的语...
    子非鱼_t_阅读 31,598评论 18 399
  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,637评论 18 139
  • Startup 单元测试的核心价值在于两点: 更加精确地定义某段代码的作用,从而使代码的耦合性更低 避免程序员写出...
    wuwenxiang阅读 10,090评论 1 27
  • 不知道大家有没有过这种感觉,喜欢着一个明明不爱自己的人,也知道彼此不可能,却依然爱着。 如果没有的话,那下面便可不...
    流浪汉9595阅读 1,738评论 0 1