| Index: testing/android/docs/junit4.md
|
| diff --git a/testing/android/docs/junit4.md b/testing/android/docs/junit4.md
|
| index d697bcd5e7ffc0073264f9cf8b0cc5fb2436fae4..d40583fbe545490aef7c961bb61fb5b9526bc905 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)
|
| +1. 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.
|
| +1. 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!
|
| +1. 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]
|
| +
|
| +1. Use `@UiThreadTest` with caution. Currently,
|
| + **@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
|
| + 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();
|
| + }
|
| + });
|
| + }
|
| + }
|
| + ```
|
| +
|
| +
|
| +1. `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
|
| + 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)
|
|
|