@@ -25,7 +25,9 @@ import androidx.test.uiautomator.By
2525import androidx.test.uiautomator.UiDevice
2626import androidx.test.uiautomator.UiObject2
2727import androidx.test.uiautomator.Until
28+ import com.google.common.base.Verify.verify
2829import com.google.common.truth.Truth.assertThat
30+ import com.google.firebase.crashlytics.FirebaseCrashlytics
2931import java.util.regex.Pattern
3032import org.junit.After
3133import org.junit.Assert
@@ -34,6 +36,8 @@ import org.junit.Before
3436import org.junit.Test
3537import org.junit.runner.RunWith
3638
39+ const val APP_NAME = " com.example.test_app"
40+
3741@RunWith(AndroidJUnit4 ::class )
3842class FirebaseCrashlyticsIntegrationTest {
3943
@@ -48,44 +52,140 @@ class FirebaseCrashlyticsIntegrationTest {
4852 @After
4953 fun cleanup () {
5054 // Make sure all processes are killed
51- Runtime .getRuntime().exec(arrayOf(" am" , " force-stop" , TEST_APP_PACKAGE ))
55+ Runtime .getRuntime().exec(arrayOf(" am" , " force-stop" , APP_NAME ))
5256 }
5357
58+ // Reuseable function to check logs for a certain term.
59+ fun readLogcat (tagFilter : String ): Boolean {
60+ val logs = mutableListOf<String >()
61+ val process = Runtime .getRuntime().exec(" logcat -d" ) // Fetch error-level logs
62+ process.inputStream.bufferedReader().useLines { lines ->
63+ lines.filter { it.contains(tagFilter) }.forEach { logs.add(it) }
64+ }
65+ return logs.any { it.contains(tagFilter) }
66+ }
67+
68+ // Shared/Common Test Steps
69+
5470 @Test
71+ // Checks that Crashlytics is Enabled in Logcat
5572 fun sharedInitializeCrashlytics () {
56- // Enable verbose logging for FirebaseCrashlytics
57- Runtime .getRuntime().exec(arrayOf(" adb" , " shell" , " setprop" , " log.tag.FirebaseCrashlytics" , " VERBOSE" )).waitFor()
73+ launchApp();
5874
59- // Launch the app
75+ val crashlyticsInitialized = readLogcat(" Initializing Firebase Crashlytics" );
76+
77+ assertThat(crashlyticsInitialized).isTrue()
78+ }
79+
80+ @Test
81+ // Crash can be found associated with set user id.
82+ fun sharedGenerateCrash () {
6083 launchApp()
6184
62- // Start monitoring logs
63- val logcatProcess = ProcessBuilder (" adb" , " logcat" , " -s" , " FirebaseCrashlytics" )
64- .redirectErrorStream(true )
65- .start()
85+ val crashlytics = FirebaseCrashlytics .getInstance()
86+ crashlytics.setUserId(" TestUser123" )
6687
67- val logcatReader = logcatProcess.inputStream.bufferedReader()
88+ getButton( " CRASH! " ).click();
6889
69- // Flag to detect Crashlytics initialization
70- var crashlyticsInitialized = false
90+ val userIdLogFound = readLogcat( " TestUser123 " )
91+ val crashFound = readLogcat( " Test " )
7192
72- // Monitor log output
73- logcatReader.useLines { lines ->
74- for (line in lines) {
75- if (line.contains(" FirebaseCrashlytics is initialized" )) {
76- crashlyticsInitialized = true
77- break
78- }
79- }
80- }
93+ // assertThat(userIdLogFound).isTrue()
94+ assertThat(crashFound).isTrue()
8195
82- // Clean up the logcat process
83- logcatProcess.destroy()
96+ }
8497
85- // Assert that Crashlytics was initialized
86- assertThat(crashlyticsInitialized).isTrue()
98+ @Test
99+ fun sharedVerifyCrash () {
100+ launchApp();
101+
102+ // Initialize Crashlytics and set user metadata as they would online
103+ val crashlytics = FirebaseCrashlytics .getInstance()
104+ crashlytics.setUserId(" TestUser123" )
105+ crashlytics.setCustomKey(" CrashKey" , " TestValue" )
106+ crashlytics.log(" This is a pre-crash log for verification." )
107+
108+ // Trigger the crash
109+ getButton(" CRASH!" ).click()
110+
111+
112+ // Check logcat for defined fields
113+ val userIdLogFound = readLogcat(" TestUser123" )
114+ val customKeyLogFound = readLogcat(" CrashKey" )
115+ val preCrashLogFound = readLogcat(" This is a pre-crash log for verification." )
116+
117+ // Verify the logs were recorded
118+ assertThat(userIdLogFound).isTrue()
119+ assertThat(customKeyLogFound).isTrue()
120+ assertThat(preCrashLogFound).isTrue()
121+ }
122+
123+ @Test
124+ fun sharedVerifyNoCrash () {
125+ launchApp();
126+
127+ // Initialize Crashlytics and set user metadata as they would online
128+ val crashlytics = FirebaseCrashlytics .getInstance()
129+ crashlytics.setUserId(" TestUser123" )
130+ crashlytics.setCustomKey(" CrashKey" , " TestValue" )
131+ crashlytics.log(" This is a pre-crash log for verification." )
132+
133+ // Check logcat for defined fields
134+ val userIdLogFound = readLogcat(" TestUser123" )
135+ val customKeyLogFound = readLogcat(" CrashKey" )
136+ val preCrashLogFound = readLogcat(" This is a pre-crash log for verification." )
137+
138+ // User activity and navigation
139+ navigateToSecondActivity();
140+
141+ Thread .sleep(2000 )
142+
143+ // Verify the logs were recorded
144+ assertThat(userIdLogFound).isTrue()
145+ assertThat(customKeyLogFound).isTrue()
146+ assertThat(preCrashLogFound).isTrue()
87147 }
88148
149+ // Core Scenario
150+
151+ @Test
152+ // Fatal errors are reported by crashlytics
153+ fun firebaseCoreFatalError () {
154+ launchApp()
155+
156+ getButton(" CRASH!" ).click();
157+
158+ val crashFound = readLogcat(" Test" )
159+ assertThat(crashFound).isTrue()
160+ }
161+
162+ // Public APIs
163+
164+ // @Test
165+ // fun publicAPILog() {
166+ //
167+ // }
168+ //
169+ // @Test
170+ // fun publicAPISetCustomValue() {
171+ //
172+ // }
173+ //
174+ // @Test
175+ // fun publicAPISetUserID() {
176+ //
177+ // }
178+ //
179+ // @Test
180+ // fun publicAPIDidCrashPreviously() {
181+ //
182+ // }
183+ //
184+ // @Test
185+ // fun publicAPIRecordException() {
186+ //
187+ // }
188+
89189
90190 // Keeping here for now as an example
91191 @Test
@@ -111,7 +211,7 @@ class FirebaseCrashlyticsIntegrationTest {
111211 // Launch the app
112212 val context = ApplicationProvider .getApplicationContext<Context >()
113213 val intent =
114- context.packageManager.getLaunchIntentForPackage(TEST_APP_PACKAGE )?.apply {
214+ context.packageManager.getLaunchIntentForPackage(APP_NAME )?.apply {
115215 // Clear out any previous instances
116216 addFlags(Intent .FLAG_ACTIVITY_CLEAR_TASK )
117217 }
0 commit comments