码迷,mamicode.com
首页 > 其他好文 > 详细

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

时间:2014-09-23 18:47:44      阅读:163      评论:0      收藏:0      [点我收藏+]

标签:des   style   blog   color   io   os   ar   strong   for   

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执行顺序

标签:des   style   blog   color   io   os   ar   strong   for   

原文地址:http://www.cnblogs.com/bj-why/p/3981018.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!