背景
- 自动化测试开发过程中,由于对注解执行顺序不了解,可能发生时序异常,也会造成代码质量低
- 各种注解所运行的线程不了解
目的
执行顺序图
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);
}
}
网友评论