Skip to content

Commit

Permalink
Daft commit: Run tests i CI
Browse files Browse the repository at this point in the history
  • Loading branch information
ekigamba committed Jul 17, 2023
1 parent cfaf286 commit 81a5c9a
Show file tree
Hide file tree
Showing 12 changed files with 469 additions and 121 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -221,7 +221,7 @@ jobs:
force-avd-creation: true
emulator-options: -no-snapshot-save -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none
disable-animations: true
script: ./gradlew :quest:clean && ./gradlew :quest:fhircoreJacocoReport --stacktrace
script: wget https://github.com/ekigamba/debug-jacoco-reports/releases/download/v0.0.1/resources.db && mv resources.db quest/src/androidTest/assets/ && ./gradlew :quest:clean && ./gradlew :quest:fhircoreJacocoReport --stacktrace

- name: Upload Quest module test coverage report to Codecov
if: matrix.api-level == 30 # Only upload coverage on API level 30
Expand Down
80 changes: 80 additions & 0 deletions .github/workflows/performance-tests.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
# This workflow will build a Java project with Gradle
# For more information see: https://help.github.com/actions/language-and-framework-guides/building-and-testing-java-with-gradle

name: Performance tests

on:
pull_request:
branches: [ main ]

env:
FHIRCORE_USERNAME: ${{ secrets.FHIRCORE_USERNAME }}
FHIRCORE_ACCESS_TOKEN: ${{ secrets.FHIRCORE_ACCESS_TOKEN }}
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}

jobs:

quest-tests:
runs-on: macos-latest
strategy:
matrix:
api-level: [30]
steps:
- name: Cancel Previous workflow runs
uses: styfle/[email protected]
with:
access_token: ${{ github.token }}
- name: Checkout 🛎️
uses: actions/checkout@v2
with:
fetch-depth: 2

- name: Set up JDK 11
uses: actions/setup-java@v1
with:
java-version: 11

- name: Grant execute permission for gradlew
run: chmod +x gradlew
working-directory: android

- name: Copy CI gradle.properties
run: mkdir -p ~/.gradle ; cp .github/ci-gradle.properties ~/.gradle/gradle.properties && cat ~/.gradle/gradle.properties

- name: Setup Gradle cache
uses: gradle/gradle-build-action@v2

- name: Load AVD cache
uses: actions/cache@v2
id: avd-cache
with:
path: |
~/.android/avd/*
~/.android/adb*
key: avd-${{ matrix.api-level }}

- name: Create AVD and generate snapshot for caching
if: steps.avd-cache.outputs.cache-hit != 'true'
uses: reactivecircus/android-emulator-runner@v2
with:
working-directory: android
api-level: ${{ matrix.api-level }}
arch: x86_64
force-avd-creation: false
emulator-options: -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none
disable-animations: false
script: echo "Generated AVD snapshot for caching."

- name: Run Quest module performance tests
uses: reactivecircus/android-emulator-runner@v2
with:
working-directory: android
api-level: ${{ matrix.api-level }}
arch: x86_64
force-avd-creation: true
emulator-options: -no-snapshot-save -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none
disable-animations: true
script: ./gradlew :quest:clean && ./gradlew :quest: --stacktrace -e package org.smartregister.fhircore.quest.performance

- name: Check performance tests
run: ./gradlew :quest:checkPerformance

This file was deleted.

18 changes: 17 additions & 1 deletion android/jacoco.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,27 @@ import org.gradle.testing.jacoco.tasks.JacocoReport

val isApplication = (project.name == "quest")
val actualProjectName = if(isApplication) "opensrp" else project.name
/*
task<Exec>("fhircoreInstrumentedTests") {
val taskName = "connected${if (isApplication) actualProjectName.capitalize() else ""}DebugAndroidTest"
commandLine(taskName, "-- tests org.smartregister.fhircore")
}
task<Exec>("fhircorePerformanceTests") {
val taskName = "connected${if (isApplication) actualProjectName.capitalize() else ""}DebugAndroidTest"
commandLine(taskName, "--tests org.smartregister.fhircore.performance")
}
*/

