mirror of
https://github.com/atsunatsu/Look4Sat.git
synced 2026-10-08 13:37:25 +00:00
test(mutual): 钉死 fixture 时间基准,消除时段性 flaky
fixture 用 2024-03-09 固定 ISS TLE + System.currentTimeMillis() 起点;SGP4 带阻力衰减 942 天后高度仅 ≈262km,12h 窗口内可能无广州过境 → 3 条依赖过境窗的用例时段性失败(Gradle 缓存 FROM-CACHE 会掩盖上一次的真跑)。 - TestOrbits.FIXTURE_BASE(2024-03-10T00:00Z,历元后约 18h)取代默认 System.currentTimeMillis() - MutualViewModel 墙钟可注入:nowMillis: () -> Long = System::currentTimeMillis(第 4 个默认参数,生产行为逐位不变;工厂具名构造零改动) - 断言里的 now 改用同一基准;prefill/scroll 测试不碰时间未动 修后::feature:mutual 28/28,全量 ./gradlew test 451/451。
This commit is contained in:
3 files changed
+19
-5
No files matched your search
+5
-2
@@ -82,7 +82,10 @@ class MutualViewModel(
|
||||
private val settingsRepo: ISettingsRepo,
|
||||
// Injected so unit tests can run the pass computation on a test dispatcher;
|
||||
// production callers keep the CPU-bound pool default.
|
||||
private val computeDispatcher: CoroutineDispatcher = Dispatchers.Default
|
||||
private val computeDispatcher: CoroutineDispatcher = Dispatchers.Default,
|
||||
// Injected so unit tests can pin the wall clock to the fixture TLE epoch and
|
||||
// stay deterministic; production callers keep the real clock default.
|
||||
private val nowMillis: () -> Long = System::currentTimeMillis
|
||||
) : ViewModel() {
|
||||
|
||||
private val _uiState = MutableStateFlow(MutualUiState())
|
||||
@@ -303,7 +306,7 @@ class MutualViewModel(
|
||||
queryGeneration += 1
|
||||
|
||||
viewModelScope.launch {
|
||||
val now = System.currentTimeMillis()
|
||||
val now = nowMillis()
|
||||
// 转发器类型筛选: 使用硬编码 AMSAT Live 清单 (见 Sources):
|
||||
// FM = {SO-50, ISS ZARYA, AO-123}, Linear = {RS-44, FO-29,
|
||||
// AO-7, AO-73, JO-97}. 不再依赖 AMSAT 网页同步: 任何网络下都
|
||||
|
||||
+4
-2
@@ -53,7 +53,9 @@ class MutualViewModelTest {
|
||||
): MutualViewModel = MutualViewModel(
|
||||
satelliteRepo = FakeSatelliteRepo(satellites, passes),
|
||||
settingsRepo = FakeSettingsRepo(position),
|
||||
computeDispatcher = StandardTestDispatcher(mainDispatcherRule.dispatcher.scheduler)
|
||||
computeDispatcher = StandardTestDispatcher(mainDispatcherRule.dispatcher.scheduler),
|
||||
// Pin the clock to the fixture base so results never depend on wall time.
|
||||
nowMillis = { TestOrbits.FIXTURE_BASE }
|
||||
)
|
||||
|
||||
private fun TestScope.queryAndSettle(vm: MutualViewModel) {
|
||||
@@ -219,7 +221,7 @@ class MutualViewModelTest {
|
||||
assertTrue(state.mutualPasses.all { it.catNum == 25544 })
|
||||
assertTrue(state.mutualPasses.all { it.name == "ISS (ZARYA)" })
|
||||
// AOS/LOS within the searched horizon
|
||||
val now = System.currentTimeMillis()
|
||||
val now = TestOrbits.FIXTURE_BASE
|
||||
assertTrue(state.mutualPasses.all { it.startTime >= now - 120_000L })
|
||||
assertTrue(state.mutualPasses.all { it.endTime <= now + 12 * 3600_000L + 120_000L })
|
||||
}
|
||||
|
||||
@@ -48,6 +48,15 @@ object TestOrbits {
|
||||
)
|
||||
)
|
||||
|
||||
/**
|
||||
* Fixed wall-clock base for every fixture computation: 2024-03-10T00:00Z,
|
||||
* ~18 h after [ISS]'s TLE epoch, so SGP4 propagates an accurate, healthy
|
||||
* orbit. Tests pin the ViewModel clock to this value as well
|
||||
* (MutualViewModel.nowMillis), which makes pass windows deterministic
|
||||
* instead of rotting as the fixture ages against System.currentTimeMillis().
|
||||
*/
|
||||
val FIXTURE_BASE: Long = 1710028800000L
|
||||
|
||||
/** Guangzhou (default BA7OPF grid OL62/OL63 area). */
|
||||
val GUANGZHOU = GeoPos(23.13, 113.26)
|
||||
|
||||
@@ -85,7 +94,7 @@ object TestOrbits {
|
||||
fun findPassWindows(
|
||||
sat: OrbitalObject = ISS,
|
||||
pos: GeoPos = GUANGZHOU,
|
||||
time: Long = System.currentTimeMillis(),
|
||||
time: Long = FIXTURE_BASE,
|
||||
hoursAhead: Int = 12
|
||||
): List<OrbitalPass> {
|
||||
if (!sat.willBeSeen(pos)) return emptyList()
|
||||
|
||||
Reference in new issue
Block a user