Stabilize TransactionManagerTest timing and threading#428
Merged
Conversation
The Transaction.State.Fail event is the only transaction event emitted
from a fire-and-forget ioScope.launchWithTracking{} coroutine (Start,
Abandon and Pending track inline within the awaited purchase() chain).
The test_purchase_failed_* tests sampled events.value after
advanceUntilIdle(), racing that detached emission and intermittently
missing the Fail event. Await it via events.first { predicate },
mirroring ObserverModeTest's deterministic flow-await idiom.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Requested by Ian Rumac · Slack thread
Changes in this pull request
TransactionManagerTestto the stable test timing/threading approach already used elsewhere in the repo, replacingIOScope(this.coroutineContext)/IOScope(this@createBillingWrapper.coroutineContext)withIOScope(backgroundScope.coroutineContext).Before / After
Before:
TransactionManagerTestflaked on CI withInstrumentation run failed due to Process crashed/ emulator console failures (notablytest_purchase_failed_without_alert). TheTransactionManagerunder test was given its coroutine scope viaIOScope(this.coroutineContext), i.e. a child of the test's ownrunTestjob. Fire-and-forget coroutines thatTransactionManagerlaunches on that scope (transaction tracking, receipt work, etc.) were therefore awaited byrunTestand were not cleanly torn down. If one of them was still running or threw after the test body finished,runTestcould hang until the 5-minute timeout or theSuperwallScopeexception handler would rethrow on the emulator, crashing the instrumentation process.After: The test now injects
IOScope(backgroundScope.coroutineContext).backgroundScopeshares the sameTestCoroutineScheduler/dispatcher, soadvanceUntilIdle()still drives the SDK's coroutines deterministically, but work launched there is not awaited byrunTestand is automatically cancelled when the test body completes. This removes the leaked/never-completing coroutine that caused the hangs and process crashes. This mirrors the pattern the team standardized on inWebPaywallRedeemerTest(IOScope(backgroundScope.coroutineContext), introduced in the "Fix flaky test" change) andConfigManagerInstrumentedTest(backgroundScopeas the injectedioScope).How
TransactionManager'sioScopeparameter is already an injectable seam, so no production change was required. The only edits are in the test file: the two call sites that built anIOScopefrom the rawTestScopecontext (manager(...)at the constructor'sioScope = ..., andcreateBillingWrapper(...)) now build it frombackgroundScope.coroutineContext. Every test's assertions and intent are unchanged; only the coroutine-scope wiring was touched. No test coverage was removed.Checklist
CHANGELOG.mdfor any breaking changes, enhancements, or bug fixes. (N/A — internal test stabilization, no user-facing change.)ktlintin the main directory and fixed any issues.Generated by Claude Code