Skip to content

Commit da1ac2e

Browse files
committed
Replace test runner with JUnit runner
1 parent 2ea701d commit da1ac2e

File tree

8 files changed

+144
-147
lines changed

8 files changed

+144
-147
lines changed

smoke-tests/README.md

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,15 @@ is a work in progress, and the following list shows what is complete:
1515
# Project Structure
1616

1717
This Gradle project is split into flavors for each Firebase product. Test code
18-
lives in these flavors. Each flavor has a single activity with the test methods.
19-
Test methods are annotated with `SmokeTest`. The Android plugin adds additional,
20-
compound flavors, such as `androidTestDatabase`. These should only contain a
21-
test class that extends `SmokeTestBase`. The are no formal test methods in these
22-
classes.
18+
lives in these flavors. Each flavor has one or more test classes in the app APK.
19+
These are regular JUnit tests.
20+
21+
There is only one testing variant, `androidTest`. This contains the
22+
`SmokeTestSuite` JUnit test runner. This custom runner finds the test classes by
23+
searching for metadata in the application's Android manifest. Therefore, a
24+
metadata tag named `com.google.firebase.testing.classes` is needed in each
25+
application variant with a comma-separated list of test class names. The
26+
`androidTest` variant does not need to be modified by test authors.
2327

2428
# Test Workflow
2529

@@ -28,8 +32,7 @@ As we want to test building as a third-party consumer, the test code and
2832
Firebase dependencies all belong in the application APK. This can be optionally
2933
obfsucated like a real application.
3034

31-
To simplify the tests, all test code is one source tree. The test source tree is
32-
presently required for bootstrapping the testing procedure and does not house
33-
anything related to the test methods. The test class reflectively finds and
34-
executes the test methods from the application APK. This may be simplified in
35-
the future.
35+
The Android instrumentation runner loads one test class, `SmokeTests`. This is
36+
executed by the `SmokeTestSuite`. `SmokeTests` is simply a placeholder class to
37+
bootstrap the logic contained in the suite runner, which then delegates to the
38+
test runners for the classes referenced by the Android manifest.

