Skip to content

Test Fixtures

Ali Sadeghi edited this page May 28, 2026 · 7 revisions

Test Fixtures Agent

Generates two reusable test data files: domain fixtures and UI fixtures.

Spawned by: Feature-Test · Model: sonnet · Color: purple Output paths:

feature/{name}/src/commonTest/kotlin/{pkg}/{name}/fixtures/{Feature}Fixtures.kt
feature/{name}/src/commonTest/kotlin/{pkg}/{name}/fixtures/{Feature}UiFixtures.kt

The agent does not re-read source files; it works from the YAML context the orchestrator passes.

{Feature}Fixtures.kt

Domain-level factories with sensible defaults plus mandatory edge cases.

object DashboardFixtures {

    // === DOMAIN MODEL FACTORIES ===

    fun createDashboard(
        id: String = "test-id",
        name: String = "Test Name",
        description: String? = "Test Description",
        // ... every field with a default
    ) = Dashboard(id = id, name = name, description = description)

    fun createDashboardList(count: Int = 3) =
        (1..count).map { i -> createDashboard(id = "id-$i", name = "Entity $i") }

    fun createEmptyDashboardList() = emptyList<Dashboard>()
    fun createSingleDashboardList() = listOf(createDashboard())
    fun createLargeDashboardList(count: Int = 100) = createDashboardList(count)

    // === EDGE CASES (ALL MANDATORY) ===
    fun createDashboardWithNullOptionals() = createDashboard(description = null)
    fun createDashboardWithEmptyStrings() = createDashboard(name = "", description = "")
    fun createDashboardWithBlankStrings() = createDashboard(name = "   ", description = "   ")
    fun createDashboardWithSpecialCharacters() = createDashboard(
        name = "Test's \"Entity\" with <special> & chars",
        description = "Line1\nLine2\tTabbed",
    )
    fun createDashboardWithUnicode() = createDashboard(name = "Test 日本語 🎉")
    fun createDashboardWithLongStrings() = createDashboard(name = "a".repeat(500))
    fun createDashboardWithMaxValues() = createDashboard(/* numeric = MAX_VALUE */)
    fun createDashboardWithMinValues() = createDashboard(/* numeric = MIN_VALUE / 0 */)

    // === DTO FACTORIES + RESPONSE WRAPPERS ===
    fun createDashboardDto(/* ALL DTO fields */) = DashboardDto(/* ... */)
    fun createDashboardResponse(
        results: List<DashboardDto> = createDashboardDtoList(),
        count: Int = results.size,
        next: String? = null,
        previous: String? = null,
    ) = DashboardResponse(results, count, next, previous)

    // === ERROR HELPERS (ErrorConst) ===
    val networkError      = ErrorConst.NoNetwork
    val unauthorizedError = ErrorConst.Unauthorized
    val notFoundError     = ErrorModel.MessageCode("Dashboard not found", 404)
    val badRequestError   = ErrorModel.MessageCode("Invalid request parameters", 4001)
    val timeoutError      = ErrorConst.ServerUnknownError(408)
    val serverError       = ErrorConst.ServerUnknownError(500)
    val serviceUnavailableError = ErrorConst.ServerUnknownError(503)
    val serializationError = ErrorConst.SerializationError

    // === EITHER HELPERS ===
    fun createSuccessDashboard(entity: Dashboard = createDashboard()) = Either.Success(entity)
    fun createSuccessDashboardList(entities: List<Dashboard> = createDashboardList()) = Either.Success(entities)
    fun createFailureDashboard(error: ErrorModel = networkError) = Either.Failure(error)

