JUnit4.1源代码分析---2

 上一篇:JUnit4源代码分析---1

这篇主要讲下JUnit是如何构建、运行Runner 。

JUnit4中是通过Request.classes(Computer computer, Class<?>... classes)来构造Runner的

 //org.junit.runner.Request
1
public static Request classes(Computer computer, Class<?>... classes) { 2 try { 3 AllDefaultPossibilitiesBuilder builder= new AllDefaultPossibilitiesBuilder(true); 4 Runner suite= computer.getSuite(builder, classes); 5 return runner(suite); 6 } catch (InitializationError e) { 7 throw new RuntimeException( 8 "Bug in saff's brain: Suite constructor, called as above, should always complete"); 9 } 10 }

       在上面这个方法中出现了一个重要的类,就是AllDefaultPossibilitiesBuilder,这个类就是用来选择RunerBuilder,继而选择Runner来执行Test。这个类中有一重要的方法runnerForClass(Class<?> testClass)(代码-1)

该方法用来确定选择RunerBuilder,继而选择Runner来执行Test。默认选择的是junit4Builder();(但是你可以自由选择和自己实现,可以用@RunWith Annotation来标注,这样就会选择annotatedBuilder()来作为RunnerBuilder.)。

在 选择好了RunnerBuilder后,接下就是要构建Runner了,这里是用Computer.getSuite()(代码-2)来获取Suite类型的 Runner(通过类层次关系,你会发现Suiter是继承自ParentRunner的,而ParentRunner是实现了Runner接口的)。

 

代码-1

    //org.junit.internal.builders.AllDefaultPossibilitiesBuilder
   public
Runner runnerForClass(Class<?> testClass) throws Throwable { List<RunnerBuilder> builders= Arrays.asList( ignoredBuilder(), annotatedBuilder(), suiteMethodBuilder(), junit3Builder(), junit4Builder()); for (RunnerBuilder each : builders) { Runner runner= each.safeRunnerForClass(testClass); if (runner != null) return runner; } return null; }

 

代码-2

 //org.junit.runners.Computer
1
  public Runner getSuite(final RunnerBuilder builder, 2 Class<?>[] classes) throws InitializationError { 3 return new Suite(new RunnerBuilder() { 4 @Override 5 public Runner runnerForClass(Class<?> testClass) throws Throwable { 6 return getRunner(builder, testClass); 7 } 8 }, classes); 9 } 10 11 /** 12 * Create a single-class runner for {@code testClass}, using {@code builder} 13 */ 14 protected Runner getRunner(RunnerBuilder builder, Class<?> testClass) throws Throwable { 15 return builder.runnerForClass(testClass); 16 }

在上面的执行体中,只是new 出一个Suite对象然后返回。在Suite构造函数中接收两个参数(RunnerBuilder,Class<?>[]);仔细研究这段代码,你会发现这个新new出来的RunnerBuilder(第3行)的功能其实就是传进来的builder(第一行),也就是AllDefaultPossibilitiesBuilder对象;这样执行RunnerBuilder.runnerForClass(),方法时就是执行AllDefaultPossibilitiesBuilder.runnerForClass()方法。

 

再进入Suite的构造函数中,你会发现它调用了Runnerbuilder.runners方法,该方法的作用是获取suite的子集合。具体获取的实现就是调用AllDefaultPossibilitiesBuilder.runnerForClass(), 该方法默认会用JUnit4Builder();然后调用JUnit4Builder.runnerForClass();最后返回的是 BlockJUnit4ClassRunner对象,该对象和Suite是平级的也是继承自ParentRunner。(代码-3)演示了这个执行过程:

//org.junit.runners.Suite
1
public Suite(RunnerBuilder builder, Class<?>[] classes) throws InitializationError { 2 this(null, builder.runners(null, classes)); 3 }

 

代码-3

 //org.junit.runners.model.RunnerBuilder
