0%

AndroidJUnitRunner原理

文章是3年多前写的这里进行了迁移
https://www.jianshu.com/p/0c98eba10b12

背景

  • 自动化测试开发过程中,由于对注解执行顺序不了解,可能发生时序异常,也会造成代码质量低

  • 各种注解所运行的线程不了解

  • 目的

  • 掌握各种注解的执行时机

  • 提高代码开发质量

    执行顺序图

    12538705-4533b03b4f6c7492.webp

    收益

  • 发现度假在@Before中进行了mock,mock不生效

  • 打开了思维,对每个注解有了了解,可以在不同的注解中进行不同的事务

    源码分析

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    public T launchActivity(@Nullable Intent startIntent) {
    ...
    if (null == startIntent) {

    startIntent = getActivityIntent();

    if (null == startIntent) {

    ...

    startIntent = new Intent(Intent.ACTION_MAIN);

    }

    }
    ...
    beforeActivityLaunched(); //子线程

    mActivity = mActivityClass.cast(mInstrumentation.startActivitySync(startIntent));//异步启动activity

    mInstrumentation.waitForIdleSync(); //子线程阻塞

    if (mActivity != null) {

    afterActivityLaunched(); //子线程

    } else {

    ...

    }

    return mActivity;

    }

    public void waitForIdleSync() {

    validateNotAppThread(); //判断不是UI线程

    Idler idler = new Idler(null);

    mMessageQueue.addIdleHandler(idler); //添加IdlerHandler

    mThread.getHandler().post(new EmptyRunnable());

    idler.waitForIdle(); //阻塞

    }

    private static final class Idler implements MessageQueue.IdleHandler {

    private final Runnable mCallback;

    private boolean mIdle;

    public Idler(Runnable callback) {

    mCallback = callback;

    mIdle = false;

    }

    public final boolean queueIdle() {

    if (mCallback != null) {

    mCallback.run();

    }

    synchronized (this) {

    mIdle = true;

    notifyAll(); //解除阻塞

    }

    return false;

    }

    public void waitForIdle() {

    synchronized (this) {

    while (!mIdle) {

    try {

    wait(); //阻塞

    } catch (InterruptedException e) {

    }

    }

    }

    }

    }

    源码相关类

  • AndroidJUnitRunner 自动化测试入口 Runner

  • TestRequestBuilder 测试前请求构建类helper

  • LenientFilterRequest Request包装类

  • AndroidJUnit4ClassRunner test方法的Runner类 ,继承ParentRunner

  • ExtendedSuite(Runner)class的Runner类 继承ParentRunner ;保存着AndroidJUnit4ClassRunner(test方法Runner)

  • TestExecutor 测试执行类 运行ExtendedSuite中的run()开始执行Statement,启动入口;

  • Statement 执行各种注解对应的方法执行顺序

    • ExtendedSuite中的方法执行顺序为:
      RunRules(@ClassRule) ->RunAfters(@AfterClass) ->RunBefores(@BeforeClass);
    • AndroidJUnit4ClassRunner中的方法执行顺序为:
      RunRules(@Rule MethodRule和TestRule) ->RunAfters(@After) ->RunBefores(@Before) ->FailOnTimeout(@Test) ->ExpectException(@Test) ->InvokeMethod(@Test)
    • 注解执行顺序
      ExtendedSuite @ClassRule-> @BeforeClass -> {AndroidJUnit4ClassRunner} -> @AfterClass
      AndroidJUnit4ClassRunner @Rule-> @Before-> @Test-> @After
  • Statement链式调用

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    //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); //@before
    statement = withAfters(method, test, statement); 参数statement对应@Before
    statement = withRules(method, test, statement);
    return statement;
    }
    //@After
    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(); //这个statement对应@Before
    } catch (Throwable e) {
    errors.add(e);
    } finally {
    for (FrameworkMethod each : afters) {
    try {
    each.invokeExplosively(target);
    } catch (Throwable e) {
    errors.add(e);
    }
    }
    }
    MultipleFailureException.assertEmpty(errors);
    }
    }