I recently migrated my Android pet project from View to Compose UI and at the begining I was excited about all the @Compose
and @Preview
functions but righ away noticed a segnificant drop in the repo's Code Coverage.
I wrote some tests to compensate for the loss, but later discovered that those tests were not calculated as coverage—probably because of all the lambdas in Compose functions!
In search for any potential answers, I just found this thread which didn't help that much:
https://github.com/jacoco/jacoco/issues/1208
Here is my Android app repo link:
https://github.com/mohsenoid/Rick-and-Morty
and here is the Code Coverage report:
https://app.codecov.io/gh/mohsenoid/Rick-and-Morty
if you have a potential solution or would like to check:
===== An example for the question improvements =====
I have this Composable UI function:
@VisibleForTesting
@Composable
fun EpisodeItem(
episode: Episode,
onEpisodeClicked: (Episode) -> Unit = {},
) {
Card(
modifier =
Modifier
.fillMaxWidth()
.clickable { onEpisodeClicked(episode) },
) {
Row(modifier = Modifier.height(80.dp)) {
Box(
modifier =
Modifier
.fillMaxHeight()
.width(100.dp)
.background(MaterialTheme.colorScheme.inverseOnSurface),
contentAlignment = Alignment.Center,
) {
Text(
text = episode.episode,
style = MaterialTheme.typography.titleLarge,
)
}
Column(
modifier =
Modifier
.fillMaxHeight()
.weight(1f)
.padding(8.dp),
) {
Text(
text = episode.airDate,
modifier = Modifier.fillMaxWidth(),
maxLines = 1,
overflow = TextOverflow.Ellipsis,
style = MaterialTheme.typography.labelMedium,
)
Spacer(modifier = Modifier.height(4.dp))
Text(
text = episode.name,
modifier =
Modifier
.fillMaxWidth(),
maxLines = 2,
overflow = TextOverflow.Ellipsis,
style = MaterialTheme.typography.titleMedium,
)
}
}
}
}
and this test for it:
@RunWith(RobolectricTestRunner::class)
class EpisodeScreenTest {
@get:Rule
val rule = createComposeRule()
@Test
fun `When content is EpisodeItem, Then it should display EpisodeItem name, airDate and episode`() {
// GIVEN
// WHEN
rule.setContent {
EpisodeItem(
episode =
createEpisode(
name = TEST_EPISODE_NAME,
airDate = TEST_EPISODE_AIR_DATE,
episode = TEST_EPISODE_EPISODE,
),
)
}
// THEN
rule.onNodeWithText(TEST_EPISODE_NAME).assertExists()
rule.onNodeWithText(TEST_EPISODE_AIR_DATE).assertExists()
rule.onNodeWithText(TEST_EPISODE_EPISODE).assertExists()
}
companion object {
private const val TEST_EPISODE_NAME = "Pilot"
private const val TEST_EPISODE_AIR_DATE = "December 2, 2013"
private const val TEST_EPISODE_EPISODE = "S01E01"
}
}
The test passes but doesn't affect the code coverage.
FYI, I confirmed that it is not the Robolectric
effect.