@ -12,8 +12,11 @@ import io.mockk.impl.annotations.MockK
import io.mockk.mockk
import io.mockk.mockk
import io.mockk.spyk
import io.mockk.spyk
import io.mockk.verify
import io.mockk.verify
import kotlinx.coroutines.test.advanceUntilIdle
import mozilla.components.support.ktx.kotlin.crossProduct
import mozilla.components.support.ktx.kotlin.crossProduct
import mozilla.components.support.test.robolectric.testContext
import mozilla.components.support.test.robolectric.testContext
import mozilla.components.support.test.rule.MainCoroutineRule
import mozilla.components.support.test.rule.runTestOnMain
import mozilla.telemetry.glean.testing.GleanTestRule
import mozilla.telemetry.glean.testing.GleanTestRule
import org.junit.Assert.assertEquals
import org.junit.Assert.assertEquals
import org.junit.Assert.assertNull
import org.junit.Assert.assertNull
@ -38,6 +41,9 @@ private val activityClass = HomeActivity::class.java
@RunWith ( AndroidJUnit4 :: class )
@RunWith ( AndroidJUnit4 :: class )
class StartupTypeTelemetryTest {
class StartupTypeTelemetryTest {
@get : Rule
val coroutinesTestRule = MainCoroutineRule ( )
@get : Rule
@get : Rule
val gleanTestRule = GleanTestRule ( testContext )
val gleanTestRule = GleanTestRule ( testContext )
@ -62,7 +68,7 @@ class StartupTypeTelemetryTest {
}
}
@Test
@Test
fun `GIVEN all possible path and state combinations WHEN record telemetry THEN the labels are incremented the appropriate number of times` ( ) {
fun `GIVEN all possible path and state combinations WHEN record telemetry THEN the labels are incremented the appropriate number of times` ( ) = runTestOnMain {
val allPossibleInputArgs = StartupState . values ( ) . toList ( ) . crossProduct (
val allPossibleInputArgs = StartupState . values ( ) . toList ( ) . crossProduct (
StartupPath . values ( ) . toList ( )
StartupPath . values ( ) . toList ( )
) { state , path ->
) { state , path ->
@ -73,7 +79,8 @@ class StartupTypeTelemetryTest {
every { stateProvider . getStartupStateForStartedActivity ( activityClass ) } returns state
every { stateProvider . getStartupStateForStartedActivity ( activityClass ) } returns state
every { pathProvider . startupPathForActivity } returns path
every { pathProvider . startupPathForActivity } returns path
telemetry . record ( )
telemetry . record ( coroutinesTestRule . testDispatcher )
advanceUntilIdle ( )
}
}
validTelemetryLabels . forEach { label ->
validTelemetryLabels . forEach { label ->
@ -87,11 +94,12 @@ class StartupTypeTelemetryTest {
}
}
@Test
@Test
fun `WHEN record is called THEN telemetry is recorded with the appropriate label` ( ) {
fun `WHEN record is called THEN telemetry is recorded with the appropriate label` ( ) = runTestOnMain {
every { stateProvider . getStartupStateForStartedActivity ( activityClass ) } returns StartupState . COLD
every { stateProvider . getStartupStateForStartedActivity ( activityClass ) } returns StartupState . COLD
every { pathProvider . startupPathForActivity } returns StartupPath . MAIN
every { pathProvider . startupPathForActivity } returns StartupPath . MAIN
telemetry . record ( )
telemetry . record ( coroutinesTestRule . testDispatcher )
advanceUntilIdle ( )
assertEquals ( 1 , PerfStartup . startupType [ " cold_main " ] . testGetValue ( ) )
assertEquals ( 1 , PerfStartup . startupType [ " cold_main " ] . testGetValue ( ) )
}
}
@ -99,33 +107,33 @@ class StartupTypeTelemetryTest {
@Test
@Test
fun `GIVEN the activity is launched WHEN onResume is called THEN we record the telemetry` ( ) {
fun `GIVEN the activity is launched WHEN onResume is called THEN we record the telemetry` ( ) {
launchApp ( )
launchApp ( )
verify ( exactly = 1 ) { telemetry . record ( ) }
verify ( exactly = 1 ) { telemetry . record ( any ( ) ) }
}
}
@Test
@Test
fun `GIVEN the activity is launched WHEN the activity is paused and resumed THEN record is not called` ( ) {
fun `GIVEN the activity is launched WHEN the activity is paused and resumed THEN record is not called` ( ) {
// This part of the test duplicates another test but it's needed to initialize the state of this test.
// This part of the test duplicates another test but it's needed to initialize the state of this test.
launchApp ( )
launchApp ( )
verify ( exactly = 1 ) { telemetry . record ( ) }
verify ( exactly = 1 ) { telemetry . record ( any ( ) ) }
callbacks . onPause ( mockk ( ) )
callbacks . onPause ( mockk ( ) )
callbacks . onResume ( mockk ( ) )
callbacks . onResume ( mockk ( ) )
verify ( exactly = 1 ) { telemetry . record ( ) } // i.e. this shouldn't be called again.
verify ( exactly = 1 ) { telemetry . record ( any ( ) ) } // i.e. this shouldn't be called again.
}
}
@Test
@Test
fun `GIVEN the activity is launched WHEN the activity is stopped and resumed THEN record is called again` ( ) {
fun `GIVEN the activity is launched WHEN the activity is stopped and resumed THEN record is called again` ( ) {
// This part of the test duplicates another test but it's needed to initialize the state of this test.
// This part of the test duplicates another test but it's needed to initialize the state of this test.
launchApp ( )
launchApp ( )
verify ( exactly = 1 ) { telemetry . record ( ) }
verify ( exactly = 1 ) { telemetry . record ( any ( ) ) }
callbacks . onPause ( mockk ( ) )
callbacks . onPause ( mockk ( ) )
callbacks . onStop ( mockk ( ) )
callbacks . onStop ( mockk ( ) )
callbacks . onStart ( mockk ( ) )
callbacks . onStart ( mockk ( ) )
callbacks . onResume ( mockk ( ) )
callbacks . onResume ( mockk ( ) )
verify ( exactly = 2 ) { telemetry . record ( ) } // i.e. this should be called again.
verify ( exactly = 2 ) { telemetry . record ( any ( ) ) } // i.e. this should be called again.
}
}
private fun launchApp ( ) {
private fun launchApp ( ) {