• Home
Name Date Size #Lines LOC

..--

example/03-May-2024-257145

testrule/03-May-2024-517345

testrunner/03-May-2024-215161

textexecutor/03-May-2024-10741

README.mdD03-May-20249.4 KiB300242

README.md

1# SDK Sandbox Test Scenario Test Utilities
2
3## Overview
4
5This directory contains utilities that allow you to run tests inside of an SDK.
6
7[design](http://go/sandbox-webview-cts-tests) (*only visible to Googlers)
8
9Three public class are provided:
10- SdkSandboxScenarioRule: This is a custom JUnit rule used for creating a test environment
11and invoking test methods
12- SdkSandboxTestScenarioRunner: This is a custom SandboxedSdkProvider that manages test
13invocations and reporting the results from within a SDK Sandbox
14- KeepSdkSandboxAliveRule: This optional JUnit rule can be used to force the SDK Sandbox
15manager to stay alive between test runs
16
17## Creating new SDK Runtime tests
18
19A simple example of using SDK Runtime testscenario utilities can be found in
20//packages/modules/AdServices/sdksandbox/tests/testutils/testscenario/example.
21
22If you need to add an entirely new JUnit test suite, you need to add both a JUnit test
23suite, and a new testable SDK.
24
25### Create a new Test SDK
26
27You will first need to define a new Sandbox SDK with your
28test cases. Create a new module for your sdk side tests.
29Inside it, create three new files:
30- AndroidManifest.xml
31- Android.bp
32- src/<package/path>/\<TestName>TestSdk.java
33
34Write to the `Android.bp`:
35
36```soong
37android_test_helper_app {
38    name: "<TestName>TestSdk",
39    manifest: "AndroidManifest.xml",
40    // This is a certificate provided by the
41    // sandbox test utilities that will be used
42    // by your JUnit test suite to load
43    // this sdk.
44    certificate: ":sdksandbox-test",
45    srcs: [
46       "src/**/*.java",
47    ],
48    platform_apis: true,
49    // This runner is used to execute SDK side tests.
50    static_libs: ["CtsSdkSandboxTestRunner"],
51    libs: ["android.test.base"],
52}
53```
54
55Write to the `AndroidManifest.xml`:
56
57```xml
58<!-- This is all normal configuration for a Sandbox SDK provider -->
59<manifest xmlns:android="http://schemas.android.com/apk/res/android"
60          package="<your.test.package>">
61
62    <application>
63        <sdk-library android:name="<your.test.package>"
64                     android:versionMajor="1" />
65        <property android:name="android.sdksandbox.PROPERTY_SDK_PROVIDER_CLASS_NAME"
66                  android:value="<your.test.package>.<TestName>TestSdk" />
67    </application>
68</manifest>
69```
70
71Finally define a test within \<TestName>Sdk.java (eg: ExampleSandboxTestSdk):
72
73```java
74import com.android.sdkSandboxTestUtils.SdkSandboxTestScenarioRunner;
75
76// The SdkSandboxTestScenarioRunner will be responsible
77// for listening for commands to execute tests from
78// the JUnit test suite and returning results.
79public class ExampleSandboxTestSdk extends SdkSandboxTestScenarioRunner {
80    @Override
81    public View beforeEachTest(Context windowContext, Bundle params, int width, int height) {
82        // You can optionally override this method to return a view
83        // that should be added to the sandbox before each test.
84        // ...
85    }
86
87    @Test
88    public void testExample() {
89        // You write tests as you normally would.
90        // These test failures will be propagated back to the JUnit
91        // test suite.
92        assertTrue(true);
93    }
94
95    // You can optionally expect parameters
96    // as part of the test definitions.
97    // This is useful for when tests require
98    // setup externally and need configuration.
99    // For example, a local host server is set up
100    // outside this test and this test needs to know
101    // what port it's running on.
102    @Test
103    public void testExampleWithParam(Bundle params) {
104        params.getString("someParameter");
105    }
106}
107```
108
109These tests will not execute on their own.
110They need to be invoked from a JUnit test suite.
111We will add this in the next section.
112
113### Invoke from a JUnit test suite
114
115This guide will skip over defining a new JUnit test suite,
116as this is the same as any other JUnit test suite in CTS.
117
118Within the `AndroidManifest.xml`, specify that the
119JUnit test suite APK relies on the SDK you defined:
120
121```xml
122<application>
123    <!-- Note the certificate should be what is defined here - this is sdksandbox-test -->
124    <uses-sdk-library android:name="<your.test.sdk.package>"
125        android:versionMajor="1"
126        android:certDigest="0B:44:2D:88:FA:A7:B3:AD:23:8D:DE:29:8A:A1:9B:D5:62:03:92:0B:BF:D8:D3:EB:C8:99:33:2C:8E:E1:15:99" />
127</application>
128```
129
130In `AndroidTest.xml`, specify that your test needs to install
131the SDK you created:
132
133```xml
134<target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
135    <option name="test-file-name" value="<TestName>Sdk" />
136</target_preparer>
137```
138
139Finally, define that your SDK should
140be built and your JUnit test suite relies on
141CtsSdkSandboxTestScenario in your `Android.bp`:
142
143```soong
144...
145static_libs: [
146    // This will be used to invoke test methods
147    // from within the test Sandbox SDK.
148    "CtsSdkSandboxTestScenario",
149],
150data: [
151    // Define your test SDK as a data
152    // dependency so that it is built before
153    // this JUnit test suite is built.
154    ":<TestName>TestSdk",
155],
156...
157```
158
159You can now invoke tests from your JUnit test suite:
160
161```java
162import android.app.sdksandbox.testutils.testscenario.SdkSandboxScenarioRule;
163
164public class ExampleSandboxTest {
165    // This rule will automatically create a new test activity
166    // and load your test SDK between each test.
167    @Rule
168    public final SdkSandboxScenarioRule sdkTester = new SdkSandboxScenarioRule(
169        "your.test.sdk.package");
170
171    @Test
172    public void testExample() throws Exception {
173        // This method will invoke a test and assert the results.
174        sdkTester.assertSdkTestRunPasses("testExample");
175
176        // You can optionally provide parameters to your
177        // tests for setup.
178        Bundle params = new Bundle();
179        params.put("someParameter", "A value");
180        sdkTester.assertSdkTestRunPasses("testExampleWithParam", params);
181    }
182}
183```
184
185## Custom test instances
186
187The `SdkSandboxTestScenarioRunner` supports invoking tests on different
188test instances from the class running your tests inside the test SDK.
189For example, you may have tests you wish to also run in a non SDK context.
190
191```java
192// You can define tests inside a separate class.
193public class ActuallyHasTests {
194    @Test
195    public void someTest() {
196        assertTrue(true);
197    }
198}
199
200public class ExampleSandboxTestSdk extends SdkSandboxTestScenarioRunner {
201    // And then optionally override the onLoadSdk method and use
202    // the API setTestInstance to set an instance to invoke tests from.
203    @Override
204    public SandboxedSdk onLoadSdk(Bundle params) {
205        setTestInstance(new ActuallyHasTests());
206        return super.onLoadSdk(params);
207    }
208}
209```
210
211## Custom setup
212
213There may be times when you need to pass through custom setup information to your sdk.
214
215You can optionally provide a Bundle
216(https://developer.android.com/reference/android/os/Bundle) to SdkSandboxScenarioRule
217that can be retrieved and used from inside test SDKs via the onLoadSdk method.
218
219One example is if you want to reuse an sdk in order to test multiple test instances. For this you
220could pass setup information to determine the specific test instance to use:
221
222```java
223public class ExampleSandboxTestSdk extends SdkSandboxTestScenarioRunner {
224
225    private ExampleParentTestClass mTestInstance;
226
227    @Override
228    public SandboxedSdk onLoadSdk(Bundle params) {
229        Bundle setupParams = params.getBundle(ISdkSandboxTestExecutor.TEST_SETUP_PARAMS);
230        if (setupParams != null) {
231            //logic for setting mTestInstance based on params
232            mTestInstance = new ExampleChildTestClass();
233        }
234
235        setTestInstance(mTestInstance);
236        return super.onLoadSdk(params);
237    }
238}
239```
240
241## Custom test binders
242
243There may be times where you want your tests to invoke behavior outside of
244the SDK. For example, you may want to perform a tap event using the instrumentation.
245
246You can optionally provide a custom [IBinder]
247(https://developer.android.com/reference/android/os/IBinder) to SdkSandboxScenarioRule
248that can be retrieved and used from inside test SDKs.
249
250In the example below, the following custom aidl will be used:
251
252```aidl
253interface SharedCustomBinder {
254    void doesSomethingOutsideSdk();
255}
256```
257
258```java
259public class ExampleSandboxTest {
260    // Provide a stub to the SdkSandboxScenarioRule.
261    @Rule
262    public final SdkSandboxScenarioRule sdkTester = new SdkSandboxScenarioRule(
263        "your.test.sdk.package", new SharedCustomBinder.Stub() {
264            public void doesSomethingOutsideSdk() {
265            }
266        });
267}
268
269public class ExampleSandboxTestSdk extends SdkSandboxTestScenarioRunner {
270    @Test
271    public void exampleTest() throws Exception {
272        // The IBinder can be retrieved inside SDK tests using the API
273        // getCustomInterface().
274        SharedCustomBinder binder = SharedCustomBinder.Stub.asInterface(getCustomInterface());
275        //
276        binder.doesSomethingOutsideSdk();
277        // ...
278    }
279}
280
281```
282
283## Keeping the Sandbox manager alive
284
285For performance reasons, you may want to keep the SDK Sandbox manager alive between each
286unit test. The SDK Sandbox manager will shutdown when the last SDK is unloaded.
287To prevent this from happening, you can use the `KeepSdkSandboxAliveRule`. It expects to be
288provided with the SDK you wish to keep loaded during all your tests. This SDK should preferably
289not do anything·
290
291
292```java
293public class ExampleSandboxTest {
294    //
295    @ClassRule
296    public static final KeepSdkSandboxAliveRule sSdkTestSuiteSetup = new KeepSdkSandboxAliveRule(
297            "any.sdk.you.want");
298}
299```
300