单元测试概述&TestNG(一)

主要内容:
● 概述单元测试相关概念及意义
● TestNG、Mockito、Unitils测试框架简介
● 使用TestNG、Mockito、Unitils及Spring进行单元测试
● 面向数据库应用的测试

1.概述单元测试

按照软件工程思想,软件测试可以分为单元测试、集成测试、功能测试、系统测试。功能测试和系统测试一般来说是测试人员的职责,但单元测试和集成测试则必须由开发人员保证。

1.1为什么需要单元测试?

软件测试阶段通过人工或自动手动来运行或测试某个系统的过程,目的在于检验它是否满足规定的需求或弄清楚预期结果与实际结果的差别。

单元测试

单元测试是开发者编写的一小段代码,用于检验目标代码的一个很小的、很明确的功能是否正确。一个单元测试通常用于判断某个特定条件或特定场景下某个特定函数的行为。例如:用户可能把一个很大的值放入一个有序的List中,然后确认该值出现在List的尾部。

程序员有责任编写功能代码,同时也有责任为自己的代码编写单元测试。执行单元测试,就是为了证明这段代码的行为和我们期望的一致。

一般情况下,一个功能模块往往会调用其他功能模块来完成某项功能,如业务层的业务类可能会调用多个DAO来完成某项业务。对某个功能模块进行单元测试时,我们希望拼比对外在功能模块的依赖,以便将焦点放在目标功能模块的测试上。这时,模拟对象是最有力的工具,它根据外在模块的接口模拟特定的操作行为,这样单元测试就可以在假设关联模块正确工作的情况下验证本模块的逻辑正确性。

集成测试

集成测试在功能模块开发完成后,为验证功能模块之间匹配调用的正确性而进行的测试。如:当对UserService业务层的类进行单元测试时,可以通过创建UserDao和LoginLogDao模拟对象,在假设DAO类正确工作的情况下对UserService进行测试。而对UserService进行集成测试时,应注入真实的UserDao和LoginLogDao进行测试。

1.2.单元测试的好处

  • 软件质量最简单、最有效的保证。
  • 是目标代码最清晰、最有效的文档。
  • 可以优化目标代码的设计。
  • 是代码重构的保障。

1.3 单元测试的误解

  • 影响开发进度
  • 增加开发成本
  • 我是个编程高手,无需进行单元测试
  • 测试人员会测出所有的bug

2.TestNG快速进阶

编写一个测试的过程由3个典型步骤。
1.编写测试的业务逻辑并在代码中插入TestNG注解
2.将测试信息添加到testng.xml或者build.xml文件中
3.运行TestNG

2.1TestNG生命周期

完整生命周期:类级初始化资源处理、方法级初始化资源处理、执行测试用例中的方法、方法级销毁资源处理、类级销毁资源处理。
类级初始化、销毁资源处理方法在一个测试用例类中只能运行一次;
方法级初始化、销毁资源处理方法在执行测试用例的每个测试方法中都会运行一次,以防止测试方法相互之间的影响。


测试用例的执行过程

如果在一个测试用例中编写了多个初始化处理方法,则运行时先执行位于最后面的初始化方法,然后往前一个个执行初始化方法。对于多个销毁资源处理方法,则按照方法的顺序一个个往后执行。

2.2使用TestNG

1.测试方法

使用@Test注解来标注一个测试方法。此外可以引用Java5.0的静态导入功能导入断言Assert类,方便地在测试方法中使用断言方法。

public class TestNGTest {

    private Car audi;
    private Car benz;
    private Car bmw;

    @BeforeMethod
    protected void setUp() {
        audi = new Car("yellow","audi",180);
        benz = new Car("white","benz",220);
        bmw = new Car("black","bmw",190);
    }

    @Test
    private void getBean() {
        Assert.assertEquals("audi", audi.getBrand());
    }

}

