一回顾
UT 就是在讲述一个故事, 故事的结构是:
在什么条件下做了什么事结果是什么
如何设置条件表述期望结果, 前文已陈述
下面这个 UT, 对您来说, 现在应该是一望即懂
- public class ResultTest {
- @Test
- public void should_returnString() {
- // given
- String expectedString = "downLoadStatus: Fail, failureReason: cannot connect";
- Result result = new Result("Fail", "cannot connect");
- // when
- String realString = result.toString();
- // then
- Assert.assertEquals(expectedString, realString);
- }
- }
given 下面的语句, 设置了条件
when 下面的语句, 做了一些事情
then 下面的语句, 表达了期望的结果
2 什么是 Runner
不过, 这不是全部
这里面还有肉眼觉察不到的条件
这个条件是什么呢?
Runner
Runner 是一个类, 它的职责是运行 UT
每一个 UT 都有一个 Runner
通过 @RunWith 来指定 Runner
比如 @RunWith(TestRunner.class)
当没有指定时, 会使用默认的 Runner
默认的 Runner 是 BlockJUnit4ClassRunner
上面的 ResultTest, 因为没有指定一个 Runner, 所以, 它就是在使用默认的 Runner
你可以使用已有的, 也可以自己动手写一个 Runner
下面通过写一个 Runner, 加深对其的认识
步骤 1: 实现抽象类 Runner
- public abstract class Runner implements Describable {
- public abstract Description getDescription();
- public abstract void run(RunNotifier notifier);
- }
子步骤 1.1: 实现方法 getDescription()
子步骤 1.2: 实现方法 run()
子步骤 1.3: 定义一个构造函数, 有一个参数, 参数类型为 Class
- public class TestRunner extends Runner {
- private Class testClass;
- public TestRunner(Class testClass) {
- super();
- this.testClass = testClass;
- }
- @Override
- public Description getDescription() {
- return Description
- .createTestDescription(testClass, "My runner description");
- }
- @Override
- public void run(RunNotifier notifier) {
- System.out.println("running the tests from MyRunner:" + testClass);
- try {
- Object testObject = testClass.newInstance();
- for (Method method : testClass.getMethods()) {
- if (method.isAnnotationPresent(Test.class)) {
- notifier.fireTestStarted(Description
- .createTestDescription(testClass, method.getName()));
- method.invoke(testObject);
- notifier.fireTestFinished(Description
- .createTestDescription(testClass, method.getName()));
- }
- }
- } catch (Exception e) {
- throw new RuntimeException(e);
- }
- }
- }
步骤 2: 使用具体的 Runner
- @RunWith(TestRunner.class)
- public class ResultTest {
- @Test
- public void should_returnString() {
- // given
- String expectedString = "downLoadStatus: Fail, failureReason: cannot connect";
- Result result = new Result("Fail", "cannot connect");
- // when
- String realString = result.toString();
- // then
- Assert.assertEquals(expectedString, realString);
- }
- }
result_with_customized_runner.png
这是一个简单易懂的实现, 它忽略了 @Test 以外的注解, 比如 @Before@BeforeClass 等
3 为什么要使用 Runner?
仔细观察 TestRunner 中 run 方法,
public void run(RunNotifier notifier)
它的含义就是
- if (/* method annotated with @Test */) {
- // run test method
- }
run 一个 case 是通过 java 反射实现的:
method.invoke(testObject)
如果没有 Runner,@Test 注解的方法, 就不能被调用了
一句话, 没有 Runer,UT 就不能运行
来源: http://www.jianshu.com/p/28166222db3e