美文网首页
Android单元测试(一):JUnit框架的使用

Android单元测试(一):JUnit框架的使用

作者: a0f39b0b2030 | 来源:发表于2018-10-31 18:21 被阅读9次

1.前言

网上有许多关于单元测试的好处,这里我就不去说了。我写单元测试的理由很简单粗暴,就是图一个方便。试想一下这个场景:我们在写一个新功能,每写一部分,我们就安装到手机上查看一下,这个过程中你要点击到对应的页面,做对应的操作,最后才能反馈给你结果。如果达到了预期效果,那么恭喜你。可是一旦这次失败了,是不是又要重复这一过程?是不是感到很麻烦?很费时间?如果你想早点写完下班,那么你就需要掌握单元测试。因为它能大大的缩短你自我验证的时间。

2.准备工作

我们新建一个项目,模板代码会默认在build文件中添加JUnit的依赖,而单元测试代码是放在src/test/java下面的,如下图:

用鼠标右键点击测试方法,选择菜单中的“Run”选项就可以执行对应的单元测试。我执行了图中的测试代码,可以看到执行方法只用了6毫秒,整个过程不到2秒。

3.JUnit介绍

JUnit是Java最基础的测试框架,主要的作用就是断言。

使用时在app的build文件中添加依赖。注意:用于测试环境框架一律是testCompile开头。

dependencies {

testCompile ‘junit:junit:4.12’

}

1

2

3

Assert类中主要方法如下:

方法名方法描述

assertEquals断言传入的预期值与实际值是相等的

assertNotEquals断言传入的预期值与实际值是不相等的

assertArrayEquals断言传入的预期数组与实际数组是相等的

assertNull断言传入的对象是为空

assertNotNull断言传入的对象是不为空

assertTrue断言条件为真

assertFalse断言条件为假

assertSame断言两个对象引用同一个对象,相当于“==”

assertNotSame断言两个对象引用不同的对象,相当于“!=”

assertThat断言实际值是否满足指定的条件

注意:上面的每一个方法,都有对应的重载方法,可以在前面加一个String类型的参数,表示如果断言失败时的提示。

JUnit 中的常用注解:

注解名含义

@Test表示此方法为测试方法

@Before在每个测试方法前执行,可做初始化操作

@After在每个测试方法后执行,可做释放资源操作

@Ignore忽略的测试方法

@BeforeClass在类中所有方法前运行。此注解修饰的方法必须是static void

@AfterClass在类中最后运行。此注解修饰的方法必须是static void

@RunWith指定该测试类使用某个运行器

@Parameters指定测试类的测试数据集合

@Rule重新制定测试类中方法的行为

@FixMethodOrder指定测试类中方法的执行顺序

执行顺序:@BeforeClass –> @Before –> @Test –> @After –> @AfterClass

4.JUnit用法

我们测试下面这个简单的时间转换工具类,来说明一下具体的用法。

public class DateUtil {

/**

* 英文全称  如:2017-11-01 22:11:00

*/

public static String FORMAT_YMDHMS = "yyyy-MM-dd HH:mm:ss";

/**

* 掉此方法输入所要转换的时间输入例如("2017-11-01 22:11:00")返回时间戳

*

* @param time

* @return 时间戳

*/

public static long dateToStamp(String time) throws ParseException{

    SimpleDateFormat sdr = new SimpleDateFormat(FORMAT_YMDHMS, Locale.CHINA);

    Date date = sdr.parse(time);

    return date.getTime();

}

/**

* 将时间戳转换为时间

*/

public static String stampToDate(long lt){

    String res;

    SimpleDateFormat simpleDateFormat = new SimpleDateFormat(FORMAT_YMDHMS, Locale.CHINA);

    Date date = new Date(lt);

    res = simpleDateFormat.format(date);

    return res;

}

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

}

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

1.基础用法

1.首先测试stampToDate方法,测试时我认为返回的结果等于“预期时间”这个字符串。测试方法执行后如下图:

可以看到预期值与实际结果不符,测试失败!想要测试成功要么预期值为”2017-10-15 16:00:02”要么使用assertNotEquals方法断言。

2.接下来测试dateToStamp方法。

很简单,我认为返回结果不等于4,结果测试通过。

3.我们注意到在dateToStamp方法中,有抛出一个解析异常(ParseException)。也就是当参数没有按照规定格式去传,就会导致这个异常。

那我们怎么验证一个方法是否抛出了异常呢?可以给@Test注解设置expected参数来实现,如下:

抛出了对应的异常则测试成功,反之则测试失败。

2.参数化测试

这时,你是不是觉得还是很麻烦,因为每次测试一个方法都要去设置对应的值,就不能连续用不不同的值去测试一个方法,省的我们不断地修改。这时就用到了@RunWith与@Parameters。

首先在测试类上添加注解@RunWith(Parameterized.class),在创建一个由 @Parameters 注解的public static方法,让返回一个对应的测试数据集合。最后创建构造方法,方法的参数顺序和类型与测试数据集合一一对应。

上图就是一个简单的例子,可以看到连续执行了三次测试,其中第二次测试没有抛出异常,测试失败!

3.assertThat用法

上面我们所用到的一些基本的断言,如果我们没有设置失败时的输出信息,那么在断言失败时只会抛出AssertionError,无法知道到底是哪一部分出错。而assertThat就帮我们解决了这一点。它的可读性更好。

assertThat(T actual, Matcher<? super T> matcher);

assertThat(String reason, T actual, Matcher matcher);

1

2

3

4

其中reason为断言失败时的输出信息,actual为断言的值,matcher为断言的匹配器。

常用的匹配器整理:

匹配器说明例子

