Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 8 additions & 13 deletions .github/workflows/android.yml
Original file line number Diff line number Diff line change
Expand Up @@ -68,28 +68,23 @@ jobs:

steps:
- name: Checkout
uses: actions/checkout@v3
uses: actions/checkout@v4
with:
fetch-depth: 0 # fetch all history for sonar analysis

- uses: GetStream/android-ci-actions/actions/setup-java@main

- uses: GetStream/android-ci-actions/actions/gradle-cache@main

- name: Run unit tests
run: |
./gradlew :stream-video-android-ui-compose:koverXmlReportDebug --scan --stacktrace
./gradlew :stream-video-android-core:koverXmlReportDebug --scan --stacktrace

- name: Unit tests core results
uses: actions/upload-artifact@v4
with:
name: unit-tests-core-results
path: stream-video-android-core/build/reports/tests/testDebugUnitTest/index.html
run: ./gradlew :testCoverage --scan --stacktrace

- name: Unit tests compose results
- name: Upload tests results
uses: actions/upload-artifact@v4
if: failure()
with:
name: unit-tests-compose-results
path: stream-video-android-ui-compose/build/reports/tests/testDebugUnitTest/index.html
name: testResults
path: ./**/build/reports/tests/**

- uses: GetStream/android-ci-actions/actions/setup-ruby@main

Expand Down
8 changes: 4 additions & 4 deletions build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
apply(plugin = "io.github.gradle-nexus.publish-plugin")
apply(plugin = "org.jetbrains.dokka")
apply(from = "${rootDir}/scripts/sonar.gradle")
apply(from = "${rootDir}/scripts/open-api-code-gen.gradle.kts")

buildscript {
Expand Down Expand Up @@ -61,8 +60,6 @@ subprojects {
)
}
}

apply(from = "${rootDir}/scripts/coverage.gradle")
}

tasks.register("clean")
Expand All @@ -78,6 +75,9 @@ apply(from = "${rootDir}/scripts/publish-root.gradle")
// return File(teamPropsDir, propsFile)
//}

apply(from = "${rootDir}/scripts/sonar.gradle")
apply(from = "${rootDir}/scripts/coverage.gradle")

afterEvaluate {
println("Running Add Pre Commit Git Hook Script on Build")
exec {
Expand All @@ -90,4 +90,4 @@ afterEvaluate {
}
}
println("Added pre-push Git Hook Script.")
}
}
4 changes: 3 additions & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,9 @@ org.gradle.caching=true
org.gradle.parallel=true

# Configure only necessary projects, useful with multimodule projects
org.gradle.configureondemand=true
# Disabling as it causes prevents tweaking tasks configuration in some cases,
# and the performance gain is minimal for our project structure.
#org.gradle.configureondemand=true

# AndroidX Migration https://developer.android.com/jetpack/androidx/migrate
android.useAndroidX=true
Expand Down
4 changes: 2 additions & 2 deletions gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
allureKotlin = "2.4.0"
androidGradlePlugin = "8.4.2"
cameraCamera2 = "1.3.4"
kover = "0.9.1"
kover = "0.8.3"
sonarqube = "6.0.1.5171"
spotless = "6.21.0"
nexusPlugin = "1.3.0"
Expand Down Expand Up @@ -65,7 +65,7 @@ androidxUiAutomator = "2.4.0-alpha01"
androidxContraintLayout = "2.1.4"
androidxEspresso = "3.5.1"
androidxMedia = "1.7.0"
paparazzi = "1.3.1"
paparazzi = "1.3.4"
robolectric = "4.11.1"
junit = "4.13.2"
truth = "1.1.3"
Expand Down
140 changes: 111 additions & 29 deletions scripts/coverage.gradle
Original file line number Diff line number Diff line change
@@ -1,41 +1,123 @@
if (!rootProject.ext.sonar.ignoreModules.contains(name)) {
apply plugin: "org.jetbrains.kotlinx.kover"
apply plugin: "org.sonarqube"

if (hasProperty('android')) {
android {
buildTypes {
debug {
testCoverageEnabled = true
enableUnitTestCoverage = true
enableAndroidTestCoverage true
}
}
}
}
ext.coverageModules = [
'stream-video-android-core',
'stream-video-android-ui-core',
'stream-video-android-ui-xml',
'stream-video-android-ui-compose',
]

ext.koverClassExcludes = [
'*R',
'*R$*',
'*BuildConfig',
'*Manifest*',
'*Composable*',
"io.getstream.android.video.generated.*",
"io.getstream.video.android.core.model.*"
]
ext.koverAnnotationExcludes = [
'androidx.compose.ui.tooling.preview.Preview'
]

kover {
def configureKoverReports(project) {
project.kover {
reports {
verify {
warningInsteadOfFailure = true
}
}
currentProject {
instrumentation {
excludedClasses.addAll(
"io.getstream.android.video.generated.*",
"io.getstream.video.android.core.model.*"
)
filters {
excludes {
classes(rootProject.ext.koverClassExcludes as String[])
annotatedBy(rootProject.ext.koverAnnotationExcludes as String[])
}
}
}
}
}

def coverageModulesWithTests = subprojects.findAll {
rootProject.ext.coverageModules.contains(it.name) && file("${it.projectDir}/src/test").exists()
}
println("Setting up coverage for:\n${coverageModulesWithTests.join("\n")}")

// Configure code coverage for modules with tests
subprojects {
def isCoverageModule = coverageModulesWithTests.collect {it.name}.contains(name)

sonar {
skipProject = !isCoverageModule
}

if (isCoverageModule) {
apply plugin: "org.jetbrains.kotlinx.kover"

afterEvaluate {
def isAndroidModule = plugins.hasPlugin("com.android.library") || plugins.hasPlugin("com.android.application")
def hasPaparazziPlugin = plugins.hasPlugin("app.cash.paparazzi")

if (isAndroidModule) {
android {
buildTypes {
debug {
testCoverageEnabled = true
enableUnitTestCoverage = true
}
}
}
}

// Determine the appropriate test task name based on module type and plugins
def testTaskName = isAndroidModule
? (hasPaparazziPlugin ? "verifyPaparazziDebug" : "testDebugUnitTest")
: "test"

sonarqube {
properties {
property "sonar.junit.reportPaths", "${buildDir}/test-results/testDebugUnitTest"
property "sonar.coverage.jacoco.xmlReportPaths", "${buildDir}/reports/kover/reportDebug.xml"
property "sonar.sources", "src/main/kotlin"
property "sonar.coverage.exclusions", "**/generated/**,**/io/getstream/video/android/core/model/**"
tasks.register("testCoverage") {
group = "verification"
description = "Run module-specific tests"
dependsOn(testTaskName)
}

kover {
currentProject {
// Variant configuration for aggregated coverage
createVariant("coverage") {
if (isAndroidModule) {
add(["debug"], true)
} else {
add(["jvm"], true)
}
}
}
configureKoverReports(project)
}
}
}
}

// Configure root project to aggregate coverage reports
apply plugin: "org.jetbrains.kotlinx.kover"

// Specify the projects that should be included in the aggregate coverage report
coverageModulesWithTests.each { project -> dependencies { kover(project) } }

// Aggregate all submodules' testCoverage + merged reports
tasks.register("testCoverage") {
group = "verification"
description = "Run all tests in all modules and generate merged coverage report"

dependsOn(subprojects.collect { it.tasks.matching { it.name == "testCoverage" } })
dependsOn("koverXmlReportCoverage", "koverHtmlReportCoverage")
}

kover {
currentProject {
// Variant configuration for aggregated coverage (needs to be defined in the root project too)
createVariant("coverage") {}
}
configureKoverReports(project)
}

sonar {
properties {
property "sonar.coverage.jacoco.xmlReportPaths", "${buildDir}/reports/kover/reportCoverage.xml"
}
}
40 changes: 12 additions & 28 deletions scripts/sonar.gradle
Original file line number Diff line number Diff line change
@@ -1,44 +1,28 @@
apply plugin: "org.sonarqube"

ext.sonar = [
ignoreModules : [
'stream-video-android-bom',
'stream-video-android-previewdata',
'demo-app',
'benchmark',
'tutorials',
'tutorial-audio',
'tutorial-video',
'tutorial-ringing',
'tutorial-livestream',
'metrics'
],
excludeFilter : [
'**/test/**',
'**/androidTest/**',
'**/R.class',
'**/R2.class',
'**/R$*.class',
'**/BuildConfig.*',
'**/Manifest*.*',
'**/*Test*.*'
'**/test/**',
'**/androidTest/**',
'**/R.class',
'**/R2.class',
'**/R$*.class',
'**/BuildConfig.*',
'**/Manifest*.*',
'**/*.mp3',
'**/*.webp',
"**/generated/**",
"**/io/getstream/video/android/core/model/**"
]
]

