diff --git a/docs/html/training/testing/ui-testing/index.jd b/docs/html/training/testing/ui-testing/index.jd index 20422f7b424fd..d660c601d5037 100644 --- a/docs/html/training/testing/ui-testing/index.jd +++ b/docs/html/training/testing/ui-testing/index.jd @@ -72,5 +72,5 @@ Testing UI for a Single App
Unit tests are the fundamental tests in your app testing strategy. By creating and running unit +tests against your code, you can easily verify that the logic of individual units is correct. +Running unit tests after every build helps you to +quickly catch and fix software regressions introduced by code changes to your app. +
+ +A unit test generally exercises the functionality of the smallest possible unit of code (which +could be a method, class, or component) in a repeatable way. You should build unit tests when you +need to verify the logic of specific code in your app. For example, if you are unit testing a +class, your test might check that the class is in the right state. Typically, the unit of code +is tested in isolation; your test affects and monitors changes to that unit only. A +mocking framework +can be used to isolate your unit from its dependencies.
+ +Note: Unit tests are not suitable for testing +complex UI interaction events. Instead, you should use the UI testing frameworks, as described in +Automating UI Tests.
+ +For testing Android apps, you typically create these types of automated unit tests:
+ +The lessons in this class teach you how to build these types of automated unit tests.
+ ++Instrumented unit tests are unit tests that run on physical devices and emulators, instead of +the Java Virtual Machine (JVM) on your local machine. You should create instrumented unit tests +if your tests need access to instrumentation information (such as the target app's +{@link android.content.Context}) or if they require the real implementation of an Android framework +component (such as a {@link android.os.Parcelable} or {@link android.content.SharedPreferences} +object). Using instrumented unit tests also helps to reduce the effort required to write and +maintain mock code. You are still free to use a mocking framework, if you choose, to simulate any +dependency relationships. Instrumented unit tests can take advantage of the Android framework APIs +and supporting APIs, such as the Android Testing Support Library. +
+ +Before building instrumented unit tests, you must:
+ +app/src/androidTest/java folder.
+ To learn more about setting up your project directory, see
+ Managing Projects.
+
+dependencies {
+ androidTestCompile 'com.android.support.test:runner:0.2'
+ androidTestCompile 'com.android.support.test:rules:0.2'
+ // Set this dependency if you want to use Hamcrest matching
+ androidTestCompile 'org.hamcrest:hamcrest-library:1.1'
+}
+
+ +Your instrumented unit test class should be written as a JUnit 4 test class. To learn more about +creating JUnit 4 test classes and using JUnit 4 assertions and annotations, see +Create a Local Unit Test Class. +
+To create an instrumented JUnit 4 test class, add the {@code @RunWith(AndroidJUnit4.class)} +annotation at the beginning of your test class definition. You also need to specify the + +{@code AndroidJUnitRunner} class +provided in the Android Testing Support Library as your default test runner. This step is described +in more detail in Run Instrumented Unit Tests. +
+ +The following example shows how you might write an instrumented unit test to test that +the {@link android.os.Parcelable} interface is implemented correctly for the +{@code LogHistory} class:
+ +
+import android.os.Parcel;
+import android.support.test.runner.AndroidJUnit4;
+import android.util.Pair;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import java.util.List;
+import static org.hamcrest.Matchers.is;
+import static org.junit.Assert.assertThat;
+
+@RunWith(AndroidJUnit4.class)
+public class LogHistoryAndroidUnitTest {
+
+ public static final String TEST_STRING = "This is a string";
+ public static final long TEST_LONG = 12345678L;
+ private LogHistory mLogHistory;
+
+ @Before
+ public void createLogHistory() {
+ mLogHistory = new LogHistory();
+ }
+
+ @Test
+ public void logHistory_ParcelableWriteRead() {
+ // Set up the Parcelable object to send and receive.
+ mLogHistory.addEntry(TEST_STRING, TEST_LONG);
+
+ // Write the data.
+ Parcel parcel = Parcel.obtain();
+ mLogHistory.writeToParcel(parcel, mLogHistory.describeContents());
+
+ // After you're done with writing, you need to reset the parcel for reading.
+ parcel.setDataPosition(0);
+
+ // Read the data.
+ LogHistory createdFromParcel = LogHistory.CREATOR.createFromParcel(parcel);
+ List<Pair<String, Long>> createdFromParcelData = createdFromParcel.getData();
+
+ // Verify that the received data is correct.
+ assertThat(createdFromParcelData.size(), is(1));
+ assertThat(createdFromParcelData.get(0).first, is(TEST_STRING));
+ assertThat(createdFromParcelData.get(0).second, is(TEST_LONG));
+ }
+}
+
+
++To organize the execution of your instrumented unit tests, you can group a collection of test +classes in a test suite class and run these tests together. Test suites can be nested; +your test suite can group other test suites and run all their component test classes together. +
+ ++A test suite is contained in a test package, similar to the main application package. By +convention, the test suite package name usually ends with the {@code .suite} suffix (for example, +{@code com.example.android.testing.mysample.suite}). +
+ ++To create a test suite for your unit tests, import the JUnit +{@code RunWith} and +{@code Suite} classes. In your test suite, add the +{@code @RunWith(Suite.class)} and the {@code @Suite.SuitClasses()} annotations. In +the {@code @Suite.SuiteClasses()} annotation, list the individual test classes or test +suites as arguments. +
+ ++The following example shows how you might implement a test suite called {@code UnitTestSuite} +that groups and runs the {@code CalculatorInstrumentationTest} and +{@code CalculatorAddParameterizedTest} test classes together. +
+ +
+import com.example.android.testing.mysample.CalculatorAddParameterizedTest;
+import com.example.android.testing.mysample.CalculatorInstrumentationTest;
+import org.junit.runner.RunWith;
+import org.junit.runners.Suite;
+
+// Runs all unit tests.
+@RunWith(Suite.class)
+@Suite.SuiteClasses({CalculatorInstrumentationTest.class,
+ CalculatorAddParameterizedTest.class})
+public class UnitTestSuite {}
+
+
++The + + Android Plug-in for Gradle +provides a default directory ({@code src/androidTest/java}) for you to store the instrumented unit +and integration test classes and test suites that you want to run on a device. The plug-in compiles +the test code in that directory and then executes the test app using a test runner class. You must +set the + +{@code AndroidJUnitRunner} class provided in the +Android Testing Support Library +as your default test runner.
+ + +To specify + +{@code AndroidJUnitRunner} as the default test instrumentation runner, add the following +setting in your {@code build.gradle} file:
+
+android {
+ defaultConfig {
+ testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
+ }
+}
+
+
++To run instrumented unit tests in your Gradle project from Android Studio: +
+Android Studio displays the results of the unit test execution in the Run +window.
+ +To run instrumented unit tests in your Gradle project from the command-line, call the + {@code connectedCheck} (or {@code cC}) task:
+ ++./gradlew cC ++ +
You can find the generated HTML test result reports in the +{@code <path_to_your_project>/app/build/outputs/reports/androidTests/connected/} directory, +and the corresponding XML files in the +{@code <path_to_your_project>/app/build/outputs/androidTest-results/connected/} directory.
\ No newline at end of file diff --git a/docs/html/training/testing/unit-testing/local-unit-tests.jd b/docs/html/training/testing/unit-testing/local-unit-tests.jd new file mode 100644 index 0000000000000..421709beaacc3 --- /dev/null +++ b/docs/html/training/testing/unit-testing/local-unit-tests.jd @@ -0,0 +1,302 @@ +page.title=Building Local Unit Tests +page.tags=testing,androidjunitrunner,junit,unit test,mock +trainingnavtop=true + +@jd:body + + +If your unit test has no dependencies or only has simple dependencies on Android, you should run +your test on a local development machine. This testing approach is efficient because it helps +you avoid the overhead of loading the target app and unit test code onto a physical device or +emulator every time your test is run. Consequently, the execution time for running your unit +test is greatly reduced. With this approach, you normally use a mocking framework, like +Mockito, to fulfill any +dependency relationships.
+ +Android Plug-in for Gradle +version 1.1.0 and higher allows you to create a source directory ({@code src/test/java}) in your +project to store JUnit tests that you want to run on a local machine. This feature improves your +project organization by letting you group your unit tests together into a single source set. You +can run the tests from Android Studio or the command-line, and the plugin executes them on the +local Java Virtual Machine (JVM) on your development machine.
+ +Before building local unit tests, you must:
+ +app/src/test/java folder.
+ To learn more about setting up your project directory, see
+ Run Local Unit Tests and
+ Managing Projects.
+
+dependencies {
+ // Unit testing dependencies
+ testCompile 'junit:junit:4.12'
+ // Set this dependency if you want to use Mockito
+ testCompile 'org.mockito:mockito-core:1.10.19'
+ // Set this dependency if you want to use Hamcrest matching
+ androidTestCompile 'org.hamcrest:hamcrest-library:1.1'
+}
+
+ Your local unit test class should be written as a JUnit 4 test class. +JUnit is the most popular +and widely-used unit testing framework for Java. The latest version of this framework, JUnit 4, +allows you to write tests in a cleaner and more flexible way than its predecessor versions. Unlike +the previous approach to Android unit testing based on JUnit 3, with JUnit 4, you do not need to +extend the {@code junit.framework.TestCase} class. You also do not need to prefix your test method +name with the {@code ‘test’} keyword, or use any classes in the {@code junit.framework} or +{@code junit.extensions} package.
+ +To create a basic JUnit 4 test class, create a Java class that contains one or more test methods. +A test method begins with the {@code @Test} annotation and contains the code to exercise +and verify a single functionality in the component that you want to test.
+ +The following example shows how you might implement a local unit test class. The test method +{@code emailValidator_CorrectEmailSimple_ReturnsTrue} verifies that the {@code isValidEmail()} +method in the app under test returns the correct result.
+ +
+import org.junit.Test;
+import java.util.regex.Pattern;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+public class EmailValidatorTest {
+
+ @Test
+ public void emailValidator_CorrectEmailSimple_ReturnsTrue() {
+ assertThat(EmailValidator.isValidEmail("name@email.com"), is(true));
+ }
+ ...
+}
+
+
+To test that components in your app return the expected results, use the + +junit.Assert methods to perform validation checks (or assertions) to compare the state +of the component under test against some expected value. To make tests more readable, you +can use +Hamcrest matchers (such as the {@code is()} and {@code equalTo()} methods) to match the +returned result against the expected result.
+ +In your JUnit 4 test class, you can use annotations to call out sections in your test code for +special processing, such as:
+ ++By default, the +Android Plug-in for Gradle executes your local unit tests against a modified +version of the {@code android.jar} library, which does not contain any actual code. Instead, method +calls to Android classes from your unit test throw an exception. +
++You can use a mocking framework to stub out external dependencies in your code, to easily test that +your component interacts with a dependency in an expected way. By substituting Android dependencies +with mock objects, you can isolate your unit test from the rest of the Android system while +verifying that the correct methods in those dependencies are called. The +Mockito mocking framework +for Java (version 1.9.5 and higher) offers compatibility with Android unit testing. +With Mockito, you can configure mock objects to return some specific value when invoked.
+ +To add a mock object to your local unit test using this framework, follow this programming model: +
+ ++The following example shows how you might create a unit test that uses a mock +{@link android.content.Context} object. +
+ +
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.CoreMatchers.*;
+import static org.mockito.Mockito.*;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.runners.MockitoJUnitRunner;
+import android.content.SharedPreferences;
+
+@RunWith(MockitoJUnitRunner.class)
+public class UnitTestSample {
+
+ private static final String FAKE_STRING = "HELLO WORLD";
+
+ @Mock
+ Context mMockContext;
+
+ @Test
+ public void readStringFromContext_LocalizedString() {
+ // Given a mocked Context injected into the object under test...
+ when(mMockContext.getString(R.string.hello_word))
+ .thenReturn(FAKE_STRING);
+ ClassUnderTest myObjectUnderTest = new ClassUnderTest(mMockContext);
+
+ // ...when the string is returned from the object under test...
+ String result = myObjectUnderTest.getHelloWorldString();
+
+ // ...then the result should be the expected one.
+ assertThat(result, is(FAKE_STRING));
+ }
+}
+
+
++To learn more about using the Mockito framework, see the +Mockito API reference and the +{@code SharedPreferencesHelperTest} class in the +sample code. +
+ ++The Android Plug-in for Gradle provides a default directory ({@code src/test/java}) for you to +store unit test classes that you want to run on a local JVM. The plug-in compiles the test code in +that directory and then executes the test app locally using the default test runner class. +
++As with production code, you can create unit tests for a +specific flavor or build type. You should keep unit tests in a test +source tree location that corresponds to your production source tree, such as: + +
| Path to Production Class | +Path to Local Unit Test Class | +
|---|---|
| {@code src/main/java/Foo.java} | +{@code src/test/java/FooTest.java} | +
| {@code src/debug/java/Foo.java} | +{@code src/testDebug/java/FooTest.java} | +
| {@code src/myFlavor/java/Foo.java} | +{@code src/testMyFlavor/java/FooTest.java} | +
+To run local unit tests in your Gradle project from Android Studio: +
+Android Studio displays the results of the unit test execution in the Run +window.
+ +To run local unit tests in your Gradle project from the command-line, call the {@code test} task +command with the {@code --continue} option.
+ ++./gradlew test --continue ++ +
If there are failing tests, the command will display links to HTML reports (one per build +variant). You can find the generated HTML test result reports in the +{@code <path_to_your_project>/app/build/reports/tests/} directory, and the corresponding XML +files in the {@code <path_to_your_project>/app/build/test-results/} directory.
\ No newline at end of file diff --git a/docs/html/training/training_toc.cs b/docs/html/training/training_toc.cs index 862663eefa1c6..089739bd002fe 100644 --- a/docs/html/training/training_toc.cs +++ b/docs/html/training/training_toc.cs @@ -1875,6 +1875,24 @@ results." +