is断言参数等于后面给出的匹配表达式assertThat(5, is (5));

not断言参数不等于后面给出的匹配表达式assertThat(5, not(6));

equalTo断言参数相等assertThat(30, equalTo(30));

equalToIgnoringCase断言字符串相等忽略大小写assertThat(“Ab”, equalToIgnoringCase(“ab”));

containsString断言字符串包含某字符串assertThat(“abc”, containsString(“bc”));

startsWith断言字符串以某字符串开始assertThat(“abc”, startsWith(“a”));

endsWith断言字符串以某字符串结束assertThat(“abc”, endsWith(“c”));

nullValue断言参数的值为nullassertThat(null, nullValue());

notNullValue断言参数的值不为nullassertThat(“abc”, notNullValue());

greaterThan断言参数大于assertThat(4, greaterThan(3));

lessThan断言参数小于assertThat(4, lessThan(6));

greaterThanOrEqualTo断言参数大于等于assertThat(4, greaterThanOrEqualTo(3));

lessThanOrEqualTo断言参数小于等于assertThat(4, lessThanOrEqualTo(6));

closeTo断言浮点型数在某一范围内assertThat(4.0, closeTo(2.6, 4.3));

allOf断言符合所有条件,相当于&&assertThat(4,allOf(greaterThan(3), lessThan(6)));

anyOf断言符合某一条件,相当于或assertThat(4,anyOf(greaterThan(9), lessThan(6)));

hasKey断言Map集合含有此键assertThat(map, hasKey(“key”));

hasValue断言Map集合含有此值assertThat(map, hasValue(value));

hasItem断言迭代对象含有此元素assertThat(list, hasItem(element));

下图为使用assertThat测试失败时所显示的具体错误信息。可以看到错误信息很详细!

当然了匹配器也是可以自定义的。这里我自定义一个字符串是否是手机号码的匹配器来演示一下。

只需要继承BaseMatcher抽象类,实现matches与describeTo方法。代码如下:

public class IsMobilePhoneMatcher extends BaseMatcher {

/**

* 进行断言判定,返回true则断言成功,否则断言失败

*/

@Override

public boolean matches(Object item) {

    if (item == null) {

        return false;

    }

    Pattern pattern = Pattern.compile("(1|861)(3|5|7|8)\\d{9}$*");

    Matcher matcher = pattern.matcher((String) item);

    return matcher.find();

}

/**

* 给期待断言成功的对象增加描述

*/

@Override

public void describeTo(Description description) {

    description.appendText("预计此字符串是手机号码!");

}

/**

* 给断言失败的对象增加描述

*/

@Override

public void describeMismatch(Object item, Description description) {

    description.appendText(item.toString() + "不是手机号码!");

}

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

}

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

执行单元测试如下:

正确的手机号码测试成功:

直播系统开发找上海捌跃网络科技有限公司QQ3343874032

错误号码测试失败:

5.@Rule用法

还记得一开始我们在@Before与@After注解的方法中加入”测试开始”的提示信息吗?假如我们一直需要这样的提示,那是不是需要每次在测试类中去实现它。这样就会比较麻烦。这时你就可以使用@Rule来解决这个问题,它甚至比@Before与@After还要强大。

自定义@Rule很简单,就是实现TestRule 接口,实现apply方法。代码如下:

public class MyRule implements TestRule {

@Override

public Statement apply(final Statement base, final Description description) {

    return new Statement() {

        @Override

        public void evaluate() throws Throwable {

            // evaluate前执行方法相当于@Before

            String methodName = description.getMethodName(); // 获取测试方法的名字

            System.out.println(methodName + "测试开始!");

            base.evaluate();  // 运行的测试方法

            // evaluate后执行方法相当于@After

            System.out.println(methodName + "测试结束!");

        }

    };

}

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

}

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

我们使用一下我们自定义的MyRule,效果如图:

原文:https://blog.csdn.net/qq_17766199/article/details/78243176

相关文章

  • 安卓单元测试 - 收藏集 - 掘金

    Android 单元测试 (三):JUnit 单元测试框架的使用 - Android - 掘金 我们写单元测试,一...

  • Robolectric框架的使用

    可以参考地址: 1.Android单元测试(一):JUnit框架的使用 2.Android单元测试(二):Mock...

  • 单元测试框架:Robolectric

    前言 前面我们介绍了单元测试框架 JUnit 和 Mockito 的使用(详情查看:单元测试框架:JUnit,单元...

  • Android Junit 单元测试、异步测试方法简介及异步测试

    Android Junit 单元测试、异步测试方法简介及异步测试框架指南 本文解决的问题 1. 如何使用junit...

  • android测试

    1.单元测试 针对每个方法进行的测试。主要使用JUnit框架进行测试。(JUnit只适用于不含android sd...

  • Junit

    Junit 1.简介 Junit是java程序的单元测试框架,包含于xunit系列框架 2.Junit使用 2.1...

  • Junit学习

    本文是对唯鹿_Android单元测试(一):JUnit框架的使用的学习笔记 需要进行测试的工具类 1.用单个数据进...

  • Instrumentation

    1、Instrumentation单元测试框架,基于Junit;Junit是java单元测试根本 2、想要进行自动...

  • SpringBoot的RestApi接口的单元测试

    记录一下SpringBoot的RestApi接口的单元测试 1.使用的junit单元测试框架,所以需要加入依赖。 ...

  • JUnit

    JUnit是一个编写测试代码的框架,它是单元测试框架的xUnit体系结构中的一个,目前主要使用的是JUnit 4 ...

网友评论

      本文标题:Android单元测试(一):JUnit框架的使用

      本文链接:https://www.haomeiwen.com/subject/bpxztqtx.html