From c89c94eda5adcd79033f70900ca51ac8ae224587 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joaquim=20St=C3=A4hli?= Date: Tue, 30 Jan 2024 17:38:35 +0100 Subject: [PATCH 1/3] Make ComScoreTracker testable --- .../core/business/tracker/comscore/ComScoreTracker.kt | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/pillarbox-core-business/src/main/java/ch/srgssr/pillarbox/core/business/tracker/comscore/ComScoreTracker.kt b/pillarbox-core-business/src/main/java/ch/srgssr/pillarbox/core/business/tracker/comscore/ComScoreTracker.kt index 4da42c92f..7420fb9af 100644 --- a/pillarbox-core-business/src/main/java/ch/srgssr/pillarbox/core/business/tracker/comscore/ComScoreTracker.kt +++ b/pillarbox-core-business/src/main/java/ch/srgssr/pillarbox/core/business/tracker/comscore/ComScoreTracker.kt @@ -20,8 +20,12 @@ import com.comscore.streaming.StreamingAnalytics /** * ComScore tracker + * + * @param streamingAnalytics the [StreamingAnalytics] to use with this tracker. */ -class ComScoreTracker : MediaItemTracker { +class ComScoreTracker internal constructor( + private val streamingAnalytics: StreamingAnalytics = StreamingAnalytics() +) : MediaItemTracker { /** * Data for ComScore * @@ -30,7 +34,6 @@ class ComScoreTracker : MediaItemTracker { data class Data(val assets: Map) private val component = PlayerComponent() - private val streamingAnalytics = StreamingAnalytics() private val window = Window() private lateinit var latestData: Data From 8884a3ce2ab7e3e86c81de6f54d82e05d5da809e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joaquim=20St=C3=A4hli?= Date: Tue, 30 Jan 2024 17:38:53 +0100 Subject: [PATCH 2/3] Add ComScoreTrackerTest --- .../tracker/comscore/ComscoreTrackerTest.kt | 190 ++++++++++++++++++ 1 file changed, 190 insertions(+) create mode 100644 pillarbox-core-business/src/test/java/ch/srgssr/pillarbox/core/business/tracker/comscore/ComscoreTrackerTest.kt diff --git a/pillarbox-core-business/src/test/java/ch/srgssr/pillarbox/core/business/tracker/comscore/ComscoreTrackerTest.kt b/pillarbox-core-business/src/test/java/ch/srgssr/pillarbox/core/business/tracker/comscore/ComscoreTrackerTest.kt new file mode 100644 index 000000000..fbfda3a58 --- /dev/null +++ b/pillarbox-core-business/src/test/java/ch/srgssr/pillarbox/core/business/tracker/comscore/ComscoreTrackerTest.kt @@ -0,0 +1,190 @@ +/* + * Copyright (c) SRG SSR. All rights reserved. + * License information is available from the LICENSE file. + */ +package ch.srgssr.pillarbox.core.business.tracker.comscore + +import androidx.media3.common.Player +import androidx.media3.common.util.Size +import androidx.media3.exoplayer.ExoPlayer +import androidx.test.ext.junit.runners.AndroidJUnit4 +import ch.srgssr.pillarbox.analytics.BuildConfig +import ch.srgssr.pillarbox.player.tracker.MediaItemTracker +import com.comscore.Analytics +import com.comscore.streaming.StreamingAnalytics +import io.mockk.confirmVerified +import io.mockk.every +import io.mockk.mockk +import io.mockk.mockkStatic +import io.mockk.unmockkAll +import io.mockk.verify +import org.junit.runner.RunWith +import kotlin.test.AfterTest +import kotlin.test.BeforeTest +import kotlin.test.Test + +@RunWith(AndroidJUnit4::class) +class ComscoreTrackerTest { + + @BeforeTest + fun setup() { + mockkStatic(Analytics::class) + } + + @AfterTest + fun tearDown() { + unmockkAll() + } + + @Test + fun `initialisation setMediaPlayerName and MediaPlayerVersion`() { + val streamingAnalytics: StreamingAnalytics = mockk(relaxed = true) + ComScoreTracker(streamingAnalytics = streamingAnalytics) + verify(exactly = 1) { + streamingAnalytics.setMediaPlayerName("Pillarbox") + streamingAnalytics.setMediaPlayerVersion(BuildConfig.VERSION_NAME) + } + confirmVerified(streamingAnalytics) + } + + @Test(expected = IllegalArgumentException::class) + fun `start() require non null initial data`() { + val streamingAnalytics: StreamingAnalytics = mockk(relaxed = true) + val tracker = ComScoreTracker(streamingAnalytics = streamingAnalytics) + val player = mockk(relaxed = true) + tracker.start(player = player, null) + } + + @Test(expected = IllegalArgumentException::class) + fun `start() require an instance of ComScoreTracker#Data for initial data`() { + val streamingAnalytics: StreamingAnalytics = mockk(relaxed = true) + val tracker = ComScoreTracker(streamingAnalytics = streamingAnalytics) + val player = mockk(relaxed = true) + tracker.start(player = player, initialData = "data") + } + + @Test + fun `start() does not call notify play or buffer start when player can't play`() { + val streamingAnalytics: StreamingAnalytics = mockk(relaxed = true) + val tracker = ComScoreTracker(streamingAnalytics = streamingAnalytics) + val player = mockk(relaxed = true) + every { player.isPlaying } returns false + every { player.surfaceSize } returns Size(100, 200) + every { player.playbackState } returns Player.STATE_IDLE + val assets = mapOf("value1" to "key1") + tracker.start(player = player, initialData = ComScoreTracker.Data(assets = assets)) + + verify(exactly = 1) { + streamingAnalytics.setMetadata(any()) + streamingAnalytics.createPlaybackSession() + } + verify(exactly = 0) { + streamingAnalytics.notifyPlay() + streamingAnalytics.notifyBufferStart() + } + } + + @Test + fun `start() call notifyBufferStart`() { + val streamingAnalytics: StreamingAnalytics = mockk(relaxed = true) + val tracker = ComScoreTracker(streamingAnalytics = streamingAnalytics) + val player = mockk(relaxed = true) + every { player.isPlaying } returns false + every { player.surfaceSize } returns Size(130, 200) + every { player.playbackState } returns Player.STATE_BUFFERING + tracker.start(player = player, initialData = ComScoreTracker.Data(assets = mapOf("value1" to "key1"))) + + verify(exactly = 1) { + streamingAnalytics.notifyBufferStart() + } + } + + @Test + fun `start() call notifyPlay`() { + val streamingAnalytics: StreamingAnalytics = mockk(relaxed = true) + val tracker = ComScoreTracker(streamingAnalytics = streamingAnalytics) + val player = mockk(relaxed = true) + every { player.isPlaying } returns true + every { player.surfaceSize } returns Size(300, 200) + every { player.playbackState } returns Player.STATE_READY + tracker.start(player = player, initialData = ComScoreTracker.Data(assets = mapOf("value1" to "key1"))) + + verify(exactly = 1) { + streamingAnalytics.notifyPlay() + } + } + + @Test + fun `start() should not call notifyPlay when not connected to a surface`() { + val streamingAnalytics: StreamingAnalytics = mockk(relaxed = true) + val tracker = ComScoreTracker(streamingAnalytics = streamingAnalytics) + val player = mockk(relaxed = true) + every { player.isPlaying } returns true + every { player.surfaceSize } returns Size.ZERO + every { player.playbackState } returns Player.STATE_READY + tracker.start(player = player, initialData = ComScoreTracker.Data(assets = mapOf("value1" to "key1"))) + + verify(exactly = 0) { + streamingAnalytics.notifyPlay() + } + } + + @Test + fun `stop() should always notifyEnd`() { + val streamingAnalytics: StreamingAnalytics = mockk(relaxed = true) + val tracker = ComScoreTracker(streamingAnalytics = streamingAnalytics) + val player = mockk(relaxed = true) + every { player.isPlaying } returns true + every { player.surfaceSize } returns Size.ZERO + every { player.playbackState } returns Player.STATE_READY + tracker.stop(player = player, MediaItemTracker.StopReason.EoF, 500) + tracker.stop(player = player, MediaItemTracker.StopReason.Stop, 500) + + verify(exactly = 2) { + streamingAnalytics.notifyEnd() + } + } + + @Test(expected = IllegalArgumentException::class) + fun `update() require an instance of ComScoreTracker#Data`() { + val streamingAnalytics: StreamingAnalytics = mockk(relaxed = true) + val tracker = ComScoreTracker(streamingAnalytics = streamingAnalytics) + val player = mockk(relaxed = true) + every { player.isPlaying } returns true + every { player.surfaceSize } returns Size.ZERO + every { player.playbackState } returns Player.STATE_READY + tracker.update("data") + } + + @Test + fun `update() with a different data`() { + val streamingAnalytics: StreamingAnalytics = mockk(relaxed = true) + val tracker = ComScoreTracker(streamingAnalytics = streamingAnalytics) + val player = mockk(relaxed = true) + every { player.isPlaying } returns true + every { player.surfaceSize } returns Size.ZERO + every { player.playbackState } returns Player.STATE_READY + tracker.start(player, initialData = ComScoreTracker.Data(emptyMap())) + tracker.update(ComScoreTracker.Data(mapOf("key01" to "value01"))) + + verify(exactly = 2) { + streamingAnalytics.setMetadata(any()) + } + } + + @Test + fun `update() with a same data`() { + val streamingAnalytics: StreamingAnalytics = mockk(relaxed = true) + val tracker = ComScoreTracker(streamingAnalytics = streamingAnalytics) + val player = mockk(relaxed = true) + every { player.isPlaying } returns true + every { player.surfaceSize } returns Size.ZERO + every { player.playbackState } returns Player.STATE_READY + tracker.start(player, initialData = ComScoreTracker.Data(emptyMap())) + tracker.update(ComScoreTracker.Data(emptyMap())) + + verify(exactly = 1) { + streamingAnalytics.setMetadata(any()) + } + } +} From 10384e1637fe377fb767de07d4039356f533f916 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ga=C3=ABtan=20Muller?= Date: Thu, 1 Feb 2024 11:04:16 +0100 Subject: [PATCH 3/3] Fix class name --- .../comscore/{ComscoreTrackerTest.kt => ComScoreTrackerTest.kt} | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename pillarbox-core-business/src/test/java/ch/srgssr/pillarbox/core/business/tracker/comscore/{ComscoreTrackerTest.kt => ComScoreTrackerTest.kt} (99%) diff --git a/pillarbox-core-business/src/test/java/ch/srgssr/pillarbox/core/business/tracker/comscore/ComscoreTrackerTest.kt b/pillarbox-core-business/src/test/java/ch/srgssr/pillarbox/core/business/tracker/comscore/ComScoreTrackerTest.kt similarity index 99% rename from pillarbox-core-business/src/test/java/ch/srgssr/pillarbox/core/business/tracker/comscore/ComscoreTrackerTest.kt rename to pillarbox-core-business/src/test/java/ch/srgssr/pillarbox/core/business/tracker/comscore/ComScoreTrackerTest.kt index fbfda3a58..64737b547 100644 --- a/pillarbox-core-business/src/test/java/ch/srgssr/pillarbox/core/business/tracker/comscore/ComscoreTrackerTest.kt +++ b/pillarbox-core-business/src/test/java/ch/srgssr/pillarbox/core/business/tracker/comscore/ComScoreTrackerTest.kt @@ -24,7 +24,7 @@ import kotlin.test.BeforeTest import kotlin.test.Test @RunWith(AndroidJUnit4::class) -class ComscoreTrackerTest { +class ComScoreTrackerTest { @BeforeTest fun setup() {