    // === JSON RESPONSES (NetworkErrorModel format) ===
    val validDashboardJson      = """{"id": "test-id", "name": "Test Name"}"""
    val validDashboardListJson  = """[ ... ]"""
    val emptyDashboardListJson  = "[]"
    val error400Json = """{"detail": "Invalid request parameters", "code": 4001}"""
    val error401Json = """{"detail": "Unauthorized", "code": null}"""
    val error404Json = """{"detail": "Dashboard not found", "code": 404}"""
    val error500Json = """{"detail": "Internal Server Error", "code": 5001}"""
    val error503Json = """{"detail": null, "code": null}"""
    val malformedJson        = "{ invalid json"
    val incompleteJson       = """{"id": "test-id"}"""
    val nullFieldsJson       = """{"id": "test-id", "name": "Test", "description": null}"""
    val extraFieldsJson      = """{"id": "test-id", "name": "Test", "unknownField": "ignored"}"""
    val emptyStringFieldsJson = """{"id": "", "name": ""}"""
    val specialCharsJson     = """{"id": "test-id", "name": "Test's \"Name\" & <more>"}"""
    val unicodeJson          = """{"id": "test-id", "name": "日本語 🎉"}"""
}

{Feature}UiFixtures.kt

UI-state factories. The 4 mandatory states plus common variations.

object DashboardUiFixtures {

    // === 4 MANDATORY STATES ===
    fun createUninitializedState() = DashboardUiModel(dataState = UiState.Uninitialized)
    fun createLoadingState()       = DashboardUiModel(dataState = UiState.Loading)
    fun createSuccessState(entities: List<Dashboard> = DashboardFixtures.createDashboardList()) =
        DashboardUiModel(dataState = UiState.Success(entities.toImmutableList()))
    fun createEmptyState() = DashboardUiModel(dataState = UiState.Success(persistentListOf()))
    fun createErrorState(message: String = "Something went wrong") =
        DashboardUiModel(dataState = UiState.Failed(ErrorModel.Message(message)))

    // === SUCCESS VARIATIONS ===
    fun createSingleItemState() = createSuccessState(DashboardFixtures.createSingleDashboardList())
    fun createLargeListState(count: Int = 50) = createSuccessState(DashboardFixtures.createDashboardList(count))

    // === ERROR VARIATIONS ===
    fun createNetworkErrorState()      = DashboardUiModel(dataState = UiState.Failed(DashboardFixtures.networkError))
    fun createUnauthorizedErrorState() = DashboardUiModel(dataState = UiState.Failed(DashboardFixtures.unauthorizedError))
    fun createNotFoundErrorState()     = DashboardUiModel(dataState = UiState.Failed(DashboardFixtures.notFoundError))
    fun createServerErrorState()       = DashboardUiModel(dataState = UiState.Failed(DashboardFixtures.serverError))

    // === INPUT / DIALOG / SELECTION (when applicable) ===
    fun createWithValidInput(inputValue: String = "valid input") = DashboardUiModel(...)
    fun createShowingConfirmDialog(entity: Dashboard = DashboardFixtures.createDashboard()) = DashboardUiModel(...)
    fun createWithSelectedItem(selectedId: String = "id-1") = DashboardUiModel(...)
    fun createWithSearchQuery(query: String = "search term") = DashboardUiModel(...)
}

Checklist

{Feature}Fixtures.kt:

  • createEntity() with ALL fields | List / Empty / Single / Large
  • Edge cases: NullOptionals, EmptyStrings, BlankStrings, SpecialCharacters, Unicode, LongStrings, MaxValues, MinValues
  • DTO factories | Response wrappers (if paginated)
  • Error helpers using ErrorConst (8 types)
  • Either helpers: createSuccessEntity(), createFailureEntity()
  • JSON: valid, empty, error (400-503), malformed, incomplete, nullFields, extraFields, specialChars, unicode

{Feature}UiFixtures.kt:

  • 4 base states: Uninitialized, Loading, Success, Empty, Error
  • Success variations: Single, Large
  • Error variations: Network, Unauthorized, NotFound, Server
  • Dialog / Input / Selection states (if applicable)

Verify

./gradlew :feature:{featurename}:compileTestKotlinDesktop

Back to Testing-Agents | Agents

Clone this wiki locally