Skip to content

Testing

Ahmed Abbas edited this page May 27, 2026 · 1 revision

Testing

This page covers testing your app's integration with the Convert Android SDK — making experiment decisions deterministic in tests, capturing SDK logs, and keeping tracking quiet. For testing the SDK itself, see its repository.

Make decisions deterministic with direct-data mode

The biggest source of test flakiness is the asynchronous config fetch. Avoid it entirely by building the SDK in direct-data mode with a known config fixture, so decisions are available synchronously and never depend on the network:

import com.convert.sdk.android.ConvertSDK
import com.convert.sdk.core.model.generated.ConfigResponseData

val config: ConfigResponseData = loadTestConfig() // deserialize a fixture JSON
val sdk = ConvertSDK.builder(context)
    .data(config)
    .build()

sdk.onReady {
    val ctx = sdk.createContext("test-visitor")
    val variation = ctx.runExperience("homepage-redesign")
    // assert on variation?.key
}

With data(...) set, the SDK seeds its config without an HTTP call. Use a stable explicit visitor id (e.g. "test-visitor") so bucketing is reproducible run to run — the same id always maps to the same variation for a given experience.

Keep tracking quiet in tests

Disable outbound tracking so tests do not emit network events:

val sdk = ConvertSDK.builder(context)
    .data(config)
    .trackingEnabled(false)
    .build()

Bucketing, rule evaluation, and sticky persistence still work with tracking disabled — only the network side is silenced. See Tracking Control. For a single call, use the per-call override: ctx.runExperience("key", enableTracking = false).

Run on the JVM with Robolectric

The SDK uses Android APIs (SharedPreferences, ConnectivityManager, WorkManager), so integration tests that build a real ConvertSDK run under Robolectric rather than as plain JVM unit tests.

@RunWith(RobolectricTestRunner::class)
class MyConvertIntegrationTest {
    @Test
    fun bucketsVisitorDeterministically() {
        val sdk = ConvertSDK.builder(ApplicationProvider.getApplicationContext())
            .data(loadTestConfig())
            .trackingEnabled(false)
            .build()
        // ...assert on decisions
    }
}

Capturing logs

The SDK logs through android.util.Log under the tag ConvertSDK. In Robolectric tests you can assert on emitted log lines via org.robolectric.shadows.ShadowLog.getLogs(). Set the log level high while debugging a test:

ConvertSDK.builder(context)
    .data(config)
    .logLevel(LogLevel.DEBUG)
    .build()

Tips

  • One SDK per test — build a fresh ConvertSDK per test (or per class) so visitor and queue state do not leak between tests.
  • Use explicit visitor ids — never rely on the auto-UUID in tests; an explicit id makes bucketing assertions stable.
  • Prefer fixtures over live keys — direct-data mode with a checked-in config fixture keeps tests hermetic and fast.

Related pages

Clone this wiki locally