Skip to content

Commit

Permalink
ci: run android instrumentation tests on CI (#233)
Browse files Browse the repository at this point in the history
  • Loading branch information
Shahroz16 authored Jul 4, 2023
1 parent 0de5764 commit 9ae6f4c
Show file tree
Hide file tree
Showing 2 changed files with 101 additions and 70 deletions.
90 changes: 63 additions & 27 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,31 +10,67 @@ jobs:
module: [sdk, messagingpush, messaginginapp, base]
name: Unit tests (${{ matrix.module }})
steps:
- uses: actions/checkout@v3
- name: Set up JDK
uses: actions/setup-java@v2
with:
distribution: 'adopt'
java-version: '11' # Robolectric requires v9, but we choose LTS: https://adoptopenjdk.net/
- name: Setup Android SDK
uses: android-actions/setup-android@v2

- name: Run unit tests (${{ matrix.module }})
run: ./gradlew :${{ matrix.module }}:runJacocoTestReport

- name: Upload code coverage report
uses: codecov/codecov-action@v2
with:
token: ${{ secrets.CODECOV_UPLOAD_TOKEN }} # not required for public repos, but sometimes uploads fail without it so include it anyway
fail_ci_if_error: true # fail if upload fails so we can catch it and fix it right away.
verbose: true
files: ./${{ matrix.module }}/build/reports/jacoco/test/jacocoTestReport.xml,./${{ matrix.module }}/build/reports/jacoco/runJacocoTestReport/runJacocoTestReport.xml

- name: Publish test results (${{ matrix.module }})
uses: mikepenz/action-junit-report@v2
with:
report_paths: '**/build/test-results/test*/TEST-*.xml'
fail_on_failure: true
require_tests: true
if: ${{ always() }} # if running tests fails, we still want to parse the test results
- uses: actions/checkout@v3
- name: Set up JDK
uses: actions/setup-java@v2
with:
distribution: 'adopt'
java-version: '11' # Robolectric requires v9, but we choose LTS: https://adoptopenjdk.net/
- name: Setup Android SDK
uses: android-actions/setup-android@v2
- name: Run unit tests (${{ matrix.module }})
run: ./gradlew :${{ matrix.module }}:runJacocoTestReport
- name: Upload code coverage report
uses: codecov/codecov-action@v2
with:
token: ${{ secrets.CODECOV_UPLOAD_TOKEN }} # not required for public repos, but sometimes uploads fail without it so include it anyway
fail_ci_if_error: true # fail if upload fails so we can catch it and fix it right away.
verbose: true
files: ./${{ matrix.module }}/build/reports/jacoco/test/jacocoTestReport.xml,./${{ matrix.module }}/build/reports/jacoco/runJacocoTestReport/runJacocoTestReport.xml
- name: Publish test results (${{ matrix.module }})
uses: mikepenz/action-junit-report@v2
with:
report_paths: '**/build/test-results/test*/TEST-*.xml'
fail_on_failure: true
require_tests: true
if: ${{ always() }} # if running tests fails, we still want to parse the test results

instrumentation-test:
runs-on: macos-latest
timeout-minutes: 45
strategy:
# Add more samples here as they are added to the project.
matrix:
sample: [kotlin_compose, java_layout]
steps:
- uses: actions/checkout@v3
- name: Set up JDK 17
uses: actions/setup-java@v2
with:
distribution: 'adopt'
java-version: '17'
- name: Setup Android SDK
uses: android-actions/setup-android@v2
- name: Gradle cache
uses: gradle/gradle-build-action@v2
- name: Start emulator
uses: reactivecircus/android-emulator-runner@v2
with:
# Configuration options for the emulator for the best optimization.
api-level: 29
force-avd-creation: false
emulator-options: -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none
disable-animations: true
ram-size: 4096M
emulator-boot-timeout: 12000
target: default
arch: x86
emulator-build: 7425822 # https://github.com/ReactiveCircus/android-emulator-runner/issues/160
profile: Nexus 6
# Run the instrumentation tests on the emulator.
script: ./gradlew :samples:${{ matrix.sample }}:connectedDebugAndroidTest
- name: Publish test results
uses: mikepenz/action-junit-report@v2
if: always()
with:
report_paths: 'samples/${{ matrix.sample }}/build/outputs/androidTest-results/connected/TEST-*.xml'
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.platform.app.InstrumentationRegistry
import dagger.hilt.android.testing.HiltAndroidRule
import dagger.hilt.android.testing.HiltAndroidTest
import io.customer.android.sample.kotlin_compose.data.persistance.AppDatabase
import io.customer.android.sample.kotlin_compose.data.repositories.PreferenceRepository
import io.customer.android.sample.kotlin_compose.data.repositories.UserRepository
import io.customer.android.sample.kotlin_compose.data.sdk.InAppMessageEventListener
import io.customer.base.internal.InternalCustomerIOApi
import io.customer.messaginginapp.MessagingInAppModuleConfig
Expand Down Expand Up @@ -49,7 +49,7 @@ class MemoryLeakageInstrumentedTest {
val hiltRule = HiltAndroidRule(this)

@Inject
lateinit var userPreferenceRepository: UserRepository
lateinit var appDatabase: AppDatabase

@Inject
lateinit var preferences: PreferenceRepository
Expand Down Expand Up @@ -85,7 +85,7 @@ class MemoryLeakageInstrumentedTest {

// Delete all users. So we always land in `Login Screen`
runBlocking {
userPreferenceRepository.deleteAllUsers()
appDatabase.clearAllTables()
}
}

Expand All @@ -102,82 +102,77 @@ class MemoryLeakageInstrumentedTest {
ActivityScenario.launch(MainActivity::class.java)

// Enter the user's name and email address.
val name =
composeTestRule.onNodeWithTag(appContext.getString(R.string.acd_first_name_input))
name.performTextInput("MemoryLeakageTest")
composeTestRule.onNodeWithTag(appContext.getString(R.string.acd_first_name_input)).apply {
performTextInput("MemoryLeakageTest")
}

val email = composeTestRule.onNodeWithTag(appContext.getString(R.string.acd_email_input))
email.performTextInput("[email protected]")
composeTestRule.onNodeWithTag(appContext.getString(R.string.acd_email_input)).apply {
performTextInput("[email protected]")
}

// Click the login button.
composeTestRule.onNodeWithTag(appContext.getString(R.string.acd_login_button))
.performClick()

composeTestRule.runOnIdle { }

// wait for 500ms
Thread.sleep(500)
// wait for 1000ms to make sure the user is logged in and home screen is visible
// this is required because we are storing data and at times depending on device that process can be slow
Thread.sleep(1000)

// Click the random event button 50 times.
val randomEvent =
composeTestRule.onNodeWithTag(appContext.getString(R.string.acd_random_event_button))

for (i in 0..50) {
randomEvent.performClick()
}
composeTestRule.onNodeWithTag(appContext.getString(R.string.acd_random_event_button))
.apply {
for (i in 0..50) {
performClick()
}
}

// Assert that there are no leaks.
LeakAssertions.assertNoLeaks()

// Click the send custom event button.
composeTestRule.onNodeWithTag(appContext.getString(R.string.acd_custom_event_button))
.performClick()
composeTestRule.onNodeWithTag(appContext.getString(R.string.acd_custom_event_button)).performClick()

// Enter the event name, property name, and property value.
val eventName =
composeTestRule.onNodeWithTag(appContext.getString(R.string.acd_event_name_input))
eventName.performTextInput("custom event test for memory leak")
composeTestRule.onNodeWithTag(appContext.getString(R.string.acd_event_name_input)).apply {
performTextInput("custom event test for memory leak")
}

val propertyName =
composeTestRule.onNodeWithTag(appContext.getString(R.string.acd_property_name_input))
propertyName.performTextInput("test property")
composeTestRule.onNodeWithTag(appContext.getString(R.string.acd_property_name_input)).apply {
performTextInput("test property")
}

val propertyValue =
composeTestRule.onNodeWithTag(appContext.getString(R.string.acd_property_value_input))
propertyValue.performTextInput("test value")
composeTestRule.onNodeWithTag(appContext.getString(R.string.acd_property_value_input)).apply {
performTextInput("test value")
}

// Click the send button 10
for (i in 0..10) {
composeTestRule.onNodeWithTag(appContext.getString(R.string.acd_send_event_button))
.performClick()
composeTestRule.onNodeWithTag(appContext.getString(R.string.acd_send_event_button)).performClick()
}

// Assert that there are no leaks.
LeakAssertions.assertNoLeaks()

// Click the back button.
composeTestRule.onNodeWithTag(
appContext.getString(R.string.acd_back_button_icon),
useUnmergedTree = true
).performClick()
composeTestRule.onNodeWithTag(appContext.getString(R.string.acd_back_button_icon), useUnmergedTree = true).performClick()

// Click the set device attribute button.
composeTestRule.onNodeWithTag(appContext.getString(R.string.acd_device_attribute_button))
.performClick()
composeTestRule.onNodeWithTag(appContext.getString(R.string.acd_device_attribute_button)).performClick()

// Enter the attribute name and value.
val attributeName =
composeTestRule.onNodeWithTag(appContext.getString(R.string.acd_attribute_name_input))
attributeName.performTextInput("memory test attribute")
composeTestRule.onNodeWithTag(appContext.getString(R.string.acd_attribute_name_input)).apply {
performTextInput("memory test attribute")
}

val attributeValue =
composeTestRule.onNodeWithTag(appContext.getString(R.string.acd_attribute_value_input))
attributeValue.performTextInput("memory test attribute")
composeTestRule.onNodeWithTag(appContext.getString(R.string.acd_attribute_value_input)).apply {
performTextInput("memory test attribute")
}

// Click the send button 10
for (i in 0..10) {
composeTestRule.onNodeWithTag(appContext.getString(R.string.acd_send_device_attribute_button))
.performClick()
composeTestRule.onNodeWithTag(appContext.getString(R.string.acd_send_device_attribute_button)).performClick()
}

// Assert that there are no leaks.
Expand Down

0 comments on commit 9ae6f4c

Please sign in to comment.