Index: testing/android/docs/junit4.md |
diff --git a/testing/android/docs/junit4.md b/testing/android/docs/junit4.md |
index d697bcd5e7ffc0073264f9cf8b0cc5fb2436fae4..1168ff5f2e9d1f52746af2ce506630f1f97a3a65 100644 |
--- a/testing/android/docs/junit4.md |
+++ b/testing/android/docs/junit4.md |
@@ -1,4 +1,3 @@ |
- |
# JUnit 4 Migration |
As of Android 24 (N), JUnit3 style javatests have been deprecated for the new |
@@ -7,6 +6,8 @@ We are in the process of changing all instrumentation tests in chromium to |
JUnit4 style. This doc explains the differences between JUnit3 and JUnit4 |
instrumentation tests and how to write or convert them. |
+[TOC] |
+ |
## Differences between JUnit3 and JUnit4 instrumentation tests |
| | JUnit3 | JUnit4 | |
@@ -24,14 +25,14 @@ instrumentation tests and how to write or convert them. |
> The tag for the JUnit4 runner must specify `chromium-junit4:"true"` |
> ([Example][2]) |
-- **Other JUnit4 features**: |
+- **Other JUnit4 features**: |
- Tests can be annotated to expect an exception, e.g. |
`@Test(expected=MyException.class)`. Tests annotated this way will |
fail if they do not throw the given exception. |
- **Test suite set up**: public static method annotated with `@BeforeClass` |
- **Test suite tear down**: public static method annotated with |
`@AfterClass` |
-- **Replacement for JUnit3 test base classes** |
+- **Replacement for JUnit3 test base classes** |
- [`TestRule`][3]: |
- TestRule is a class to **outsource your test setUp, tearDown, and |
utility methods**. Since there are no more interitance and TestBase classes, |
@@ -46,112 +47,194 @@ instrumentation tests and how to write or convert them. |
Support Library that allows tests to launch an Activity. |
([Documentation][4]) |
- |
## Example Code of JUnit3 test and JUnit4 test |
JUnit3: |
```java |
- public class MyTestClass extends MyActivityInstrumentationTestCase2<TestActivity> { |
- @Override |
- protected void setUp(){ |
- super.setUp(); |
- setActivityIntent(new Intent()); |
- getActivity(); |
- } |
+public class MyTestClass extends MyActivityInstrumentationTestCase2<TestActivity> { |
+ @Override |
+ protected void setUp(){ |
+ super.setUp(); |
+ setActivityIntent(new Intent()); |
+ getActivity(); |
+ } |
- @Override |
- protected void tearDown() { |
- specialActionFromSuper(); |
- super.tearDown(); |
- } |
+ @Override |
+ protected void tearDown() { |
+ specialActionFromSuper(); |
+ super.tearDown(); |
+ } |
- public void testA() { |
- assertEquals(1, 1); |
- } |
+ public void testA() { |
+ assertEquals(1, 1); |
} |
+} |
``` |
JUnit4: |
```java |
- @RunWith(BaseJUnit4ClassRunner.class); |
- public class TestClass { |
- @Rule public ActivityTestRule<TestActivity> mRule = new ActivityTestRule<>(TestActivity.class); |
+@RunWith(BaseJUnit4ClassRunner.class); |
+public class TestClass { |
+ @Rule public ActivityTestRule<TestActivity> mRule = new ActivityTestRule<>(TestActivity.class); |
- @Before |
- public void setUp() { //Must be public |
- mRule.launchActivity(new Intent()); |
- } |
+ @Before |
+ public void setUp() { //Must be public |
+ mRule.launchActivity(new Intent()); |
+ } |
- @After |
- public void tearDown() { //Must be public |
- mRule.specialActionFromActivityTestRule(); |
- } |
+ @After |
+ public void tearDown() { //Must be public |
+ mRule.specialActionFromActivityTestRule(); |
+ } |
- @Test |
- public void testA() { |
- Assert.assertEquals(1, 1); |
- } |
+ @Test |
+ public void testA() { |
+ Assert.assertEquals(1, 1); |
} |
+} |
``` |
## Migration process |
-1. Add required libraries to your target dependencies in BUILD.gn |
- - JUnit 4 library: `//third_party/junit` |
- - Android Testing Support Rules: |
- - `//third_party/android_support_test_runner:runner_java` (for `AndroidJUnitRunner`, etc) |
- - `//third_party/android_support_test_runner:rules_java` (for `ActivityTestRule`, etc) |
-2. Add class runner to your test apk manifest. |
- ([example][2]) |
- - Keep in mind you can have multiple instrumentations in your manifest. Our |
- test runner will run JUnit4 tests with JUnit4 runner and JUnit3 tests |
- with non-JUnit4 runner. |
-3. Refactor TestBase class to a TestRule class. |
- ([example CL](https://codereview.chromium.org/2632043002)) |
- - +yolandyan will do this part, however, if you did refactoring yourself, |
- please add him as a reviewer for your CL and enjoy his eternal appreciation! |
-4. Use [auto migrate script][5] |
- to or manually convert all JUnit3 tests to JUnit4 style in a your javatest |
- directory |
- - we understand it's tedious to just manually write all the annotations, |
- change modifiers, etc to convert all the javatest, so we created an auto |
- change script that helps you to convert all the javatests in a certain |
- directory. Please check its [README page][5] |
- on instructions. |
+1. Add required libraries to your target dependencies in BUILD.gn |
+ - JUnit 4 library: `//third_party/junit` |
+ - Android Testing Support Rules: |
+ - `//third_party/android_support_test_runner:runner_java` |
+ (for `AndroidJUnitRunner`, etc) |
+ - `//third_party/android_support_test_runner:rules_java` |
+ (for `ActivityTestRule`, etc) |
+2. Add class runner to your test apk manifest. |
+ ([example][2]) |
+ - Keep in mind you can have multiple instrumentations in your manifest. |
+ Our test runner will run JUnit4 tests with JUnit4 runner and JUnit3 |
+ tests with non-JUnit4 runner. |
+3. Refactor TestBase class to a TestRule class. |
+ ([example CL](https://codereview.chromium.org/2632043002)) |
+ - +yolandyan will do this part, however, if you did refactoring yourself, |
+ please add him as a reviewer for your CL and enjoy his eternal appreciation! |
+4. Use [auto migrate script][5] to or manually convert all JUnit3 tests to |
+ JUnit4 style in a your javatest directory |
+ - we understand it's tedious to just manually write all the annotations, |
+ change modifiers, etc to convert all the javatest, so we created an auto |
+ change script that helps you to convert all the javatests in a certain |
+ directory. Please check its [README page][5] |
+ on instructions. |
+ |
+ |
+## Customized TestRule example |
+ |
+TestRule: |
+ |
+```java |
+public class MyRule implements TestRule { |
+ // 1: Add utility methods... |
+ |
+ @Override |
+ public Statement apply(final Statement base, Description desc) { |
+ return new Statement() { |
+ @Override |
+ public void evaluate() { |
+ // 2: Code here runs before @Before method |
+ base.evaluate() |
+ // 3: Code here runs after @After method |
+ } |
+ } |
+ } |
+} |
+``` |
+ |
## Caveats |
-1. Instrumentation tests that rely on test thread to have message handler |
- will not work. For example error message: |
-``` |
-java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare() |
-``` |
- Please utilize `@UiThreadTest` or `ActivityTestRule.runOnUiThread(Runnable r)` |
- to refactor these tests. For more, check this [github issue][6] |
+1. Instrumentation tests that rely on test thread to have message handler |
+ will not work. For example error message: |
+ |
+ java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare() |
+ |
+ Please utilize `@UiThreadTest` or |
+ `ActivityTestRule.runOnUiThread(Runnable r)` to refactor these tests. |
+ 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
|
+ |
+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
|
+ **@UiThreadTest is only effective when UiThreadTestRule or |
+ ActivityTestRule is declared** in the test class. Please use |
+ `android.support.test.annotation.UiThreadTest`, not |
+ `android.test.UiThreadTest`. When using @UiThreadTest, **it would cause |
+ `setUp` and `tearDown` to run in Ui Thread** as well. Avoid that by simply |
+ calling [`runOnUiThread`][9] or [`runOnMainSync`][10] with a Runnable. |
+ |
+ ```java |
+ //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
|
+ public class Test { |
+ @Rule |
+ public ActivityTestRule<MyActivity> mRule = new ActivityTestRule<>( |
+ MyActivity.class> |
+ |
+ @Before |
+ public void setUp() { |
+ // Cause failure because this also runs on Ui Thread, while it |
+ // is intended for Instrumentation worker thread |
+ mRule.launchActivity() |
+ } |
+ |
+ @UiThreadTest |
+ public void test() { |
+ actionThatNeedsUiThread(); |
+ } |
+ } |
+ ``` |
+ |
+ The correct thing to do is |
-2. `assertEquals(float a, float b)` and `assertEquals(double a, double b)` are |
+ ```java |
+ //Correct test |
+ public class Test { |
+ @Rule |
+ public ActivityTestRule<MyActivity> mRule = new ActivityTestRule<>( |
+ MyActivity.class> |
+ |
+ @Before |
+ public void setUp() { |
+ mRule.launchActivity() |
+ } |
+ |
+ public void test() { |
+ mRule.runOnUiThread(new Runnable() { |
+ @Override |
+ public void run() { |
+ actionThatNeedsUiThread(); |
+ } |
+ }); |
+ } |
+ } |
+ ``` |
+ |
+ |
+3. `assertEquals(float a, float b)` and `assertEquals(double a, double b)` are |
deprecated in JUnit4's Assert class. **Despite only generating a warning at |
build time, they fail at runtime.** Please use |
`Assert.assertEquals(float a, float b, float delta)` |
+ |
## Common questions |
-- Q: are `@Test` and `@LargeTest/@MediumTest/@SmallTest` annotation both |
- necessary? |
- - A: Yes, both are required for now. We plan to refactor this in the future. |
-- Q: Isn't the inheritance of the Test classes just migrated to inheritance |
- of TestRules? |
- - A: Yes. During the migration, we plan to maintain a 1:1 mapping between |
- the test base classes and TestRules (e.g. ContentShellTestBase to |
- ContentShellTestRule in this [CL](https://codereview.chromium.org/2632043002)). |
- This allows the auto convert script to replace API calls in any |
- JUnit3 tests. After the migration, we plan to refactor the TestRules to |
- be more modular. |
- |
-If you have any other questions, feel free to report in |
-[this bug][7]. |
+- 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
|
+ necessary? |
+ - A: Yes, both are required for now. We plan to refactor this in the |
+ future. |
+- Q: Isn't the inheritance of the Test classes just migrated to inheritance |
+ of TestRules? |
+ - A: Yes. During the migration, we plan to maintain a 1:1 mapping between |
+ the test base classes and TestRules (e.g. ContentShellTestBase to |
+ ContentShellTestRule in this |
+ [CL](https://codereview.chromium.org/2632043002)). |
+ This allows the auto convert script to replace API calls in any |
+ JUnit3 tests. After the migration, we plan to refactor the TestRules to |
+ be more modular. |
+ |
+If you have any other questions, feel free to report in [this bug][7]. |
## Links and Crbugs |
@@ -167,3 +250,5 @@ If you have any other questions, feel free to report in |
[6]: http://github.com/skyisle/android-test-kit/issues/121 |
[7]: https://bugs.chromium.org/p/chromium/issues/detail?id=640116 |
[8]: http://junit.org/junit4/javadoc/4.12/org/junit/rules/RuleChain.html |
+[9]: https://developer.android.com/reference/android/app/Instrumentation.html#runOnMainSync(java.lang.Runnable) |
+[10]: https://developer.android.com/reference/android/support/test/rule/UiThreadTestRule.html#runOnUiThread(java.lang.Runnable) |