首页 > 代码库 > junit4.12源码分析-runner执行顺序

junit4.12源码分析-runner执行顺序

filter、sort

runner执行要先过滤和排序。默认的filter是ALL代表全部通过,默认的排序是MethodSorter的DEFAULT

ParentRunner调用filter和sort方法:

    public void filter(Filter filter) throws NoTestsRemainException {        synchronized (childrenLock) {            List<T> children = new ArrayList<T>(getFilteredChildren());            for (Iterator<T> iter = children.iterator(); iter.hasNext(); ) {                T each = iter.next();                if (shouldRun(filter, each)) {                    try {                        filter.apply(each);                    } catch (NoTestsRemainException e) {                        iter.remove();                    }                } else {                    iter.remove();                }            }            filteredChildren = Collections.unmodifiableCollection(children);            if (filteredChildren.isEmpty()) {                throw new NoTestsRemainException();            }        }    }    public void sort(Sorter sorter) {        synchronized (childrenLock) {            for (T each : getFilteredChildren()) {                sorter.apply(each);            }            List<T> sortedChildren = new ArrayList<T>(getFilteredChildren());            Collections.sort(sortedChildren, comparator(sorter));            filteredChildren = Collections.unmodifiableCollection(sortedChildren);        }    }

MethodSorter类实现method的排序:

    public static final Comparator<Method> DEFAULT = new Comparator<Method>() {        public int compare(Method m1, Method m2) {            int i1 = m1.getName().hashCode();            int i2 = m2.getName().hashCode();            if (i1 != i2) {                return i1 < i2 ? -1 : 1;            }            return NAME_ASCENDING.compare(m1, m2);        }    };

statement、rule

statement是junit4设计的核心,采用责任链模式,每个statement都会向后引用一个statement,statement链先后顺序就是runner的执行顺序。

runner中调用classBlock,先进行methodBlock,方法级别的statement链构建,然后再进行class级别的statement链构建

ParentRunner:    protected Statement classBlock(final RunNotifier notifier) {        Statement statement = childrenInvoker(notifier);        if (!areAllChildrenIgnored()) {            statement = withBeforeClasses(statement);            statement = withAfterClasses(statement);            statement = withClassRules(statement);        }        return statement;    }BlockJUnit4ClassRunner:    protected Statement methodBlock(FrameworkMethod method) {        Object test;        try {            test = new ReflectiveCallable() {                @Override                protected Object runReflectiveCall() throws Throwable {                    return createTest();                }            }.run();        } catch (Throwable e) {            return new Fail(e);        }        Statement statement = methodInvoker(method, test);        statement = possiblyExpectingExceptions(method, test, statement);        statement = withPotentialTimeout(method, test, statement);        statement = withBefores(method, test, statement);        statement = withAfters(method, test, statement);        statement = withRules(method, test, statement);        return statement;    }

 RunBefores、RunAfters、RunRules

RunBefores先执行当前方法,再对引用的statement调用evaluate。RunAfters相反,先对引用的statement调用evaluate,再执行当前方法。RunRules初始化时apply所有TestRule,就是把TestRule放到statement链。

Rule分为@ClassRule和@Rule,@ClassRule是类级别的,@Rule是方法级别的。具体的rule在何时执行要看apply方法中statement链调用evaluate的先后。

不考虑rule和测试类继承,执行完methodBlock后,statement链是@Before->@Test->@After,classBlock执行完后,statement链是@BeforeClass->@Before->@Test->@After->@AfterClass。

不考虑rule,执行完methodBlock后,statement链是父类@Before->子类@Before->@Test->子类@After->父类@After,classBlock执行完后,statement链是父类@BeforeClass->子类@BeforeClass->父类@Before->子类@Before->@Test->子类@After->父类@After->子类@AfterClass->父类@AfterClass

public class RunBefores extends Statement {    private final Statement next;    private final Object target;    private final List<FrameworkMethod> befores;    public RunBefores(Statement next, List<FrameworkMethod> befores, Object target) {        this.next = next;        this.befores = befores;        this.target = target;    }    @Override    public void evaluate() throws Throwable {        for (FrameworkMethod before : befores) {            before.invokeExplosively(target);        }        next.evaluate();    }}public class RunAfters extends Statement {    private final Statement next;    private final Object target;    private final List<FrameworkMethod> afters;    public RunAfters(Statement next, List<FrameworkMethod> afters, Object target) {        this.next = next;        this.afters = afters;        this.target = target;    }    @Override    public void evaluate() throws Throwable {        List<Throwable> errors = new ArrayList<Throwable>();        try {            next.evaluate();        } catch (Throwable e) {            errors.add(e);        } finally {            for (FrameworkMethod each : afters) {                try {                    each.invokeExplosively(target);                } catch (Throwable e) {                    errors.add(e);                }            }        }        MultipleFailureException.assertEmpty(errors);    }}public class RunRules extends Statement {    private final Statement statement;    public RunRules(Statement base, Iterable<TestRule> rules, Description description) {        statement = applyAll(base, rules, description);    }    @Override    public void evaluate() throws Throwable {        statement.evaluate();    }    private static Statement applyAll(Statement result, Iterable<TestRule> rules,            Description description) {        for (TestRule each : rules) {            result = each.apply(result, description);        }        return result;    }}

 

junit4.12源码分析-runner执行顺序