TestBalloon

repository·main·Indexed 42 days ago

https://github.com/infix-de/testballoon

A Kotlin-first, DSL-based testing framework that prioritizes plain Kotlin code over annotations. It is designed for high flexibility and deep integration across all Kotlin target platforms, including Android and Kotlin Multiplatform.

Tokens
24.3K
Snippets
71
Records
134
Agent score
54%

What's inside TestBalloon

  1. Overview of TestBalloon capabilities

    main

    TestBalloon is a DSL-based, Kotlin-first test framework designed to replace restrictive, annotation-based testing with plain Kotlin configuration. It provides a concise and flexible API that is easy to customize for various test setups.

    Key Features

    • Advanced Testing Patterns: Supports parameterized tests, multi-level hierarchies, fixtures, and expressive naming.
    • Concurrency: Built-in full coroutine support with coroutine context inheritance and deep parallelism.
    • Extensibility: Uses a scope-friendly DSL and decorator chains for configuration.
    • Assertion Compatibility: Works with existing assertion libraries and Kotlin Power Assert.
    • Platform Integration: Deeply integrated with Gradle tasks and Kotlin's platform-specific test runtimes.
  2. Overview of TestBalloon

    main

    TestBalloon is a DSL-based, Kotlin-first testing framework designed to replace restrictive, annotation-based testing with plain Kotlin configuration. It provides a concise and flexible API that is easy to customize for various test setups.

    Key Capabilities:

    • Advanced Test Features: Supports parameterized tests, multi-level hierarchies, fixtures, expressive naming, and decorator chains for configuration.
    • Concurrency: Built-in full coroutine support with coroutine context inheritance and high-degree parallelism.
    • Compatibility: Works with existing assertion libraries and Kotlin Power Assert.
    • Platform Support: Native support for all Kotlin target platforms, including JVM, JS, WebAssembly, Native (Linux, Windows, iOS, macOS), Android (host-side and device-side), and Robolectric.
  3. IntelliJ IDEA integration and limitations

    main

    TestBalloon integrates with IntelliJ IDEA (ideally via the TestBalloon plugin).

    Features:

    • Run/Debug gutter icons for individual tests and suites.
    • Test status indicators (success/fail) for JVM targets.
    • Results appear in the standard IntelliJ test run window.
    • Stack traces automatically fold framework-internal lines.
    • Kotlin inspections for title-case naming of suite properties.

    Limitations:

    • The "Rerun Failed Tests" action in the test run window is not supported.
  4. Android Platform Support Overview

    main

    TestBalloon supports both Android host-side (unit) tests and Android device-side (instrumented) tests.

    Key Capabilities & Limitations:

    • JUnit 4 Support: Releases 0.7.0 and above support using JUnit 4 rules within TestBalloon tests.
    • Compatibility: Existing JUnit 4 tests can run alongside TestBalloon tests.
    • Nested Suites: Nested test suites are supported.
    • Limitation: Concurrent or parallel test invocation is not supported on Android because it conflicts with how the Android test infrastructure handles Activities.
  5. Key features and capabilities of TestBalloon

    main

    TestBalloon is a Kotlin-first, DSL-based testing framework designed to eliminate bloat and provide a small-surface API. It is built to scale with complex interactions and across multiple targets.

    Core Capabilities:

    • Parameterized tests: Easily run the same test logic with different inputs.
    • Multi-level hierarchy: Organize tests into structured, expressive hierarchies.
    • Coroutine support: Full built-in support for Coroutines and coroutine context inheritance.
    • Deep parallelism: High-performance test execution via concurrent runs.
    • Fixtures: Managed test data and environment setup.
    • Expressive names: Clear, readable test identification.
    • Scope-friendly DSL: A domain-specific language that respects Kotlin scopes.
    • Configuration via decorator chains: Flexible test configuration using decorators.
  6. What is a fixture in TestBalloon

    main

    A fixture is a state holder for a lazily initialized value used across multiple tests. Fixtures allow you to define setup and tear-down logic for test data or resources.

    Fixtures are created using the testFixture function, where the trailing lambda produces the value. The initialization can be a suspending block.

    Creating a fixture

    You can return an existing class instance or a custom object:

    // Using an existing class
    testFixture {
        Account(balance = 42.0)
    }
    
    // Using a custom object for multiple properties
    testFixture {
        object {
            val initialBalance = 42.0
            val account = Account(balance = initialBalance)
        }
    }
    testFixture {
        Account(balance = 42.0)
    }
  7. Understand TestBalloon API stability and deprecation cycles

    main

    TestBalloon is production-ready, but users should expect potential migration issues as the public API evolves. From release 1.0 onwards, TestBalloon follows a strict three-step deprecation cycle for API changes:

    1. Version n: The old API is marked with a deprecation WARNING.
    2. Version n+1: The old API is marked with a deprecation ERROR.
    3. Version n+2: The old API is removed.

    For changes that provide source-compatible overloads, the old API will receive a HIDDEN deprecation immediately.

    TestBalloon aims for:

    • Functional stability: No unexpected or incompatible behavior changes.
    • Source compatibility: Providing migration paths for necessary changes.
    • Binary compatibility: Providing a stable binary API for extensions.
  8. How TestBalloon structures test hierarchies

    main

    TestBalloon uses a hierarchical model to organize tests, allowing for flexible grouping beyond simple class-based suites. The hierarchy is composed of:

    • TestSession: The root of the hierarchy for an individual test run.
    • TestSuite: A grouping element that contains child elements (other suites or tests). Suites cannot contain direct test logic.
    • Test: An element containing the actual test logic and assertions. Tests cannot have child elements.
    • TestElement: The base interface/type for all elements in the hierarchy.

    This structure allows for deep nesting and complex organization of test sets.

  9. How incremental compilation tests work

    main

    Incremental compilation tests verify TestBalloon's behavior in Kotlin/JVM and KMP projects using the following lifecycle:

    1. Project Setup: TestBalloon uses test suites named incremental-compilation-testBalloon-*. For each suite, a project template is copied into integration-test/build/projects.
    2. Test Series Execution: A testSeries() invocation prepares the project (e.g., via gradlew clean) and registers a sequence of tests, typically:
      • baseline: Initial compilation from a clean state.
      • remove File1.kt: Testing compilation after a file removal.
      • restore File1.kt: Testing compilation after a file restoration.
    3. Verification: TestBalloon runs these tests in order, invoking Gradle for each task and verifying that the results meet expected outcomes.

    Manual Inspection: After execution, the projects remain in integration-test/build/projects/incremental-compilation-testBalloon-*. You can examine build reports or use these self-contained projects for manual testing.

  10. Understand the TestBalloon coroutine hierarchy

    main

    TestBalloon organizes tests and suites into a test element hierarchy. Each element in this hierarchy (test, suite, compartment, or session) is assigned its own coroutine. The parent-child relationship between these coroutines mirrors the relationship between the test elements themselves, meaning coroutine contexts are inherited down the hierarchy.

    This structure allows for structured testing where configuration and context flow from the top-level session down to individual tests.

  11. Configure Gradle test filtering

    main

    Gradle uses the JUnit Platform API for test selection but applies its own restricted selection logic.

    Selection Mechanisms

    Gradle's Test task uses:

    • ClassSelector: Gradle passes a selector for every class it finds (it does not know which are test classes beforehand).
    • UniqueIdSelector: Used by Gradle Enterprise to distribute tests across processes.
    • ClassNameFilter: Used when explicit test filtering is applied.

    Known Limitations

    Gradle's selection logic can be erratic and may fail to match patterns for certain JUnit 4/5 structures, such as:

    • @Nested tests in JUnit 5.
    • Parameterized tests in JUnit 4 or 5.

    If patterns fail to match, it is often due to Gradle's internal TestSelectionMatcher assuming a restricted test structure.