1
  public List<Runner> runners(Class<?> parent, Class<?>[] children) 2 throws InitializationError { 3 addParent(parent); 4 5 try { 6 return runners(children); 7 } finally { 8 removeParent(parent); 9 } 10 } 11   private List<Runner> runners(Class<?>[] children) { 12 ArrayList<Runner> runners= new ArrayList<Runner>(); 13 for (Class<?> each : children) { 14 Runner childRunner= safeRunnerForClass(each); 15 if (childRunner != null) 16 runners.add(childRunner); 17 } 18 return runners; 19 } 20 21 public Runner safeRunnerForClass(Class<?> testClass) { 22 try { 23 return runnerForClass(testClass); 24 } catch (Throwable e) { 25 return new ErrorReportingRunner(testClass, e); 26 } 27 } 28   

    //org.junit.internal.builders.AllDefaultPossibilitiesBuilder 29   @Override 30 public Runner runnerForClass(Class<?> testClass) throws Throwable { 31 List<RunnerBuilder> builders= Arrays.asList( 32 ignoredBuilder(), 33 annotatedBuilder(), 34 suiteMethodBuilder(), 35 junit3Builder(), 36 junit4Builder()); 37 38 for (RunnerBuilder each : builders) { 39 Runner runner= each.safeRunnerForClass(testClass); 40 if (runner != null) 41 return runner; 42 } 43 return null; 44 }
45   //org.junit.internal.builders.AllDefaultPossibilitiesBuilder 46   protected JUnit4Builder junit4Builder() { 47 return new JUnit4Builder(); 48 } 49   public Runner runnerForClass(Class<?> testClass) throws Throwable { 50 return new BlockJUnit4ClassRunner(testClass); 51 }

构造完上面的子集合以后,就进行到Suite的另外一个构造函数中

//org.junit.runners.Suite
1
  protected Suite(Class<?> klass, List<Runner> runners) throws InitializationError { 2 super(klass); 3 fRunners = runners; 4 }

该构造函数中主要的功能就是调用父类的构造函数,在父类的构造函数中主要有以下功能:

1)、进行了部分方法的的验证,包括对BeforeClass和AfterClass所注解得方法进行了public static void 和无参数的判断和一些规则的判断。

2)、构造了一个TestClass(代码-4),这个类对Class对象进行了解析,把目标Class的方法和成员变量都解析出来了。并建立了一个从Annotation到方法和Annotation到成员变量的对应Map。

 

下面是ParentRunner的构造函数:

//org.junit.runners.ParentRunner
1
  protected ParentRunner(Class<?> testClass) throws InitializationError { 2 fTestClass= new TestClass(testClass); 3 validate(); 4 }
1   private void validate() throws InitializationError {
2         List<Throwable> errors= new ArrayList<Throwable>();
3         collectInitializationErrors(errors);
4         if (!errors.isEmpty())
5             throw new InitializationError(errors);
6     }
1   protected void collectInitializationErrors(List<Throwable> errors) {
2         validatePublicVoidNoArgMethods(BeforeClass.class, true, errors);
3         validatePublicVoidNoArgMethods(AfterClass.class, true, errors);
4         validateClassRules(errors);
5     }

 

代码-4

//org.junit.runners.model.TestClass       
    //Annotation到方法的对应
 1    private Map<Class<?>, List<FrameworkMethod>> fMethodsForAnnotations= new HashMap<Class<?>, List<FrameworkMethod>>();
 2     //Annotation到成员变量的对应
 3     private Map<Class<?>, List<FrameworkField>> fFieldsForAnnotations= new HashMap<Class<?>, List<FrameworkField>>();
 4 
 5     public TestClass(Class<?> klass) {
 6         fClass= klass;
 7         if (klass != null && klass.getConstructors().length > 1)
 8             throw new IllegalArgumentException(
 9                     "Test class can only have one constructor");
10 
11         for (Class<?> eachClass : getSuperClasses(fClass)) {
12             for (Method eachMethod : eachClass.getDeclaredMethods())
13                 addToAnnotationLists(new FrameworkMethod(eachMethod),
14                         fMethodsForAnnotations);
15             for (Field eachField : eachClass.getDeclaredFields())
16                 addToAnnotationLists(new FrameworkField(eachField),
17                         fFieldsForAnnotations);
18         }
19     }