tasks.create(name = "fhircoreJacocoReport", type = JacocoReport::class) {
dependsOn(
setOf(
"test${if(isApplication) actualProjectName.capitalize() else ""}DebugUnitTest", // Generates unit test coverage report
"connected${if (isApplication) actualProjectName.capitalize() else ""}DebugAndroidTest" // Generates instrumentation test coverage report
//"connected${if (isApplication) actualProjectName.capitalize() else ""}DebugAndroidTest" // Generates instrumentation test coverage report
)
)
reports {
Expand Down
29 changes: 29 additions & 0 deletions android/quest/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
import com.android.build.api.variant.FilterConfiguration.FilterType
import java.io.FileReader
import org.gradle.api.tasks.testing.logging.TestLogEvent
import org.json.JSONObject
import kotlin.collections.hashMapOf

buildscript {
apply(from = "../jacoco.gradle.kts")
Expand Down Expand Up @@ -302,6 +305,10 @@ tasks.withType<Test> {
minHeapSize = "4608m"
maxHeapSize = "4608m"
maxParallelForks = (Runtime.getRuntime().availableProcessors() / 2).takeIf { it > 0 } ?: 1

if (!name.toLowerCase().contains("performance")) {
exclude("org.smartregister.fhircore.performance.*")
}
}

configurations {
Expand Down Expand Up @@ -369,3 +376,25 @@ dependencies {
}
ktlint(project(":linting"))
}

task("checkPerformanceLimits") {
val resultsFile = File("performance-results.json")
val expectationsFile = File("expected-results.json")

// Read the expectations file
val expectedResultsMap : HashMap<String, HashMap<String, Float>> = hashMapOf()

JSONObject(FileReader(expectationsFile).readText()).run {
keys().forEach { key ->
val resultMaxDeltaMap :HashMap<String, Float> = hashMapOf()
val methodExpectedResults = this.getJSONObject("key")

methodExpectedResults.keys().forEach { expectedResultsKey ->
resultMaxDeltaMap.put(expectedResultsKey, methodExpectedResults.getFloat(expectedResultsKey))
}
}
}

// Loop through the results file updating the results
JSONObject
}
6 changes: 6 additions & 0 deletions android/quest/expected-results.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"HouseholdRegisterPerformanceTests2#benchmarkPage0": {
"max": 6.8054019E7,
"delta": 1.8054019E7
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
package org.smartregister.fhircore.performance

import androidx.benchmark.junit4.BenchmarkRule
import androidx.benchmark.junit4.measureRepeated
import androidx.test.platform.app.InstrumentationRegistry
import dagger.hilt.android.testing.HiltAndroidRule
import dagger.hilt.android.testing.HiltAndroidTest
import java.io.File
import java.nio.file.Files
import javax.inject.Inject
import kotlin.io.path.Path
import kotlinx.coroutines.runBlocking
import org.junit.Before
import org.junit.Rule
import org.junit.Test
import org.smartregister.fhircore.engine.data.local.DefaultRepository
import org.smartregister.fhircore.engine.data.local.register.RegisterRepository
import timber.log.Timber

@HiltAndroidTest
class ChildRegisterPerformanceTests {

@get:Rule val benchmarkRule = BenchmarkRule()

@Inject lateinit var defaultRepository: DefaultRepository
@Inject lateinit var registerRepository: RegisterRepository

@get:Rule val hiltRule = HiltAndroidRule(this)

@Before
fun setUp() {
hiltRule.inject()

if (InstrumentationRegistry.getInstrumentation().context.externalCacheDir == null) {
Timber.e("Instrumentation registry is null")
} else {
Timber.e("Instrumentation registry is NOT NULL")
}
// Might need to login

runBlocking {
defaultRepository.configurationRegistry.loadConfigurations(
"app/debug",
InstrumentationRegistry.getInstrumentation().targetContext
) { loadConfigSuccessful ->
}
}

// Copy over the db
val appContext = InstrumentationRegistry.getInstrumentation().targetContext
val testContext = InstrumentationRegistry.getInstrumentation().context

val resourcesDbInputStream = testContext.assets.open("resources.db")

// Delete the database files
"/data/data/${appContext.packageName}/databases/resources.db".deleteFileIsExists()
"/data/data/${appContext.packageName}/databases/resources.db-shm".deleteFileIsExists()
"/data/data/${appContext.packageName}/databases/resources.db-wal".deleteFileIsExists()

// Copy over the db
Files.copy(
resourcesDbInputStream,
Path("/data/data/${appContext.packageName}/databases/resources.db")
)
}

@Test
fun benchmarkPage0() {
benchmarkingFunctionality(0)
}

@Test
fun benchmarkPage1() {
benchmarkingFunctionality(0)
}

@Test
fun benchmarkPage2() {
benchmarkingFunctionality(1)
}

@Test
fun benchmarkPage3() {
benchmarkingFunctionality(2)
}

@Test
fun benchmarkPage4() {
benchmarkingFunctionality(3)
}

@Test
fun benchmarkPage5() {
benchmarkingFunctionality(4)
}

@Test
fun benchmarkPage6() {
benchmarkingFunctionality(5)
}

fun benchmarkingFunctionality(page: Int) {
benchmarkRule.measureRepeated {
runBlocking {
var repoData = registerRepository.loadRegisterData(page, "childRegister")
System.out.println("Records fetched ${repoData.size}")
}
}
}

fun String.deleteFileIsExists() {
try {
if (File(this).exists()) Files.delete(Path(this))
} catch (ex: NoSuchFileException) {}
}
}
Loading

0 comments on commit 81a5c9a

Please sign in to comment.