smoke-tests/build.gradle

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -29,11 +29,6 @@ apply plugin: "com.android.application"
2929
android {
3030
compileSdkVersion 24
3131

32-
compileOptions {
33-
sourceCompatibility JavaVersion.VERSION_1_8
34-
targetCompatibility JavaVersion.VERSION_1_8
35-
}
36-
3732
defaultConfig {
3833
minSdkVersion 16
3934
multiDexEnabled true
@@ -58,18 +53,18 @@ repositories {
5853
dependencies {
5954
// Common
6055

61-
implementation "com.google.firebase:firebase-common:16.0.7"
56+
api "androidx.test:runner:1.1.0"
57+
api "junit:junit:4.12"
6258

63-
androidTestImplementation "androidx.test:runner:1.1.0"
59+
implementation "androidx.test:rules:1.1.0"
60+
implementation "com.google.firebase:firebase-common:16.0.7"
6461

6562
// Firestore
6663
firestoreImplementation "com.google.android.gms:play-services-tasks:16.0.1"
6764
firestoreImplementation "com.google.firebase:firebase-auth:16.1.0"
6865
firestoreImplementation "com.google.firebase:firebase-firestore:18.1.0"
6966
firestoreImplementation "com.google.truth:truth:0.43"
7067

71-
androidTestFirestoreImplementation "androidx.test:rules:1.1.0"
72-
androidTestFirestoreImplementation "junit:junit:4.12"
7368
}
7469

7570
apply plugin: "com.google.gms.google-services"

smoke-tests/src/androidTest/java/com/google/firebase/testing/common/SmokeTestRunner.java

Lines changed: 0 additions & 73 deletions
This file was deleted.
Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
// Copyright 2018 Google LLC
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package com.google.firebase.testing.common;
16+
17+
import android.content.Context;
18+
import android.content.pm.ApplicationInfo;
19+
import android.content.pm.PackageManager;
20+
import androidx.test.InstrumentationRegistry;
21+
import java.util.ArrayList;
22+
import java.util.Arrays;
23+
import java.util.List;
24+
import org.junit.runner.Description;
25+
import org.junit.runner.Runner;
26+
import org.junit.runner.notification.RunNotifier;
27+
import org.junit.runners.ParentRunner;
28+
import org.junit.runners.model.InitializationError;
29+
import org.junit.runners.model.RunnerBuilder;
30+
31+
/**
32+
* A runner for smoke tests.
33+
*
34+
* <p>This is a JUnit runner inspired by the {@code Suite} runner from JUnit. That runner uses an
35+
* annotation to determine the classes in the suite. This runner, on the other hand, uses metadata
36+
* in the application's Android manifest. Therefore, a single test class can be reused with many
37+
* different test suites by simply changing the manifest.
38+
*
39+
* <p>The application's manifest must include metadata with the name {@code
40+
* com.google.firebase.testing.classes} or else this run with fail to run. This item is expected to
41+
* be a comma-separated list of class names. These class names must be valid, loadable JUnit test
42+
* classes in the application APK.
43+
*/
44+
public class SmokeTestSuite extends ParentRunner<Runner> {
45+
46+
private static final String TAG = "SmokeTestSuite";
47+
private static final String TEST_CLASSES_KEY = "com.google.firebase.testing.classes";
48+
49+
private final List<Runner> runners;
50+
51+
public SmokeTestSuite(Class<?> clazz, RunnerBuilder builder) throws InitializationError {
52+
super(clazz);
53+
this.runners = builder.runners(clazz, getTestClasses());
54+
}
55+
56+
@Override
57+
protected Description describeChild(Runner runner) {
58+
return runner.getDescription();
59+
}
60+
61+
@Override
62+
protected List<Runner> getChildren() {
63+
return runners;
64+
}
65+
66+
@Override
67+
protected void runChild(Runner runner, RunNotifier notifier) {
68+
runner.run(notifier);
69+
}
70+
71+
private static List<Class<?>> getTestClasses() throws InitializationError {
72+
Context ctx = InstrumentationRegistry.getTargetContext();
73+
return getTestClasses(ctx);
74+
}
75+
76+
private static List<Class<?>> getTestClasses(Context ctx) throws InitializationError {
77+
List<String> names = getTestClassNames(ctx);
78+
ArrayList<Class<?>> classes = new ArrayList<>(names.size());
79+
80+
try {
81+
for (String name : names) {
82+
Class<?> c = Class.forName(name);
83+
classes.add(c);
84+
}
85+
} catch (ClassNotFoundException ex) {
86+
throw new InitializationError(ex);
87+
}
88+
89+
return classes;
90+
}
91+
92+
private static List<String> getTestClassNames(Context ctx) throws InitializationError {
93+
String name = ctx.getPackageName();
94+
try {
95+
PackageManager pm = ctx.getPackageManager();
96+
ApplicationInfo ai = pm.getApplicationInfo(name, PackageManager.GET_META_DATA);
97+
String names = ai.metaData.getString(TEST_CLASSES_KEY);
98+
99+
if (names == null) {
100+
throw new InitializationError("No test classes found in Application Manifest");
101+
}
102+
103+
return Arrays.asList(names.split(","));
104+
} catch (PackageManager.NameNotFoundException ex) {
105+
throw new InitializationError(ex);
106+
}
107+
}
108+
}

smoke-tests/src/main/java/com/google/firebase/testing/common/SmokeTest.java renamed to smoke-tests/src/androidTest/java/com/google/firebase/testing/common/SmokeTests.java

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,8 @@
1414

1515
package com.google.firebase.testing.common;
1616

17-
import java.lang.annotation.ElementType;
18-
import java.lang.annotation.Retention;
19-
import java.lang.annotation.RetentionPolicy;
20-
import java.lang.annotation.Target;
17+
import org.junit.runner.RunWith;
2118

22-
/** Marks a method as a smoke test. */
23-
@Retention(RetentionPolicy.RUNTIME)
24-
@Target(ElementType.METHOD)
25-
public @interface SmokeTest {}
19+
/** An empty class that serves as the entrypoint for the smoke tests. */
20+
@RunWith(SmokeTestSuite.class)
21+
public final class SmokeTests {}

smoke-tests/src/androidTestFirestore/java/com/google/firebase/testing/firestore/FirestoreTest.java

Lines changed: 0 additions & 42 deletions
This file was deleted.

smoke-tests/src/firestore/AndroidManifest.xml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,14 @@
44
<uses-permission android:name="android.permission.INTERNET" />
55

66
<application>
7-
<activity android:name="com.google.firebase.testing.firestore.FirestoreActivity">
7+
<activity android:name="android.app.Activity">
88
<intent-filter>
99
<action android:name="android.intent.action.MAIN" />
1010
<category android:name="android.intent.category.LAUNCHER" />
1111
</intent-filter>
1212
</activity>
13+
14+
<meta-data android:name="com.google.firebase.testing.classes"
15+
android:value="com.google.firebase.testing.firestore.FirestoreTest" />
1316
</application>
1417
</manifest>

smoke-tests/src/firestore/java/com/google/firebase/testing/firestore/FirestoreActivity.java renamed to smoke-tests/src/firestore/java/com/google/firebase/testing/firestore/FirestoreTest.java

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@
1717
import static com.google.common.truth.Truth.assertThat;
1818

1919
import android.app.Activity;
20+
import androidx.test.rule.ActivityTestRule;
21+
import androidx.test.runner.AndroidJUnit4;
2022
import com.google.android.gms.tasks.Task;
2123
import com.google.android.gms.tasks.TaskCompletionSource;
2224
import com.google.firebase.auth.FirebaseAuth;
@@ -26,14 +28,19 @@
2628
import com.google.firebase.firestore.FirebaseFirestore;
2729
import com.google.firebase.firestore.FirebaseFirestoreException;
2830
import com.google.firebase.firestore.ListenerRegistration;
29-
import com.google.firebase.testing.common.SmokeTest;
3031
import com.google.firebase.testing.common.Tasks2;
3132
import java.util.HashMap;
33+
import org.junit.Rule;
34+
import org.junit.Test;
35+
import org.junit.runner.RunWith;
3236

33-
/** An empty activity with Firestore smoke tests. */
34-
public final class FirestoreActivity extends Activity {
37+
/** Firestore smoke tests. */
38+
@RunWith(AndroidJUnit4.class)
39+
public final class FirestoreTest {
3540

36-
@SmokeTest
41+
@Rule public final ActivityTestRule<Activity> activity = new ActivityTestRule<>(Activity.class);
42+
43+
@Test
3744
public void listenForUpdate() throws Exception {
3845
FirebaseAuth auth = FirebaseAuth.getInstance();
3946
FirebaseFirestore firestore = FirebaseFirestore.getInstance();

0 commit comments

Comments
 (0)