这样就成功构造了一个Runner对象(也就是Suite对象),接下了就是运行该Runner了。

 1   public Result run(Runner runner) {
 2         Result result= new Result();
 3         RunListener listener= result.createListener();
 4         fNotifier.addFirstListener(listener);
 5         try {
 6             fNotifier.fireTestRunStarted(runner.getDescription());
 7             runner.run(fNotifier);
 8             fNotifier.fireTestRunFinished(result);
 9         } finally {
10             removeListener(listener);
11         }
12         return result;
13     }

 

 上面这个方法就是负责启动执行Runner的,他调用Runner.run()方法。也就是ParentRunner(Suite继承自ParentRunner,而Sutie没有对run方法进行重载)的run()方法。

再跟进到ParentRunner.run()方法中,这个方法的功能有:

1、构造一个链式的Statement,分别是:

RunRules --> RunAfters(@AfterClass) -->RunBefores(@BeforeClass) -->

(RunRules--> RunAfters(@After) -->RunBefores(@Before)-->FailOnTimeout(@Test(timeout=?))-->ExpectException(@Test(expect=?))-->InvokeMethod(@Test)...)-->

....

(RunRules--> RunAfters(@After) -->RunBefores(@Before)-->FailOnTimeout(@Test(timeout=?))-->ExpectException(@Test(expect=?))-->InvokeMethod(@Test)...);

从这个链式的结构中可以看出,最先执行的是RunRules这个Statement,然后是RunAfter(这里不要有疑问为什么先执行RunAfter,进去看看实现吧(代码2.1会揭晓一切的))...;

2、记录错误信息,在run方法中会传递进来一个RunNotifier对象,在这里RunNotifier可以拥有多个RunListener。默认的情况下在JunitCore里的RunNotifier只包含Result.RunListener对象,这样就可以进行对Result的状态的改变从而记录运行结果信息,其实这就是典型的观察者模式。RunNotifier就是观察者,得到通知就通知其子集合区执行相应的操作。

 1   @Override
 2     public void run(final RunNotifier notifier) {
 3         EachTestNotifier testNotifier= new EachTestNotifier(notifier,
 4                 getDescription());
 5         try {
 6             Statement statement= classBlock(notifier);
 7             statement.evaluate();
 8         } catch (AssumptionViolatedException e) {
 9             testNotifier.fireTestIgnored();
10         } catch (StoppedByUserException e) {
11             throw e;
12         } catch (Throwable e) {
13             e.printStackTrace();
14             testNotifier.addFailure(e);
15         }
16     }
1   protected Statement classBlock(final RunNotifier notifier) {
2         Statement statement= childrenInvoker(notifier);
3         statement= withBeforeClasses(statement);
4         statement= withAfterClasses(statement);
5         statement= withClassRules(statement);
6         return statement;
7     }

 

 

 

 代码-2.1(RunAfter会先执行它的下一个,等它的下一个执行完成之后才执行本体。这样就可以保证呗@After和@AfterClass的注解的方法一定会被执行,即使某个环节执行过程出错也会执行finally的RunAfter本体);

 

 1 public class RunAfters extends Statement {
 2     private final Statement fNext;
 3 
 4     private final Object fTarget;
 5 
 6     private final List<FrameworkMethod> fAfters;
 7     
 8     public RunAfters(Statement next, List<FrameworkMethod> afters, Object target) {
 9         fNext= next;
10         fAfters= afters;
11         fTarget= target;
12     }
13 
14     @Override
15     public void evaluate() throws Throwable {
16         List<Throwable> errors = new ArrayList<Throwable>();
17         try {
18             fNext.evaluate();
19         } catch (Throwable e) {
20             errors.add(e);
21         } finally {
22             for (FrameworkMethod each : fAfters)
23                 try {
24                     each.invokeExplosively(fTarget);
25                 } catch (Throwable e) {
26                     errors.add(e);
27                 }
28         }30         MultipleFailureException.assertEmpty(errors);
31     }
32 }

 

 

这样JUint的执行流程就讲完了。。。

-----------------------------完-------------------------------

 上一篇:JUnit4源代码分析---1

 

 

 

 

 

 

 

 

 

posted on 2012-08-23 13:49  云 娜Blog  阅读(1148)  评论(1编辑  收藏  举报