-
断言:用于验证期望值ecpected和实际值 之间的逻辑关系。
- assertEquals([message], expected, actual) //message表示自定义错误信息,可选
- 可以验证两个数是否相等,可以验证期望对象的引用过于实际对象的的引用是否指向同一个对象
- assertNull([message], object)
- 断言某个对象为Null
- assertNotNull([message], object)
- 断言某个对象不为Null
- assertTrue([message], condition)
- 验证条件为真
- assertFalse([message], condition)
- 验证条件为假
- assertEquals([message], expected, actual) //message表示自定义错误信息,可选
-
断言使用不够灵活,必须使用一个固定的expected的值。使得测试不太灵活
-
解决:使用Hamcrest类库:
- 该库提供一个assertThat类型的断言提供以下方法:
-
字符串相关匹配符:
startsWith
endWith
containsWith
equalTolgnoringCase
equalTolgnoringWhiteSpace
//对字符串的操作
assertThat("android studio", startsWith("and"));
assertThat("android studio", endsWith("and"));
assertThat("android studio", containsString("and"));
assertThat("android studio", equalToIgnoringCase("and"));
assertThat("android studio", equalToIgnoringWhiteSpace("android studio"));
- 数值相关匹配符:
close to
greaterThan
lessThan
lessThanOrEqualTo
greaterThanOrEqualTo
//对数字的操作
assertThat(10.6, closeTo(10.5,0.2));
assertThat(10.6, greaterThan(10.5));
assertThat(10.6, lessThan(10.7));
assertThat(10.6,lessThanOrEqualTo(10.6));
assertThat(10.6, greaterThanOrEqualTo(10.4));
- 集合相关匹配符:
hasEntry
hasKey
hasValue
hasItem
hasItems
hasItemInArray
// 对集合的操作
Map<String,String> map = new HashMap<String, String>(); map.put("a", "hello");
map.put("b", "world");
map.put("c", "wjx");
assertThat(map, hasEntry("a","hello"));
assertThat(map, hasKey("a"));
assertThat(map, hasValue("wjx"));
List<String> list = new ArrayList<>();
list.add("a");
list.add("b");
assertThat(list, hasItem("a"));
assertThat(list, hasItems("a", "b"));
String[] strings = new String[] {"a","b"};
assertThat(strings, hasItemInArray("a"));
- 对象相关匹配符:
notNullValue
nullValue
sameInstance
instanceOf
hasProperty
- 组合等逻辑匹配符:
allOf
anyOf
both
either
is
isA
not
any
anything
//组合逻辑测试
//两者都满足 a&&b
assertThat(10.4, both(greaterThan(10.0)).and(lessThan(10.5)));
//所有条件都满足 a&&b&&c
assertThat(10.4, allOf(greaterThan(10.0),lessThan(10.5)));
//任一条件都满足, a||b||c
assertThat(10.4, anyOf(greaterThan(10.0), lessThan(10.4)));
//两者满足一个
assertThat(10.4, either(greaterThan(10.0)).or(lessThan(10.2)));
assertThat(10., is(10.4));assertThat(10.4, is(equalTo(10.4)));
assertThat(10.4, is(greaterThan(10.3)));
String str = new String("abc");
assertThat(str, is(CoreMatchers.<String>instanceOf(String.class)));
assertThat(str, isA(String.class));
assertThat(10.4, not(10.5));
assertThat(str, not("abcd"));
assertThat(str,any(String.class));
assertThat(str, anything());
- 当我们运行一个测试类里所有测试方法时,测试方法的执行顺序并不固定
- Junit4中提供@FixMethodOrder注解来配置执行顺序,其可选值有:
- MethodSorters.NAME_ASCENDING
- MethodSorters.DEFAULT
- MethodSorters.JVM
- Junit4中提供@FixMethodOrder注解来配置执行顺序,其可选值有:
//@FixMethodOrder(MethodSorters.JVM)//随机顺序
//@FixMethodOrder(MethodSorters.NAME_ASCENDING)//名字的字典序
//@FixMethodOrder(MethodSorters.DEFAULT) //默认按照hascode的方法名的值来排序
- 使用方法介绍完了,该进入源码分析部分:
- Junit的 Main方法:
- 在org.junit.runner包下哎,有个JUnitCore.java类
- Junit的 Main方法:
private final RunNotifier notifier = new RunNotifier();
/**
* Run the tests contained in the classes named in the <code>args</code>.
* If all tests run successfully, exit with a status of 0. Otherwise exit with a
status of 1.
* Write feedback while tests are running and write
* stack traces for all failed tests after the tests all complete.
*
* @param args names of classes in which to find tests to run
*/
public static void main(String... args) {
Result result = new JUnitCore().runMain(new RealSystem(), args);
System.exit(result.wasSuccessful() ? 0 : 1);
}
再往下看:
Result runMain(JUnitSystem system, String... args) {
system.out().println("JUnit version " + Version.id());
JUnitCommandLineParseResult jUnitCommandLineParseResult =
JUnitCommandLineParseResult.parse(args);
//观察者模式
RunListener listener = new TextListener(system);
addListener(listener);
return run(jUnitCommandLineParseResult.createRequest(defaultComputer()));}
//所有的单元测试方法都是通过RUnner来执行的,Runner只是一个抽象类,它使用来跑测试用理并通知结果的,JUnit提供了很多Runner的实现类,可以根据不同的情况选择不同的tesst runner
public Result run(junit.framework.Test test) { r
eturn run(new JUnit38ClassRunner(test));
}
/**
* Do not use. Testing purposes only.
*/
public Result run(Runner runner) {
Result result = new Result();
RunListener listener = result.createListener();
notifier.addFirstListener(listener);
try {
notifier.fireTestRunStarted(runner.getDescription());
runner.run(notifier);
notifier.fireTestRunFinished(result);
} finally {
removeListener(listener);
}
return result;
}
- Suite:测试套件
- 假设有三个测试类Test1,Test2,Test3
- 使用Suite编写一个Testsuit
@RunWith(Suite.class)
@Suite.SuiteClasses({
Test1.class,
Test2.class,
Test3.class
})
public vlass TestSuite{
//无需实现任何方法
}
注意:测试套件还可以嵌套