在TestNG中,在测试方法添加@Test注解即可。
@BeforeClass @AfterClass 在一个Test类的所有测试方法执行前后各执行一次

@BeforeClass/@AfterClass @BeforeMethod/@AfterMethod
在一个类中只能出现一次 在一个类可出现多次,执行顺序不确定
方法名不限制 方法名不限制
类中只执行一次 在每个测试方法之前或者之后都会执行一次
@BeforeClass父类中标识了该注解的方法将会先于当前类中标识了该注解的方法执行。
@AfterClass父类中标识了该注解的方法将会在当前类中标识了该注解的方法之后执行。
@BeforeMethod父类中标识了该注解的方法将会先于当前类中标识了该注解的方法执行。
@AfterMethod父类中标识了该注解的方法将会在当前类中标识了该注解的方法之后执行。
必须声明为public static 必须声明为public,并且非static
所有标识为@AfterClass的方法一定会被执行,即使标识为@BeforeClass的方法抛出异常的情况下也会执行 所有标识为@AfterMethod的方法一定会被执行,即使标识为@BeforeMethod或@Test的方法抛出异常的情况下也会执行

2.异常测试

通过对@Test传入expected参数值,即可测试异常。

3.超时测试

通过对@Test注解中为timeOut参数指定时间值,即可进行超时测试。
如果测试运行时间超过指定的毫秒数,即测试失败。超时测试对网路链接类非常重要。


4.参数化测试

为了测试程序的健壮性,可能需要模拟不同的参数对方法进行测试。如果每个类型的参数创建一个测试方法,很难接受。TestNG提供参数化测试。

package sample.testng;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import static org.testng.Assert.*;
import org.testng.annotations.*;


public class TestNGParameterTest {
    private SimpleDateFormat simpleDateFormat;

    @DataProvider(name = "testParam")
    public static Object[][] getParamters() {
        String[][] params = {
                { "2016-02-01 00:30:59", "yyyyMMdd", "20160201" },
                { "2016-02-01 00:30:59", "yyyy年MM月dd日", "2016年02月01日" },
                { "2016-02-01 00:30:59", "HH时mm分ss秒", "00时30分59秒" } };
         return params;
    }

    @Test(dataProvider = "testParam")
    public void testSimpleDateFormat(String date,String dateformat,String expectedDate) throws ParseException{
        SimpleDateFormat df  = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Date d = df.parse(date);
        simpleDateFormat = new SimpleDateFormat(dateformat);
        String result = simpleDateFormat.format(d);
        assertEquals(result,expectedDate);
    }

}

首先编写测试类的参数数据提供者方法,然后用此方法进行参数初始化。该方法返回一个Object[][]类型。用@DataProvider注解标识该方法并设置name。之后在需要测试的方法中设置@Test(dataProvider="")属性。

5.分组测试

TestNG支持执行复杂的分组测试。


@Test(groups = {"class-group"})
public class TestNGGroupsTest {

    @Test(groups = {"group1", "group2"})
    public void testMethod1() {
    }

    @Test(groups = {"group1", "group2"})
    public void testMethod2() {
    }

    @Test(groups = {"group1"})
    public void testMethod3() {
    }

}

6.依赖测试

如果测试方法需要按照一个特定的顺序被调用。TestNG为@Test注解提供了dependsOnMethods或dependsOnGroups属性来实现测试方法间的依赖关系。

public class TestNGDependsTest {

    @Test
    public void testMethod1() {
    }

    @Test
    public void testMethod2() {
        assertNotNull(new User());
    }

    @Test(dependsOnMethods = {"testMethod1","testMethod2"},alwaysRun=true)
    public void testMethod3() {

    }

}

当执行testMethod3()测试方法时,会先调用两个依赖的测试方法。如果testMethod1()或testMethod2()任意一个失败都不会执行testMethod3()。这种依赖为强依赖,默认。可以通过@Test的alwaysRun=true改变,则testMethod3()总会执行。

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

推荐阅读更多精彩内容