在文章开始之前先给大家安利一个网站:http://www.vogella.com/ ,这个网站上写得内容都非常的好,只可惜是英文网站,不过这正好是个学习英语的机会! 所以我根据自己的理解将这个网站的部分博客翻译了一下,能力有限如有翻译错误还望留言指正。
有很多地方无法完全用中文来描述,所以部分还是使用英文。
什么是JUnit框架
JUnit是一个单元测试框架,它使用注解的形式来指定需要测试的方法。JUnit是个开源项目并托管在GitHub上(https://github.com/junit-team/junit)
如何使用JUnit进行测试?
JUnit测试其实就是执行一个类中的方法,并且这个类仅用于测试,称之为测试类(Test Class),这个方法使用 @Test 注解标注。
这个方法执行待测试的代码,你可以通过使用JUnit或者其他的Assert(断言)框架提供的Assert相关的方法来检查预期结果和实际结果是否相符。这些方法的调用通常称之为断言(asserts )或者断言语句(assert statements)。
在开发中应该在断言语句中提供一些有意义的信息。这会使得开发者更容易去定位和修复问题。
测试代码放置的位置
一般典型的单元测试是放在单独的项目中或者是在单独的源文件中创建的,以便将测试代码和实际的代码分开。maven和Gradle构建工具的标准约定就是:
- src/main/java - 用于Java类
- src/test/java - 用于测试类
IDEA或Android Studio的测试文件路径:
JUnit的示例代码
下面的代码展示了基本的JUnit 4.x版本的JUnit单元测试,该测试假定MyClass类存在并且含有一个multiply(int, int)方法。并使用断言语句来断言multiply方法的正确性。
package com.lulu.androidtestdemo;
import com.lulu.androidtestdemo.junit.testexample.MyClass;
import org.junit.Test;
import org.junit.runner.JUnitCore;
import org.junit.runner.Result;
import org.junit.runner.notification.Failure;
import static org.junit.Assert.assertEquals;
/**
* Created by zhanglulu on 2018/1/23.
*/
public class MyClassTest {
@Test
public void multiplicationOfZeroIntegersShouldReturnZero() {
MyClass tester = new MyClass(); // MyClass is tested
// assert statements
assertEquals("0 x 0 must be 0",0, tester.multiply(0, 0));
assertEquals("0 x 10 must be 0", 0, tester.multiply(0, 10));
assertEquals("10 x 0 must be 0", 0, tester.multiply(10, 0));
Result result = JUnitCore.runClasses(CalculatorTest.class);
for (Failure failure : result.getFailures()) {
System.out.println(failure.toString());
}
}
}
JUnit命名约定
JUnit 测试有几个潜在命名约定。一种广泛的解决方案就是在测试类的名字末尾添加 “Test” 后缀。
作为一般的规则,每个测试方法的名称应该明确说明当前的测试任务。如果该测试方法正确地完成了,就避免了再去实际代码中查看实现逻辑。
还有一种约定就是在测试方法名称中使用“should"。例如,"ordersShouldBeCreated"或者”menuShouldGetActive"。这样就可以提示我们这个测试方法都做了什么。
另一种方法是用“Given[ExplainYourInput]When[WhatIsDone]Then[ExpectedResult]”来作为测试方法的名字。
当然这些命名约定并不是严格的规定,所以没有严格的要求让我们在单元测试用例中保持这样的书写习惯,但是统一一种书写方式在合作开发中还是非常重要的。
从命令行中运行测试
你还可以通过使用标准的Java代码在IDE之外运行JUnit测试。
org.junit.runner.JUnitCore类提供了runClasses()方法。这个方法允许你运行一个或者多个测试类。它将返回org.junit.runner.Result类型的对象。这个对象可用于检索有关测试的信息。
下面的类用来演示如何运行MyClassTest。并将该类执行产生的错误信息打印在控制台上。
package com.lulu.androidtestdemo;
import org.junit.runner.JUnitCore;
import org.junit.runner.Result;
import org.junit.runner.notification.Failure;
/**
* Created by zhanglulu on 2018/1/23.
*/
public class MyTestRunner {
public static void main(String[] args) {
Result result = JUnitCore.runClasses(MyClassTest.class);
for (Failure failure : result.getFailures()) {
System.out.println(failure.toString());
}
}
}
上面中的Java类可以在命令行工具中直接执行,并输出执行失败的测试方法的信息。
测试执行顺序
JUnit假定所有的测试方法都可以按任意的顺序执行。质量高的测试代码不应该假定任何的顺序,就是说,一段测试代码不能依赖其他的测试代码。
在JUnit4.11中,默认使用的是确定的但不可预测的顺序来执行测试的(As of JUnit 4.11 the default is to use a deterministic, but not predictable, order for the execution of the tests.)
当然你可以使用注解的方式来定义测试方法的名称以字典顺序排序。如果想开启此功能,需要使用@FixMethodOrder(MethodSorters.NAME_ASCENDING)注解标注这个测试类,你也可以通过设置MethodSorters.DEFAULT参数来明确使用默认值。也可以使用MethodSorters.JVM明确它使用JVM的默认值。
Note:这个注解标记是放在测试类上的,但是在真正写测试方法时一般不会指定顺序。