Skip to content

Commit 1151982

Browse files
committed
test(android): give every repository test its own settings stores
SyncIntegrationTest failed because it read the app's real settings on the device. Four more instrumented tests built SpamRepository the same way: the SMS and spam pipeline tests reset a few settings and inherited the rest from whatever the installed app had stored (contacts-only mode, for one, would flip their verdicts), and the backup and hot-list tests wrote test state into the installed app. TestSettingsStores gains a repository() factory and all five use it. CallScreeningDeadlineTest keeps the real stores on purpose, since the cold path through them is what it times, and now says so.
1 parent 5557a08 commit 1151982

8 files changed

Lines changed: 46 additions & 24 deletions

File tree

‎CHANGELOG.md‎

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -369,11 +369,12 @@ The rest of this section takes effect when the report Worker is next deployed.
369369
the result doesn't match what the app expects or a table loses rows. The
370370
migration test that would have caught the August database lockout ran only
371371
on an emulator, and nothing ran it.
372-
- The on-device sync tests keep their settings to themselves. They used the
373-
app's own saved settings, so once the app had loaded its built-in database
374-
on the test phone, every older test feed was refused as a rollback and the
375-
tests failed. The dashboard tests now check the labels and buttons from the
376-
August redesign.
372+
- The on-device tests keep their settings to themselves. They used the app's
373+
own saved settings, so once the app had loaded its built-in database on the
374+
test phone, every older test feed was refused as a rollback and the sync
375+
tests failed, and the backup and screening tests wrote test settings into
376+
the installed app. The dashboard tests now check the labels and buttons from
377+
the August redesign.
377378
- The on-device accessibility checks draw each screen in the app's theme on
378379
its own background. They measured colors against the bare white test window
379380
instead, which failed 20 screens for colors nobody sees and hid the real

