- Matrix testing:
datanow accepts aMap<K, V>directly, exposing each entry as a destructurablePair<K, V>(data("envs", mapOf("dev" to 8080)) - { (name, port) -> … }). Default name is"<index>: (key: value)". Entries iterate in map order, so use an ordered map (themapOf/linkedMapOfdefault) for reproduciblereplay.- Fluent receiver form
.asData(…)onIterable,Sequence, andMap, mirroringdataone-to-one:listOf(1, 2, 3).asData() - { … },myMap.asData(nameFn = { (k, _) -> k }) test { … }. nameFnnow resolves by lambda arity: a single-parameter namer ({ v -> … },{ it }, or destructured{ (k, v) -> … }) names cases by value alone; the two-parameter{ index, value -> … }form keeps the index; omitting it uses the indexed default. Applies todata,.asData, andproperty.
- Matrix testing:
- Breaking:
matrixSuite(...)now takes its configuration as a singlematrixConfig { … }argument instead of many named parameters:val Suite by matrixSuite(matrixConfig { execution = ExecutionMode.Concurrent(8); defaultCompactReport = … }) { … }(orval Suite by matrixSuite { … }with no config). This matches the per-scopetest/testSuiteconfig form. Migration: wrap the former named arguments inmatrixConfig { … }, turningname = value, …intoname = valuelines. - Why: the TestBalloon compiler plugin (observed on
1.0.0-K2.4.0-Beta2) silently fails to discover a top-levelval x by matrixSuite(...)when the call passes named arguments out of declaration order with non-constant values — Kotlin 2.4 lowers such a call into a temporary-introducing block, and the plugin'svisitPropertyNewonly recognizes a plainIrCall, so the suite is dropped from discovery ("did not discover any tests") or itsqualifiedPropertyNameis never injected. Collapsing the parameters into onematrixConfigargument keeps the call site a shape the plugin always discovers, regardless of how the config fields are ordered. (A standalone reproduction for the upstream framework bug lives inrepro-consumer/.) - Fix
TestConfigbeing re-applied at every nested matrix level. The base config (a session config captured viaMatrixTestDefaults { }, or a suite-leveltestConfig) is now applied once at the level it's set and inherited to children by TestBalloon, instead of being re-chained at each nested data/property case, suite, and test. This caused stateful wrappers to multiply — most visibly a sessiontestScopecombined withexecution = Concurrentdeadlocking or aborting discovery ("did not discover any tests"), and a suite-levelaroundAllrunning once per case. Removed the internalMatrixTestDefaults.testSessionConfigcapture (TestBalloon already propagates the session config). Per-elementtestConfigontest/testSuite/matrixSuite(incl. FreeSpec forms) still applies exactly once, soaroundAll/aroundEachbehave as expected. test/testSuiteand their FreeSpec"name"(…)forms now accept a full matrix config via a newmatrixConfig { … }value (e.g.testSuite("g", matrixConfig { execution = ExecutionMode.Concurrent(8) }) { },"g"(matrixConfig { … }) - { }). Unset fields inherit the enclosing scope;testConfigis one of the fields, so the existingtestConfig =forms are now thin wrappers aroundmatrixConfig { testConfig = … }. Lets you set per-subtree concurrency (and have it auto-disable theTestScope) without a separatematrixSuite. Also available on the fixture-scopetest/testSuite(and their FreeSpec forms). When amatrixConfigsets bothexecution = Concurrent(…)and atestConfigthat enables aTestScope, the concurrency disable wins.- Matrix concurrency now auto-disables TestBalloon's virtual-time
TestScope: anyExecutionMode.Concurrentlayer/suite and everycompactblock (both execute on real dispatchers) chaintestScope(isEnabled = false), so concurrent/compact matrices run even under a session that enablestestScope(the default) — no manualtestScope(isEnabled = false)needed. Sequential execution leaves the inheritedTestScopeintact.
- Breaking:
- Matrix testing:*
- Fail early nesting tests in tests instead of suites
- Deduplicate the
data/propertyAPI across the real-tree andcompactscopes. Both now share a single sealedMatrixScopesurface and one set ofdata/propertyoverloads (returningDataLayer/PropertyLayer), instead of two parallel copies. No behaviour change; the per-scope layer types (MatrixDataLayer/CompactDataLayer/ …) are gone. - Internal: collapse the compact
VirtualNodemodel from four layer variants (Data/DataTest/Property/PropertyTest) to two (Data/Property) carrying aLayerBody(container vs. terminal), halving the execution dispatch and removing duplicated child-scope building. No behaviour change. - Breaking — replay API. Replace the scalar+list replay overloads with one
replayparameter per layer, typed as a small self-describing value class: data takesreplay = Indexes(0L, 2L)(orIndexes(0L..9L)), property takesreplay = Cases(seed = 1L, iteration = 2L)(flat common case),Cases(Input(...), Input(...))for several seeds, orCases(seed, 1L..5L)for a range.ReplayInputis renamedInput. The copy-paste failure-report lines now emit these forms. Net: thedata/propertyoverloads drop from 12 to 6, and range selection is available via secondary constructors. MigratereplayIndex(es) = …→replay = Indexes(…),replay(s) = ReplayInput(…)→replay = Cases(…). - Internal: unify the parallel data/property machinery behind a single sealed
LayerSpec. The four real-tree*Internalregistration methods collapse to oneregisterLayer, the two compact registration methods to oneaddLayer, the twoVirtualNodelayer kinds to oneVirtualNode.Layer, and the two execution branches / four dispatch helpers each halve. ~190 fewer lines; public API (thedata/propertyoverloads,DataLayer/PropertyLayer, config builders) and all output are unchanged. - Annotate the named
data/propertyandcompactlayer functions with@TestRegistering, so the IDE shows a run-gutter on a top-level or statically-nested layer line (running the whole layer). Tests/suites nested inside adata/property/compactlayer still cannot be run from the gutter — their path contains a runtime-generated per-case segment — so run the enclosing layer or use aTESTBALLOON_INCLUDE_PATTERNSfilter. Nameless layers stay unannotated. See the Matrix "Notes" in the README.
- Matrix testing: nameless
data/propertylayersdataandpropertynow have overloads that omit the leading name (e.g.data(listOf(...)) test { ... },property(Arb.int()) - { ... }). A nameless layer skips the intermediate grouping node and registers its rows directly in the surrounding scope. A named layer remains shorthand for wrapping a nameless one in a labeled suite. Available in both regular andcompactscopes, across all overloads (Iterable/Sequence,replayIndex(es)/replay(s),- { }andtest { }).
- Matrix testing: replay info shows layer kind
Error replay infoframes are now tagged with their layer kind —(property)or(data)— for named and nameless layers alike (e.g.(property) seed: ...). Nameless layers print the marker without a name; the general failure/report path still shows no synthesized segment.
- Matrix testing: replace layer separator slash with TestBalloon separator arrow
- Matrix testing: replay info shows the full path
- The
Error replay infopath now mirrors the compact report path in full — enclosing grouping suites ("name" - { ... }) and plaintestleaves appear as path segments, not just the replayabledata/propertylayers. Only replayable layers still emit a- ...argument line; group-only chains produce no replay block.
- The
- Matrix testing: bounded compact concurrency
CompactConcurrency.Shared(n)runs a compact block through one compact-wide worker budget, so nested virtual layers can no longer multiply coroutine counts;CompactConcurrency.Layeredkeeps per-layer behaviour. Set it percompactblock or viadefaultCompactConcurrency.
- Matrix testing: replay failing cases
- Failure reports — real test-tree leaves and compacted virtual rows alike — now include a copy-paste-ready
Error replay infoblock whose lines are validproperty/dataarguments. - Pin a property layer to recorded cases with
replay = ReplayInput(seed, iteration), orreplays = listOf(...)for several seed/iteration pairs at once; pin a data layer withreplayIndex/replayIndexes. Pasting the reported lines re-runs exactly the failing case(s). replayis independent of a layer'sseed(deterministic full run vs. selecting recorded cases).- Replay info captures the full enclosing layer chain and records data indexes independently of
nameFn.
- Failure reports — real test-tree leaves and compacted virtual rows alike — now include a copy-paste-ready
- Matrix testing: API changes:
- Make name for compact layers mandatory
- Matrix testing
- TestBalloon 1.0.0
- Improve compacted data/property test reporting:
- Add a
Summary: X OK, Y failedline to compacted failure messages - Add
suppressCompactSuccessesconfiguration and terminal overrides to omit individualOKrows while keeping the summary - Avoid recursively embedding full nested compacted reports in parent compacted error rows
- Bound compacted failure row names using the configured test name length
- Add a
- Add concurrent execution for compacted suspending terminal
withDataandcheckAllleaves viacompactConcurrent - Add periodic progress heartbeat output while compacted terminal
withDataandcheckAllleaves are running - Simplify and fix custom truncation/stringification for primitive and unsigned arrays
- By default, only the first error's stack trace is reported for compacted data/property tests. This used to be
different. To fall back to the old behaviour (or for debugging), set
addSuppressedErrorsToCompactedFailures = true - Remove deprecated functions marked for removal. Refactor as follows:
withDataSuites(…) {…}->withData(…) - {…}(note the dash)checkAllSuites(…) {…}->checkAll(…) - {…}(note the dash)
- Remove
displayNameanddisplayNameLength - Remove deprecated
DEFAULT_TEST_NAME_MAX_LEN
- treat varags of
Pair<String,*>the same asMap<String,*>in data-driven tests - TestBalloon 0.8.2
- Fix incorrect internal reference to max length
- Platform-agnostic test name length defaults
- Prefixes for data test and property test
- Shorter compact names
- Global test name length configuration -> deprecate
DEFAULT_TEST_NAME_MAX_LEN - Hard fails on too long overall test names on Android
- Support TestBalloon 0.8-RC
- Add missing TestExecutionScope to data-driven test leaves
- Support fixture generation for suites in addition to tests
- Support nesting, but only ever use the fixture generator for the toplevel scope
- FreeSpec now requires explicit fixture parameter specification to disambiguate
- Remove deprecated properties marked for removal with 0.6
- Refactor to get rid of reification for:
- proper stack traces
- Kotlin 2.3 compatibility
- Sane default stringification of collection and arrays types
- All primitive arrays are correctly joined to string
- All unsigned arrays are correctly joined to string
ByteArrayandUByteArrayuse hex notation
- fix property test compacting bug
- clarify deprecations
- Datatest
- fix misnamed
withDataSuites - fix misnamed
arguments->parameters
- fix misnamed
- Fix length config bug
- Default display name max length to -1 (no truncation)
- Remove bare-lambda fixture generation
- Change global defaults and fix length bug
- Allow globally (and per test/suite) setting of max display length
Configurable max test name length (globally and per test)
- Revised fixture generation
- Use explicit function instead of bare lambdas; no more context params needed
- Deprecate old bare lambdas
- Optionally compacted data driven tests and property tests
- Work around test name issues
- More migration helpers and alternative syntax for nesting suites
- Per-test fixture generation addon
- Update to TestBalloon 0.7.1
Initial release