This page describes how to write a JUnit4-style device test driven by the host. This means that the host side of the harness is going to trigger actions against the device.
Note that we consider "host-side" tests and "host-driven" tests to be slightly different:
- host-driven test: Is a test running on the host that interacts with one or more devices. The system under test (SUT) is not on the host itself but is being tested from the host.
- host-side test: Is a test purely running on the host and testing something only on the host, for example unit tests.
Why create a host-driven test rather than an instrumentation test?
Some tests might require you to affect the device overall state, like issuing a reboot command. In the instrumentation test case, a reboot would kill the instrumentation, the test could not continue, and no results would be available.
Host-driven tests can also drive additional setup steps that require interaction with external devices on which the test depends on.
A host-driven test can handle these use cases and allow for advanced testing of the device with more scenarios. If you are in that situation, writing a host-driven test makes the most sense.
How are host-driven tests written in TF?
Here is a sample:
@RunWith(DeviceJUnit4ClassRunner.class)
public class SampleHostJUnit4DeviceTest extends BaseHostJUnit4Test {
@Before
public void setUp() throws Exception {
// Some setup
}
@Test
public void testCheckWeHaveDevice() throws Exception {
Assert.assertNotNull(getDevice());
}
}
Host-driven tests in Trade Federation are driven by the DeviceJUnit4ClassRunner JUnit4 test runner. The overall structure of the test class is the same as a regular JUnit4 test:
@BeforeClass
@Before
@Test
@After
@AfterClass
Assume
,Assert
Extending BaseHostJunit4Test is a way to inherit useful testing utilities API such as:
installPackage
: Allows to install an APK on the target device.installPackageAsUser
: Allows to install an APK as a user on the target device.uninstallPackage
: Allows to uninstall an APK.isPackageInstalled
: Check whether a package is installed or not.hasDeviceFeature
: Check whether device supports a feature or not. (pm list features
)runDeviceTests(DeviceTestRunOptions options)
: Run an instrumentation test against a target device using DeviceTestRunOptions to handle all the possible options.
Also provide access to the Tradefed device object:
getDevice()
: Returns a TF device object for manipulating the device.getBuild()
: Returns a build info TF object to get information about the build.getAbi()
: Returns the ABI the test is running against.
Tradefed support: Per-class device preparation and clean up
JUnit4 @BeforeClass
and @AfterClass
are only applicable to static methods,
which makes it impossible to use the #getDevice()
handler to do some
device-specific, one-time, per-class setup or clean up. To solve this issue, use
the Tradefed annotation.
- @BeforeClassWithInfo: Runs before @BeforeClass annotations
- @AfterClassWithInfo: Runs after @AfterClass annotations
@BeforeClassWithInfo
public static void beforeClassWithDevice(TestInformation testInfo) {
assertNotNull(testInfo.getDevice());
testInfo.properties().put("mytest:test-prop", "test");
}
@AfterClassWithInfo
public static void afterClassWithDevice(TestInformation testInfo) {
assertNotNull(testInfo.getDevice());
testInfo.properties().put("mytest:test-prop", "test");
}
TestInformation
allows you to use the device and store properties that can be
used either in the static or non-static scope. BaseHostJUnit4Test
supports
getting the TestInformation
in a non-static scope via #getTestInformation()
.
If you are not extending BaseHostJUnit4Test
, you can implement
ITestInformationReceiver
in order to receive the TestInformation
object.
How to configure a host-driven test in Tradefed?
In Tradefed XML configuration file, host-driven tests are run through the HostTest runner.
<test class="com.android.tradefed.testtype.HostTest" >
<option name="class" value="android.sample.cts.SampleHostJUnit4DeviceTest" />
</test>