‎app/src/androidTest/java/com/sysadmindoc/callshield/data/BackupRestoreIntegrationTest.kt‎

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,19 +45,22 @@ class BackupRestoreIntegrationTest {
4545
private lateinit var db: AppDatabase
4646
private lateinit var dao: SpamDao
4747
private lateinit var repo: SpamRepository
48+
private lateinit var stores: TestSettingsStores
4849

4950
@Before
5051
fun setUp() {
5152
context = ApplicationProvider.getApplicationContext()
5253
val builder = Room.inMemoryDatabaseBuilder(context, AppDatabase::class.java)
5354
db = builder.allowMainThreadQueries().build()
5455
dao = db.spamDao()
55-
repo = SpamRepository(context, db)
56+
stores = TestSettingsStores(context)
57+
repo = stores.repository(context, db)
5658
}
5759

5860
@After
5961
fun tearDown() {
6062
db.close()
63+
stores.close()
6164
}
6265

6366
@Test

‎app/src/androidTest/java/com/sysadmindoc/callshield/data/SmsPipelineIntegrationTest.kt‎

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ class SmsPipelineIntegrationTest {
2222
private lateinit var db: AppDatabase
2323
private lateinit var dao: SpamDao
2424
private lateinit var repo: SpamRepository
25+
private lateinit var stores: TestSettingsStores
2526

2627
@Before
2728
fun setUp() =
@@ -33,13 +34,15 @@ class SmsPipelineIntegrationTest {
3334
.allowMainThreadQueries()
3435
.build()
3536
dao = db.spamDao()
36-
repo = SpamRepository(context, db)
37+
stores = TestSettingsStores(context)
38+
repo = stores.repository(context, db)
3739
resetHotPathSettings()
3840
}
3941

4042
@After
4143
fun tearDown() {
4244
db.close()
45+
stores.close()
4346
}
4447

4548
@Test

‎app/src/androidTest/java/com/sysadmindoc/callshield/data/SpamPipelineIntegrationTest.kt‎

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ class SpamPipelineIntegrationTest {
3030
private lateinit var db: AppDatabase
3131
private lateinit var dao: SpamDao
3232
private lateinit var repo: SpamRepository
33+
private lateinit var stores: TestSettingsStores
3334

3435
@Before
3536
fun setUp() =
@@ -41,13 +42,15 @@ class SpamPipelineIntegrationTest {
4142
.allowMainThreadQueries()
4243
.build()
4344
dao = db.spamDao()
44-
repo = SpamRepository(context, db)
45+
stores = TestSettingsStores(context)
46+
repo = stores.repository(context, db)
4547
resetHotPathSettings()
4648
}
4749

4850
@After
4951
fun tearDown() {
5052
db.close()
53+
stores.close()
5154
}
5255

5356
@Test
@@ -176,12 +179,7 @@ class SpamPipelineIntegrationTest {
176179
PhoneIdentityCanonicalizer("GB") { number, _ ->
177180
if (number == "02079460018") "+442079460018" else null
178181
}
179-
val regionalRepo =
180-
SpamRepository(
181-
context = context,
182-
database = db,
183-
phoneIdentityCanonicalizer = canonicalizer,
184-
)
182+
val regionalRepo = stores.repository(context, db, phoneIdentityCanonicalizer = canonicalizer)
185183
regionalRepo.blockNumber("020 7946 0018", type = "test")
186184

187185
val result = regionalRepo.isSpam("+44 20 7946 0018")

‎app/src/androidTest/java/com/sysadmindoc/callshield/data/SyncIntegrationTest.kt‎

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -49,14 +49,7 @@ class SyncIntegrationTest {
4949

5050
// The feed policy refuses a feed older than the last one accepted, which
5151
// the app's own settings remember on the device, so each test starts empty.
52-
private fun repository(remote: SpamDataSource) =
53-
SpamRepository(
54-
context = context,
55-
database = db,
56-
remote = remote,
57-
settingsDataStore = stores.settings,
58-
privateSettingsDataStore = stores.privateSettings,
59-
)
52+
private fun repository(remote: SpamDataSource) = stores.repository(context, db, remote)
6053

6154
@Test
6255
fun syncFromGitHubPopulatesInMemoryRoomDatabaseFromRemoteSnapshot() =

‎app/src/androidTest/java/com/sysadmindoc/callshield/data/TestSettingsStores.kt‎

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@ import android.content.Context
44
import androidx.datastore.core.DataStore
55
import androidx.datastore.preferences.core.PreferenceDataStoreFactory
66
import androidx.datastore.preferences.core.Preferences
7+
import com.sysadmindoc.callshield.data.local.AppDatabase
8+
import com.sysadmindoc.callshield.data.remote.GitHubDataSource
9+
import com.sysadmindoc.callshield.data.remote.SpamDataSource
710
import kotlinx.coroutines.CoroutineScope
811
import kotlinx.coroutines.Dispatchers
912
import kotlinx.coroutines.SupervisorJob
@@ -27,6 +30,21 @@ internal class TestSettingsStores(
2730
val settings: DataStore<Preferences> = store("settings")
2831
val privateSettings: DataStore<Preferences> = store("private")
2932

33+
/** A repository on [database] that keeps its settings in these stores. */
34+
fun repository(
35+
context: Context,
36+
database: AppDatabase,
37+
remote: SpamDataSource = GitHubDataSource(),
38+
phoneIdentityCanonicalizer: PhoneIdentityCanonicalizer = PhoneIdentityCanonicalizer.fromContext(context.applicationContext),
39+
) = SpamRepository(
40+
context = context,
41+
database = database,
42+
remote = remote,
43+
settingsDataStore = settings,
44+
privateSettingsDataStore = privateSettings,
45+
phoneIdentityCanonicalizer = phoneIdentityCanonicalizer,
46+
)
47+
3048
private fun store(name: String) =
3149
PreferenceDataStoreFactory.create(
3250
corruptionHandler = replaceCorruptPreferences(),

‎app/src/androidTest/java/com/sysadmindoc/callshield/service/CallScreeningDeadlineTest.kt‎

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,9 @@ class CallScreeningDeadlineTest {
3232
assertEquals(CallShieldScreeningService::class.java.name, component?.className)
3333

3434
// A new facade leaves checker/prefix/rule caches cold while using
35-
// the same Room/DataStore path as onScreenCall.
35+
// the same Room/DataStore path as onScreenCall. Unlike the other
36+
// repository tests it keeps the app's own stores on purpose: the
37+
// cold path through them is what this test times.
3638
val repository = SpamRepository(context)
3739
val checkSpam = CheckSpamUseCase(SpamRepositoryAdapter(repository))
3840
val number = "+12125550199"

‎app/src/androidTest/java/com/sysadmindoc/callshield/service/HotListSyncIntegrationTest.kt‎

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import androidx.test.ext.junit.runners.AndroidJUnit4
77
import com.sysadmindoc.callshield.data.SmsContentAnalyzer
88
import com.sysadmindoc.callshield.data.SpamHeuristics
99
import com.sysadmindoc.callshield.data.SpamRepository
10+
import com.sysadmindoc.callshield.data.TestSettingsStores
1011
import com.sysadmindoc.callshield.data.local.AppDatabase
1112
import com.sysadmindoc.callshield.data.model.HotNumber
1213
import com.sysadmindoc.callshield.data.model.SpamNumber
@@ -26,6 +27,7 @@ class HotListSyncIntegrationTest {
2627
private lateinit var context: Context
2728
private lateinit var db: AppDatabase
2829
private lateinit var repo: SpamRepository
30+
private lateinit var stores: TestSettingsStores
2931

3032
@Before
3133
fun setUp() {
@@ -35,7 +37,8 @@ class HotListSyncIntegrationTest {
3537
.inMemoryDatabaseBuilder(context, AppDatabase::class.java)
3638
.allowMainThreadQueries()
3739
.build()
38-
repo = SpamRepository(context, db)
40+
stores = TestSettingsStores(context)
41+
repo = stores.repository(context, db)
3942
SpamHeuristics.updateHotRanges(emptyList())
4043
SmsContentAnalyzer.updateSpamDomains(emptyList())
4144
}
@@ -45,6 +48,7 @@ class HotListSyncIntegrationTest {
4548
SpamHeuristics.updateHotRanges(emptyList())
4649
SmsContentAnalyzer.updateSpamDomains(emptyList())
4750
db.close()
51+
stores.close()
4852
}
4953

5054
@Test

0 commit comments

Comments
 (0)