ext.sonar.ignoreModules.each {
ext.sonar.excludeFilter << "**/${it}/**"
}

sonarqube {
properties {
property("sonar.host.url", "https://sonarcloud.io")
property("sonar.token", "${System.getenv("SONAR_TOKEN")}")
property("sonar.organization", "getstream")
property("sonar.projectKey", "GetStream_stream-video-android")
property("sonar.projectName", "stream-video-android")
property "sonar.java.coveragePlugin", "jacoco"
property "sonar.sourceEncoding", "UTF-8"
property "sonar.java.binaries", "${rootDir}/**/build/tmp/kotlin-classes/debug"
property "sonar.coverage.exclusions", rootProject.ext.sonar.excludeFilter
property "sonar.exclusions", rootProject.ext.sonar.excludeFilter.join(",")
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import io.getstream.video.android.compose.base.BaseComposeTest
import io.getstream.video.android.compose.ui.components.call.activecall.AudioCallContent
import io.getstream.video.android.compose.ui.components.call.activecall.AudioOnlyCallContent
import io.getstream.video.android.mock.previewCall
import org.junit.Ignore
import org.junit.Rule
import org.junit.Test

Expand Down Expand Up @@ -54,6 +55,7 @@ internal class AudioCallContentTest : BaseComposeTest() {
}
}

@Ignore("https://linear.app/stream/issue/AND-786/fix-video-snapshot-tests")
@Test
fun `snapshot AudioOnlyCallContent in default state`() {
snapshot {
Expand All @@ -65,6 +67,7 @@ internal class AudioCallContentTest : BaseComposeTest() {
}
}

@Ignore("https://linear.app/stream/issue/AND-786/fix-video-snapshot-tests")
@Test
fun `snapshot AudioOnlyCallContent without header`() {
snapshot {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,20 +20,24 @@ import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.ui.Modifier
import app.cash.paparazzi.DeviceConfig
import app.cash.paparazzi.Paparazzi
import com.android.resources.ScreenOrientation
import io.getstream.video.android.compose.base.BaseComposeTest
import io.getstream.video.android.compose.ui.components.audio.AudioAppBar
import io.getstream.video.android.compose.ui.components.audio.AudioControlActions
import io.getstream.video.android.compose.ui.components.audio.AudioParticipantsGrid
import io.getstream.video.android.compose.ui.components.audio.AudioRoomContent
import io.getstream.video.android.mock.previewCall
import io.getstream.video.android.mock.previewParticipantsList
import org.junit.Ignore
import org.junit.Rule
import org.junit.Test

internal class AudioRoomTest : BaseComposeTest() {

@get:Rule
val paparazzi = Paparazzi(deviceConfig = DeviceConfig.NEXUS_5_LAND)
val paparazzi = Paparazzi(
deviceConfig = DeviceConfig.PIXEL_2.copy(orientation = ScreenOrientation.LANDSCAPE),
)

override fun basePaparazzi(): Paparazzi = paparazzi

Expand Down Expand Up @@ -61,6 +65,7 @@ internal class AudioRoomTest : BaseComposeTest() {
}
}

@Ignore("https://linear.app/stream/issue/AND-786/fix-video-snapshot-tests")
@Test
fun `snapshot AudioRoom composable`() {
snapshot {
Expand All @@ -71,6 +76,7 @@ internal class AudioRoomTest : BaseComposeTest() {
}
}

@Ignore("https://linear.app/stream/issue/AND-786/fix-video-snapshot-tests")
@Test
fun `snapshot AudioRoom DarkMode composable`() {
snapshot(isInDarkMode = true) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ package io.getstream.video.android.compose
import androidx.compose.foundation.layout.Box
import app.cash.paparazzi.DeviceConfig
import app.cash.paparazzi.Paparazzi
import com.android.resources.ScreenOrientation
import io.getstream.video.android.compose.base.BaseComposeTest
import io.getstream.video.android.compose.ui.components.livestream.LivestreamPlayer
import io.getstream.video.android.compose.ui.components.livestream.LivestreamPlayerOverlay
Expand All @@ -29,7 +30,9 @@ import org.junit.Test
internal class LivestreamTest : BaseComposeTest() {

@get:Rule
val paparazzi = Paparazzi(deviceConfig = DeviceConfig.NEXUS_5_LAND)
val paparazzi = Paparazzi(
deviceConfig = DeviceConfig.PIXEL_2.copy(orientation = ScreenOrientation.LANDSCAPE),
)

override fun basePaparazzi(): Paparazzi = paparazzi

Expand Down
Loading