[3] Android Testing - mariamaged/Java-Android-Kotlin GitHub Wiki
Android - Touring the Tests
1. Instrumented Tests
- Unit tests run much faster, but they cannot test as much, because they do not have access to everything inside of Android.
- For example, while we could test our ability to
talk to a Web service
fromunit tests
, we cannot test our ability to getGPS locations
usingAndroid APIs
from unit tests. - Similarly, most automated
UI testing
needs instrumented tests, as the Android UI system is only really available to Android.
- For example, while we could test our ability to
1.1 What You Can Test
- However, from a practical standpoint, there will be limits as to what you can test:
- Emulators do not emulate everything about hardware.
- For example, you will not be able to test readings that you get from nearby cell towers, as an emulator is not in communication with any actual cell towers.
- You want your tests to be repeatable.
- Hence, even on hardware, you may need to limit testing what you really get from the hardware, as you do not control that hardware and what it might return.
- For example, while in theory you could test getting actual location data via GPS from a device, you cannot guarantee the precise values that will get returned, as GPS is
inexact by its nature
.
- Any given device has one set of hardware characteristics.
- Any given emulator will mimic one set of hardware characteristics.
- Testing things that
vary based on hardware characteristics
will require multiple test runs across a fleet of devices or emulators that will reflect the varying characteristics.
- Emulators do not emulate everything about hardware.
1.2 The Test Class
Kotlin
package com.mariamaged.helloworld
import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.ext.junit.runners.AndroidJUnit4
import org.junit.Test
import.org.junit.runner.RunWith
import org.junit.Assert.*
@RunWith(AndroidJUnit4::class)
class ExampleInstrumentedTest {
@Test
fun useAppContext() {
// Context of the app under test.
val appContext = InstrumentationRegistry.getInstrumentation().targetContext
assertEquals("com.mariamaged.helloworld", appContext.packageName)
}
}
Java
package com.mariamged.helloworld
import android.content.Context;
import androidx.test.platform.app.InstrumentationRegistry;
import androidx.test.ext.junit.runner.AndroidJUnit4;
import org.junit.Test;
import org.junit.runner.RunWithl;
import static org.junit.Assert.*;
@RunWith(AndroidJUnit4.class)
public class ExampleInstrumentedTest {
@Test
void useAppContext() {
Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext();
assertEquals("com.marimaged.helloworld", appContext.getPackageName());
}
}
1.2.1 The Annotations
- Both Java and Kotlin have a single class, named ExampleInstrumentedTest, annotated with
@RunWith(AndroidJUnit::clas)
annotation.- This annotation tells JUnit - and, more importantly, some Android Studio stuff for running tests - that this class contains
test code
that should be run as part of an instrumented test.
- This annotation tells JUnit - and, more importantly, some Android Studio stuff for running tests - that this class contains
A Test class can contain one or more of these @Test methods/ functions.
- When it comes time to run the tests, Android Studio will:'
- Create an instance of your test class.
- Call one of the @Test methods/ functions on that instance.
- Create another instance of your test class.
- Call another of the @Test methods/ functions on that new instance.
- And so on, until all of the @Test methods/ functions are called.
1.2.2 How You Run Them
- Option 1: you can run/ debug an individual function or method.
- Option 2: you can run all the test functions/ method by clicking the "double-run button" next to the class name.
Correct Test Results
Failing Test Results
1.2.3 The androidTestImplementation Dependencies
- The one that is really required is
androidx.test:runner
.- This is the library that supplies the AndroidJUnitRunner class and other core classes for writing and running our instrumented tests.
- The other one is
androidx.test.espresso:espresso-core
.- This is the core of Espresso, a powerful library for writing GUI tests.
2. Unit Tests
- They too use JUnit tests.
2.1 Where They Run
- Unit tests are the same sort of tests that you would run in an ordinary Java or Kotlin project that had no ties at all to building Android apps.
2.2 What You Can Test
- You can test your
non-Android business logic
fairly easily, just using standard JUnit tests.- However, any code that uses
Android-related classes
is going to have aproblem
, though.
- However, any code that uses
You can past this somewhat by the use of
mocking engines
, such asMockito
.
- They allow you to create
"fake"
Android objects based on real Android classes, where you teach the mocks how to respond to particular method calls.
2.3 The Test Class
Kotlin
package com.mariamaged.helloworld
import org.junit.Test
import org.junit.Assert.*
class ExampleUnitTest {
@Test
fun addition_isCorrect() {
assertEquals(2, 2 + 2)
}
}
Java
package com.mariamaged.helloworld
import org.junit.Test;
import static org.junit.Assert.*;
public class ExampleUnitTest {
@Test
void addition_isCorrect() {
assertEquals(4, 2 + 2);
}
}
2.2.1 Annotations
- Unit classes do not normally get a
@RunWith
annotation. - However, we still put
@Test
annotations on the method or functions that contain the tests to be run.
2.2.2 How You Run Them
- Option 1: Click the green "run" icon next to a test method/ function to run it alone.
- **Option 2: Click the "run" icon next to a test class to run all of its test code.
2.2.3 What the Test Result Look Like
2.2.4 The testImplementation Dependencies
- The one default
testImplementation
dependency isjunit:junit
, which pulls in the JUnit classes.