-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Improved handling for test result flank failures (#46)
- Loading branch information
1 parent
baff38d
commit f7cccfb
Showing
24 changed files
with
500 additions
and
181 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
File renamed without changes.
7 changes: 7 additions & 0 deletions
7
core/src/main/kotlin/net/lachlanmckee/bitrise/core/CoroutinesExt.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
package net.lachlanmckee.bitrise.core | ||
|
||
import kotlinx.coroutines.Deferred | ||
|
||
suspend fun <T> Deferred<Result<T>>.awaitGetOrThrow(): T { | ||
return await().getOrThrow() | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
9 changes: 9 additions & 0 deletions
9
core/src/main/kotlin/net/lachlanmckee/bitrise/core/data/entity/BuildLogResponse.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
package net.lachlanmckee.bitrise.core.data.entity | ||
|
||
import com.google.gson.FieldNamingPolicy | ||
import gsonpath.annotation.AutoGsonAdapter | ||
|
||
@AutoGsonAdapter(fieldNamingPolicy = [FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES]) | ||
data class BuildLogResponse( | ||
val expiringRawLogUrl: String | ||
) |
59 changes: 38 additions & 21 deletions
59
...s/src/main/kotlin/net/lachlanmckee/bitrise/results/domain/entity/TestResultDetailModel.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,27 +1,44 @@ | ||
package net.lachlanmckee.bitrise.results.domain.entity | ||
|
||
internal data class TestResultDetailModel( | ||
val buildSlug: String, | ||
val bitriseUrl: String, | ||
val cost: String, | ||
val testSuiteModelList: List<TestSuiteModel> | ||
) | ||
internal sealed class TestResultDetailModel { | ||
abstract val buildSlug: String | ||
abstract val bitriseUrl: String | ||
abstract val firebaseUrl: String | ||
abstract val totalFailures: Int | ||
|
||
internal data class TestSuiteModel( | ||
val name: String, | ||
val totalTests: Int, | ||
val successfulTestCount: Int, | ||
val time: String, | ||
val resultType: TestResultType, | ||
val testCases: List<TestModel> | ||
) | ||
internal data class WithResults( | ||
override val buildSlug: String, | ||
override val bitriseUrl: String, | ||
override val firebaseUrl: String, | ||
override val totalFailures: Int, | ||
val cost: String?, | ||
val testSuiteModelList: List<TestSuiteModel> | ||
) : TestResultDetailModel() { | ||
|
||
internal data class TestModel( | ||
val path: String, | ||
val webLink: String?, | ||
val time: String | ||
) | ||
internal data class TestSuiteModel( | ||
val name: String, | ||
val totalTests: Int, | ||
val time: String, | ||
val resultType: TestResultType, | ||
val testCases: List<TestModel> | ||
) | ||
|
||
internal enum class TestResultType { | ||
FAILURE, SKIPPED, SUCCESS | ||
internal data class TestModel( | ||
val path: String, | ||
val webLink: String?, | ||
val time: String | ||
) | ||
|
||
internal enum class TestResultType { | ||
FAILURE, SKIPPED, SUCCESS | ||
} | ||
} | ||
|
||
internal data class NoResults( | ||
override val buildSlug: String, | ||
override val bitriseUrl: String, | ||
override val firebaseUrl: String | ||
) : TestResultDetailModel() { | ||
override val totalFailures: Int = 0 | ||
} | ||
} |
97 changes: 76 additions & 21 deletions
97
...rc/main/kotlin/net/lachlanmckee/bitrise/results/domain/interactor/TestResultInteractor.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,36 +1,91 @@ | ||
package net.lachlanmckee.bitrise.results.domain.interactor | ||
|
||
import kotlinx.coroutines.* | ||
import net.lachlanmckee.bitrise.core.awaitGetOrThrow | ||
import net.lachlanmckee.bitrise.core.data.datasource.remote.BitriseDataSource | ||
import net.lachlanmckee.bitrise.results.domain.entity.TestResultDetailModel | ||
import net.lachlanmckee.bitrise.results.domain.entity.TestResultDetailModel.WithResults.TestResultType | ||
import net.lachlanmckee.bitrise.results.domain.entity.TestResultDetailModel.WithResults.TestSuiteModel | ||
import net.lachlanmckee.bitrise.results.domain.mapper.FirebaseUrlMapper | ||
import net.lachlanmckee.bitrise.results.domain.mapper.TestSuiteModelMapper | ||
import javax.inject.Inject | ||
|
||
internal class TestResultInteractor @Inject constructor( | ||
private val bitriseDataSource: BitriseDataSource, | ||
private val testSuiteModelMapper: TestSuiteModelMapper | ||
private val testSuiteModelMapper: TestSuiteModelMapper, | ||
private val firebaseUrlMapper: FirebaseUrlMapper | ||
) { | ||
suspend fun execute(buildSlug: String): Result<TestResultDetailModel> { | ||
return bitriseDataSource | ||
.getArtifactDetails(buildSlug) | ||
.mapCatching { artifactDetails -> | ||
println(artifactDetails) | ||
|
||
if (artifactDetails.data.isEmpty()) { | ||
throw IllegalStateException("No artifacts found. Perhaps the tests did not run?") | ||
} | ||
suspend fun execute(buildSlug: String): Result<TestResultDetailModel> = kotlin.runCatching { | ||
createTestResultModel(buildSlug) | ||
} | ||
|
||
TestResultDetailModel( | ||
buildSlug = buildSlug, | ||
bitriseUrl = "https://app.bitrise.io/build/$buildSlug", | ||
cost = bitriseDataSource | ||
.getArtifactText(artifactDetails, buildSlug, "CostReport.txt") | ||
.getOrThrow(), | ||
private suspend fun createTestResultModel( | ||
buildSlug: String | ||
): TestResultDetailModel { | ||
val costResponse = getCostAsync(buildSlug) | ||
val testSuiteModelListResponse = getTestSuiteModelListAsync(buildSlug) | ||
val firebaseUrlResponse = getFirebaseUrlAsync(buildSlug) | ||
|
||
val costResult = costResponse.await() | ||
val testSuiteModelListResult = testSuiteModelListResponse.await() | ||
val firebaseUrl = firebaseUrlResponse.awaitGetOrThrow() | ||
val bitriseUrl = "https://app.bitrise.io/build/$buildSlug" | ||
|
||
return if (testSuiteModelListResult.isSuccess) { | ||
val testSuiteModelList = testSuiteModelListResult.getOrThrow() | ||
|
||
TestResultDetailModel.WithResults( | ||
buildSlug = buildSlug, | ||
bitriseUrl = bitriseUrl, | ||
firebaseUrl = firebaseUrl, | ||
totalFailures = testSuiteModelList.sumBy { suiteModel -> | ||
if (suiteModel.resultType == TestResultType.FAILURE) { | ||
suiteModel.totalTests | ||
} else { | ||
0 | ||
} | ||
}, | ||
cost = costResult.getOrNull(), | ||
testSuiteModelList = testSuiteModelList | ||
) | ||
} else { | ||
TestResultDetailModel.NoResults( | ||
buildSlug = buildSlug, | ||
bitriseUrl = bitriseUrl, | ||
firebaseUrl = firebaseUrl | ||
) | ||
} | ||
} | ||
|
||
testSuiteModelList = bitriseDataSource | ||
.getTestResults(buildSlug) | ||
private fun getCostAsync( | ||
buildSlug: String | ||
): Deferred<Result<String>> { | ||
return GlobalScope.async { | ||
bitriseDataSource | ||
.getArtifactDetails(buildSlug) | ||
.mapCatching { artifactDetails -> | ||
bitriseDataSource | ||
.getArtifactText(artifactDetails, buildSlug, "CostReport.txt") | ||
.getOrThrow() | ||
.let(testSuiteModelMapper::mapToTestSuiteModelList) | ||
) | ||
} | ||
} | ||
} | ||
} | ||
|
||
private fun getTestSuiteModelListAsync( | ||
buildSlug: String | ||
): Deferred<Result<List<TestSuiteModel>>> { | ||
return GlobalScope.async { | ||
bitriseDataSource.getTestResults(buildSlug) | ||
.mapCatching(testSuiteModelMapper::mapToTestSuiteModelList) | ||
} | ||
} | ||
|
||
private fun getFirebaseUrlAsync( | ||
buildSlug: String | ||
): Deferred<Result<String>> { | ||
return GlobalScope.async { | ||
bitriseDataSource.getBuildLog(buildSlug) | ||
.mapCatching(firebaseUrlMapper::mapBuildLogToFirebaseUrl) | ||
} | ||
} | ||
} |
16 changes: 16 additions & 0 deletions
16
results/src/main/kotlin/net/lachlanmckee/bitrise/results/domain/mapper/FirebaseUrlMapper.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
package net.lachlanmckee.bitrise.results.domain.mapper | ||
|
||
import javax.inject.Inject | ||
|
||
internal class FirebaseUrlMapper @Inject constructor() { | ||
fun mapBuildLogToFirebaseUrl(buildLog: String): String { | ||
return buildLog | ||
.lineSequence() | ||
.first { it.contains(FIREBASE_CONSOLE_PREFIX) } | ||
.let { FIREBASE_CONSOLE_PREFIX + it.substringAfter(FIREBASE_CONSOLE_PREFIX) } | ||
} | ||
|
||
private companion object { | ||
private const val FIREBASE_CONSOLE_PREFIX = "https://console.firebase.google.com/project/" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
14 changes: 14 additions & 0 deletions
14
results/src/main/kotlin/net/lachlanmckee/bitrise/results/presentation/HtmlElements.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
package net.lachlanmckee.bitrise.results.presentation | ||
|
||
import kotlinx.html.BODY | ||
import kotlinx.html.a | ||
import kotlinx.html.classes | ||
|
||
fun BODY.button(label: String, url: String) { | ||
a(href = url) { | ||
classes = setOf("mdl-button mdl-button--colored", "mdl-js-button", "mdl-js-ripple-effect", "gray-button") | ||
target = "_blank" | ||
text(label) | ||
} | ||
text(" ") | ||
} |
Oops, something went wrong.