美文网首页
自动化测试AndroidJUnitRunner

自动化测试AndroidJUnitRunner

作者: JuneLeo | 来源:发表于2018-06-07 17:52 被阅读0次
    背景
    • 自动化测试开发过程中,由于对注解执行顺序不了解,可能发生时序异常,也会造成代码质量低
    • 各种注解所运行的线程不了解
    目的
    • 掌握各种注解的执行时机
    • 提高代码开发质量
    执行顺序图
    image
    收益
    • 发现度假在@Before中进行了mock,mock不生效
    • 打开了思维,对每个注解有了了解,可以在不同的注解中进行不同的事务
    源码分析
    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链式调用
    //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);
        }
    }
    

    相关文章

      网友评论

          本文标题:自动化测试AndroidJUnitRunner

          本文链接:https://www.haomeiwen.com/subject/sdxnsftx.html