Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(260)

Side by Side Diff: testing/android/docs/junit4.md

Issue 2749353002: Add doc on customizing TestRule (Closed)
Patch Set: Address comments Created 3 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1
2 # JUnit 4 Migration 1 # JUnit 4 Migration
3 2
4 As of Android 24 (N), JUnit3 style javatests have been deprecated for the new 3 As of Android 24 (N), JUnit3 style javatests have been deprecated for the new
5 JUnit4-based [Android Testing Support Library][1]. 4 JUnit4-based [Android Testing Support Library][1].
6 We are in the process of changing all instrumentation tests in chromium to 5 We are in the process of changing all instrumentation tests in chromium to
7 JUnit4 style. This doc explains the differences between JUnit3 and JUnit4 6 JUnit4 style. This doc explains the differences between JUnit3 and JUnit4
8 instrumentation tests and how to write or convert them. 7 instrumentation tests and how to write or convert them.
9 8
9 [TOC]
10
10 ## Differences between JUnit3 and JUnit4 instrumentation tests 11 ## Differences between JUnit3 and JUnit4 instrumentation tests
11 12
12 | | JUnit3 | JUnit4 | 13 | | JUnit3 | JUnit4 |
13 |--------------|-----------------------------------------------------|---------- --------------------------------| 14 |--------------|-----------------------------------------------------|---------- --------------------------------|
14 | Inheritance | Tests extends TestCase or child classes | No inheri tance. | 15 | Inheritance | Tests extends TestCase or child classes | No inheri tance. |
15 | Test methods | methods named with test prefix | methods a nnotated with @Test | 16 | Test methods | methods named with test prefix | methods a nnotated with @Test |
16 | Set up | setUp() method | public me thod annotated with @Before | 17 | Set up | setUp() method | public me thod annotated with @Before |
17 | Tear down | tearDown() method | public me thod annotated with @After | 18 | Tear down | tearDown() method | public me thod annotated with @After |
18 | Test runner | declared within test apk AndroidManifest.xml | Must spec ify `chromium-junit4:"true"` | 19 | Test runner | declared within test apk AndroidManifest.xml | Must spec ify `chromium-junit4:"true"` |
19 | Class runner | N/A | @RunWith( XClassRunner.class) | 20 | Class runner | N/A | @RunWith( XClassRunner.class) |
20 | Assertion | Extends from junit.framework.Assert, inherited APIs | Use stati c methods from org.junit.Assert | 21 | Assertion | Extends from junit.framework.Assert, inherited APIs | Use stati c methods from org.junit.Assert |
21 22
22 > Please note that during the migration, we support running JUnit3 and JUnit4 23 > Please note that during the migration, we support running JUnit3 and JUnit4
23 > tests in the same apk. This requires two tags, one each for JUnit3 and JUnit4. 24 > tests in the same apk. This requires two tags, one each for JUnit3 and JUnit4.
24 > The tag for the JUnit4 runner must specify `chromium-junit4:"true"` 25 > The tag for the JUnit4 runner must specify `chromium-junit4:"true"`
25 > ([Example][2]) 26 > ([Example][2])
26 27
27 - **Other JUnit4 features**: 28 - **Other JUnit4 features**:
28 - Tests can be annotated to expect an exception, e.g. 29 - Tests can be annotated to expect an exception, e.g.
29 `@Test(expected=MyException.class)`. Tests annotated this way will 30 `@Test(expected=MyException.class)`. Tests annotated this way will
30 fail if they do not throw the given exception. 31 fail if they do not throw the given exception.
31 - **Test suite set up**: public static method annotated with `@BeforeClass` 32 - **Test suite set up**: public static method annotated with `@BeforeClass`
32 - **Test suite tear down**: public static method annotated with 33 - **Test suite tear down**: public static method annotated with
33 `@AfterClass` 34 `@AfterClass`
34 - **Replacement for JUnit3 test base classes** 35 - **Replacement for JUnit3 test base classes**
35 - [`TestRule`][3]: 36 - [`TestRule`][3]:
36 - TestRule is a class to **outsource your test setUp, tearDown, and 37 - TestRule is a class to **outsource your test setUp, tearDown, and
37 utility methods**. Since there are no more interitance and TestBase cl asses, 38 utility methods**. Since there are no more interitance and TestBase cl asses,
38 one should use TestRule for any API calls provided by its test base cl asses 39 one should use TestRule for any API calls provided by its test base cl asses
39 previously. 40 previously.
40 - One test can declare multiple TestRules and the class runner will run all of 41 - One test can declare multiple TestRules and the class runner will run all of
41 them. If the order of the TestRule matters to you, use 42 them. If the order of the TestRule matters to you, use
42 [`RuleChain`][8] 43 [`RuleChain`][8]
43 44
44 - [`ActivityTestRule`][4] 45 - [`ActivityTestRule`][4]
45 - `ActivityTestRule` is a special `TestRule` provided by Android Testing 46 - `ActivityTestRule` is a special `TestRule` provided by Android Testing
46 Support Library that allows tests to launch an Activity. 47 Support Library that allows tests to launch an Activity.
47 ([Documentation][4]) 48 ([Documentation][4])
48 49
49
50 ## Example Code of JUnit3 test and JUnit4 test 50 ## Example Code of JUnit3 test and JUnit4 test
51 51
52 JUnit3: 52 JUnit3:
53 53
54 ```java 54 ```java
55 public class MyTestClass extends MyActivityInstrumentationTestCase2<TestActi vity> { 55 public class MyTestClass extends MyActivityInstrumentationTestCase2<TestActivity > {
56 @Override 56 @Override
57 protected void setUp(){ 57 protected void setUp(){
58 super.setUp(); 58 super.setUp();
59 setActivityIntent(new Intent()); 59 setActivityIntent(new Intent());
60 getActivity(); 60 getActivity();
61 } 61 }
62 62
63 @Override 63 @Override
64 protected void tearDown() { 64 protected void tearDown() {
65 specialActionFromSuper(); 65 specialActionFromSuper();
66 super.tearDown(); 66 super.tearDown();
67 } 67 }
68 68
69 public void testA() { 69 public void testA() {
70 assertEquals(1, 1); 70 assertEquals(1, 1);
71 }
72 } 71 }
72 }
73 ``` 73 ```
74 74
75 JUnit4: 75 JUnit4:
76 76
77 ```java 77 ```java
78 @RunWith(BaseJUnit4ClassRunner.class); 78 @RunWith(BaseJUnit4ClassRunner.class);
79 public class TestClass { 79 public class TestClass {
80 @Rule public ActivityTestRule<TestActivity> mRule = new ActivityTestRule <>(TestActivity.class); 80 @Rule public ActivityTestRule<TestActivity> mRule = new ActivityTestRule<>(T estActivity.class);
81 81
82 @Before 82 @Before
83 public void setUp() { //Must be public 83 public void setUp() { //Must be public
84 mRule.launchActivity(new Intent()); 84 mRule.launchActivity(new Intent());
85 } 85 }
86 86
87 @After 87 @After
88 public void tearDown() { //Must be public 88 public void tearDown() { //Must be public
89 mRule.specialActionFromActivityTestRule(); 89 mRule.specialActionFromActivityTestRule();
90 } 90 }
91 91
92 @Test 92 @Test
93 public void testA() { 93 public void testA() {
94 Assert.assertEquals(1, 1); 94 Assert.assertEquals(1, 1);
95 }
96 } 95 }
96 }
97 ``` 97 ```
98 98
99 ## Migration process 99 ## Migration process
100 100
101 1. Add required libraries to your target dependencies in BUILD.gn 101 1. Add required libraries to your target dependencies in BUILD.gn
102 - JUnit 4 library: `//third_party/junit` 102 - JUnit 4 library: `//third_party/junit`
103 - Android Testing Support Rules: 103 - Android Testing Support Rules:
104 - `//third_party/android_support_test_runner:runner_java` (for `AndroidJU nitRunner`, etc) 104 - `//third_party/android_support_test_runner:runner_java`
105 - `//third_party/android_support_test_runner:rules_java` (for `ActivityTe stRule`, etc) 105 (for `AndroidJUnitRunner`, etc)
106 2. Add class runner to your test apk manifest. 106 - `//third_party/android_support_test_runner:rules_java`
107 ([example][2]) 107 (for `ActivityTestRule`, etc)
108 - Keep in mind you can have multiple instrumentations in your manifest. Our 108 2. Add class runner to your test apk manifest.
109 test runner will run JUnit4 tests with JUnit4 runner and JUnit3 tests 109 ([example][2])
110 with non-JUnit4 runner. 110 - Keep in mind you can have multiple instrumentations in your manifest.
111 3. Refactor TestBase class to a TestRule class. 111 Our test runner will run JUnit4 tests with JUnit4 runner and JUnit3
112 ([example CL](https://codereview.chromium.org/2632043002)) 112 tests with non-JUnit4 runner.
113 - +yolandyan will do this part, however, if you did refactoring yourself, 113 3. Refactor TestBase class to a TestRule class.
114 please add him as a reviewer for your CL and enjoy his eternal appreciatio n! 114 ([example CL](https://codereview.chromium.org/2632043002))
115 4. Use [auto migrate script][5] 115 - +yolandyan will do this part, however, if you did refactoring yourself,
116 to or manually convert all JUnit3 tests to JUnit4 style in a your javatest 116 please add him as a reviewer for your CL and enjoy his eternal appreciat ion!
117 directory 117 4. Use [auto migrate script][5] to or manually convert all JUnit3 tests to
118 - we understand it's tedious to just manually write all the annotations, 118 JUnit4 style in a your javatest directory
119 change modifiers, etc to convert all the javatest, so we created an auto 119 - we understand it's tedious to just manually write all the annotations,
120 change script that helps you to convert all the javatests in a certain 120 change modifiers, etc to convert all the javatest, so we created an auto
121 directory. Please check its [README page][5] 121 change script that helps you to convert all the javatests in a certain
122 on instructions. 122 directory. Please check its [README page][5]
123 on instructions.
124
125
126 ## Customized TestRule example
127
128 TestRule:
129
130 ```java
131 public class MyRule implements TestRule {
132 // 1: Add utility methods...
133
134 @Override
135 public Statement apply(final Statement base, Description desc) {
136 return new Statement() {
137 @Override
138 public void evaluate() {
139 // 2: Code here runs before @Before method
140 base.evaluate()
141 // 3: Code here runs after @After method
142 }
143 }
144 }
145 }
146 ```
147
123 148
124 ## Caveats 149 ## Caveats
125 150
126 1. Instrumentation tests that rely on test thread to have message handler 151 1. Instrumentation tests that rely on test thread to have message handler
127 will not work. For example error message: 152 will not work. For example error message:
128 ```
129 java.lang.RuntimeException: Can't create handler inside thread that has not call ed Looper.prepare()
130 ```
131 Please utilize `@UiThreadTest` or `ActivityTestRule.runOnUiThread(Runnable r) `
132 to refactor these tests. For more, check this [github issue][6]
133 153
134 2. `assertEquals(float a, float b)` and `assertEquals(double a, double b)` are 154 java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()
155
156 Please utilize `@UiThreadTest` or
157 `ActivityTestRule.runOnUiThread(Runnable r)` to refactor these tests.
158 For more, check this [github issue][6]
nyquist 2017/03/23 21:28:00 Nit: GitHub
the real yoland 2017/03/24 01:35:49 Done
159
160 2. Use `@UiThreadTest` with caution. Currently,
nyquist 2017/03/23 21:28:00 Nit: 1. throughout.
the real yoland 2017/03/24 01:35:49 Done
161 **@UiThreadTest is only effective when UiThreadTestRule or
162 ActivityTestRule is declared** in the test class. Please use
163 `android.support.test.annotation.UiThreadTest`, not
164 `android.test.UiThreadTest`. When using @UiThreadTest, **it would cause
165 `setUp` and `tearDown` to run in Ui Thread** as well. Avoid that by simply
166 calling [`runOnUiThread`][9] or [`runOnMainSync`][10] with a Runnable.
167
168 ```java
169 //Wrong test
nyquist 2017/03/23 21:28:00 Nit: space after // and period at the end. Same be
the real yoland 2017/03/24 01:35:49 Done
170 public class Test {
171 @Rule
172 public ActivityTestRule<MyActivity> mRule = new ActivityTestRule<>(
173 MyActivity.class>
174
175 @Before
176 public void setUp() {
177 // Cause failure because this also runs on Ui Thread, while it
178 // is intended for Instrumentation worker thread
179 mRule.launchActivity()
180 }
181
182 @UiThreadTest
183 public void test() {
184 actionThatNeedsUiThread();
185 }
186 }
187 ```
188
189 The correct thing to do is
190
191 ```java
192 //Correct test
193 public class Test {
194 @Rule
195 public ActivityTestRule<MyActivity> mRule = new ActivityTestRule<>(
196 MyActivity.class>
197
198 @Before
199 public void setUp() {
200 mRule.launchActivity()
201 }
202
203 public void test() {
204 mRule.runOnUiThread(new Runnable() {
205 @Override
206 public void run() {
207 actionThatNeedsUiThread();
208 }
209 });
210 }
211 }
212 ```
213
214
215 3. `assertEquals(float a, float b)` and `assertEquals(double a, double b)` are
135 deprecated in JUnit4's Assert class. **Despite only generating a warning at 216 deprecated in JUnit4's Assert class. **Despite only generating a warning at
136 build time, they fail at runtime.** Please use 217 build time, they fail at runtime.** Please use
137 `Assert.assertEquals(float a, float b, float delta)` 218 `Assert.assertEquals(float a, float b, float delta)`
138 219
220
139 ## Common questions 221 ## Common questions
140 222
141 - Q: are `@Test` and `@LargeTest/@MediumTest/@SmallTest` annotation both 223 - Q: are `@Test` and `@LargeTest/@MediumTest/@SmallTest` annotation both
nyquist 2017/03/23 21:28:00 Nit: "Are"
the real yoland 2017/03/24 01:35:49 Done
142 necessary? 224 necessary?
143 - A: Yes, both are required for now. We plan to refactor this in the future. 225 - A: Yes, both are required for now. We plan to refactor this in the
144 - Q: Isn't the inheritance of the Test classes just migrated to inheritance 226 future.
145 of TestRules? 227 - Q: Isn't the inheritance of the Test classes just migrated to inheritance
146 - A: Yes. During the migration, we plan to maintain a 1:1 mapping between 228 of TestRules?
147 the test base classes and TestRules (e.g. ContentShellTestBase to 229 - A: Yes. During the migration, we plan to maintain a 1:1 mapping between
148 ContentShellTestRule in this [CL](https://codereview.chromium.org/2632043002 )). 230 the test base classes and TestRules (e.g. ContentShellTestBase to
149 This allows the auto convert script to replace API calls in any 231 ContentShellTestRule in this
150 JUnit3 tests. After the migration, we plan to refactor the TestRules to 232 [CL](https://codereview.chromium.org/2632043002)).
151 be more modular. 233 This allows the auto convert script to replace API calls in any
234 JUnit3 tests. After the migration, we plan to refactor the TestRules to
235 be more modular.
152 236
153 If you have any other questions, feel free to report in 237 If you have any other questions, feel free to report in [this bug][7].
154 [this bug][7].
155 238
156 ## Links and Crbugs 239 ## Links and Crbugs
157 240
158 - [Android Test Support Library documentation][1] 241 - [Android Test Support Library documentation][1]
159 - [Auto change script][5] 242 - [Auto change script][5]
160 - [Crbug for JUnit3 to JUnit4 migration][7] 243 - [Crbug for JUnit3 to JUnit4 migration][7]
161 244
162 [1]: https://developer.android.com/topic/libraries/testing-support-library/index .html 245 [1]: https://developer.android.com/topic/libraries/testing-support-library/index .html
163 [2]: https://cs.chromium.org/chromium/src/android_webview/tools/system_webview_s hell/layout_tests/AndroidManifest.xml?l=36 246 [2]: https://cs.chromium.org/chromium/src/android_webview/tools/system_webview_s hell/layout_tests/AndroidManifest.xml?l=36
164 [3]: http://junit.org/junit4/javadoc/4.12/org/junit/rules/TestRule.html 247 [3]: http://junit.org/junit4/javadoc/4.12/org/junit/rules/TestRule.html
165 [4]: https://developer.android.com/reference/android/support/test/rule/ActivityT estRule.html 248 [4]: https://developer.android.com/reference/android/support/test/rule/ActivityT estRule.html
166 [5]: https://github.com/yoland68/chromium-junit-auto-migrate 249 [5]: https://github.com/yoland68/chromium-junit-auto-migrate
167 [6]: http://github.com/skyisle/android-test-kit/issues/121 250 [6]: http://github.com/skyisle/android-test-kit/issues/121
168 [7]: https://bugs.chromium.org/p/chromium/issues/detail?id=640116 251 [7]: https://bugs.chromium.org/p/chromium/issues/detail?id=640116
169 [8]: http://junit.org/junit4/javadoc/4.12/org/junit/rules/RuleChain.html 252 [8]: http://junit.org/junit4/javadoc/4.12/org/junit/rules/RuleChain.html
253 [9]: https://developer.android.com/reference/android/app/Instrumentation.html#ru nOnMainSync(java.lang.Runnable)
254 [10]: https://developer.android.com/reference/android/support/test/rule/UiThread TestRule.html#runOnUiThread(java.lang.Runnable)
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698