文章是3年多前写的这里进行了迁移
https://www.jianshu.com/p/0c98eba10b12
背景
自动化测试开发过程中,由于对注解执行顺序不了解,可能发生时序异常,也会造成代码质量低
各种注解所运行的线程不了解
目的
掌握各种注解的执行时机
提高代码开发质量
执行顺序图
收益
发现度假在@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
105public T launchActivity( 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
- ExtendedSuite中的方法执行顺序为:
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() {
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对应
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;
}
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);
}
}