feat: add TestScenario GWT testing helpers to eventcore-testing#346
Merged
feat: add TestScenario GWT testing helpers to eventcore-testing#346
Conversation
Add TestScenario with a Given-When-Then fluent API for writing eventcore integration tests: - given_events(stream_id, events) seeds precondition events - when(command) executes a command and collects results - succeeded() / failed_with_business_rule() assert outcomes - then_events(expected) / then_event_count(n) verify stored events The "remove fluent StreamWrites API" part of the original issue does not apply — the register_stream/append pattern is the core write mechanism used by execute() and cannot be removed. Closes #241
jwilger
reviewed
Apr 11, 2026
Replace failed_with_business_rule(&str) with failed_with(impl Into<CommandError>) to match the typed error pattern established by require! macro (#327). Update the scenario test's Withdraw command to use require! with a typed WithdrawError enum, demonstrating the intended pattern. Update thiserror-for-errors rule to cover test assertion helpers.
jwilger
approved these changes
Apr 11, 2026
Merged
jwilger
added a commit
that referenced
this pull request
Apr 13, 2026
## 🤖 New release
* `eventcore-macros`: 0.6.0 -> 0.7.0
* `eventcore-types`: 0.6.0 -> 0.7.0 (⚠ API breaking changes)
* `eventcore-postgres`: 0.6.0 -> 0.7.0 (⚠ API breaking changes)
* `eventcore-sqlite`: 0.6.0 -> 0.7.0 (⚠ API breaking changes)
* `eventcore`: 0.6.0 -> 0.7.0 (⚠ API breaking changes)
* `eventcore-memory`: 0.6.0 -> 0.7.0 (⚠ API breaking changes)
* `eventcore-testing`: 0.6.0 -> 0.7.0 (✓ API compatible changes)
* `eventcore-examples`: 0.6.0 -> 0.7.0 (✓ API compatible changes)
### ⚠ `eventcore-types` breaking changes
```text
--- failure auto_trait_impl_removed: auto trait no longer implemented ---
Description:
A public type has stopped implementing one or more auto traits. This can break downstream code that depends on the traits being implemented.
ref: https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits
impl: https://github.com/obi1kenobi/cargo-semver-checks/tree/v0.47.0/src/lints/auto_trait_impl_removed.ron
Failed in:
type CommandError is no longer UnwindSafe, in /tmp/.tmp9Ta52e/eventcore/eventcore-types/src/errors.rs:21
type CommandError is no longer RefUnwindSafe, in /tmp/.tmp9Ta52e/eventcore/eventcore-types/src/errors.rs:21
--- failure enum_unit_variant_changed_kind: An enum unit variant changed kind ---
Description:
A public enum's exhaustive unit variant has changed to a different kind of enum variant, breaking possible instantiations and patterns.
ref: https://doc.rust-lang.org/reference/items/enumerations.html
impl: https://github.com/obi1kenobi/cargo-semver-checks/tree/v0.47.0/src/lints/enum_unit_variant_changed_kind.ron
Failed in:
variant EventStoreError::VersionConflict in /tmp/.tmp9Ta52e/eventcore/eventcore-types/src/store.rs:381
--- failure trait_added_supertrait: non-sealed trait added new supertraits ---
Description:
A non-sealed trait added one or more supertraits, which breaks downstream implementations of the trait
ref: https://doc.rust-lang.org/cargo/reference/semver.html#generic-bounds-tighten
impl: https://github.com/obi1kenobi/cargo-semver-checks/tree/v0.47.0/src/lints/trait_added_supertrait.ron
Failed in:
trait eventcore_types::CommandLogic gained Send in file /tmp/.tmp9Ta52e/eventcore/eventcore-types/src/command.rs:149
trait eventcore_types::CommandLogic gained Sync in file /tmp/.tmp9Ta52e/eventcore/eventcore-types/src/command.rs:149
--- failure trait_method_added: pub trait method added ---
Description:
A non-sealed public trait added a new method without a default implementation, which breaks downstream implementations of the trait
ref: https://doc.rust-lang.org/cargo/reference/semver.html#trait-new-item-no-default
impl: https://github.com/obi1kenobi/cargo-semver-checks/tree/v0.47.0/src/lints/trait_method_added.ron
Failed in:
trait method eventcore_types::Event::event_type_name in file /tmp/.tmp9Ta52e/eventcore/eventcore-types/src/command.rs:128
```
### ⚠ `eventcore-postgres` breaking changes
```text
--- failure enum_unit_variant_changed_kind: An enum unit variant changed kind ---
Description:
A public enum's exhaustive unit variant has changed to a different kind of enum variant, breaking possible instantiations and patterns.
ref: https://doc.rust-lang.org/reference/items/enumerations.html
impl: https://github.com/obi1kenobi/cargo-semver-checks/tree/v0.47.0/src/lints/enum_unit_variant_changed_kind.ron
Failed in:
variant CoordinationError::LeadershipNotAcquired in /tmp/.tmp9Ta52e/eventcore/eventcore-postgres/src/lib.rs:540
```
### ⚠ `eventcore-sqlite` breaking changes
```text
--- failure enum_variant_added: enum variant added on exhaustive enum ---
Description:
A publicly-visible enum without #[non_exhaustive] has a new variant.
ref: https://doc.rust-lang.org/cargo/reference/semver.html#enum-variant-new
impl: https://github.com/obi1kenobi/cargo-semver-checks/tree/v0.47.0/src/lints/enum_variant_added.ron
Failed in:
variant SqliteCoordinationError:LockPoisoned in /tmp/.tmp9Ta52e/eventcore/eventcore-sqlite/src/lib.rs:57
```
### ⚠ `eventcore` breaking changes
```text
--- failure enum_missing: pub enum removed or renamed ---
Description:
A publicly-visible enum cannot be imported by its prior path. A `pub use` may have been removed, or the enum itself may have been renamed or removed entirely.
ref: https://doc.rust-lang.org/cargo/reference/semver.html#item-remove
impl: https://github.com/obi1kenobi/cargo-semver-checks/tree/v0.47.0/src/lints/enum_missing.ron
Failed in:
enum eventcore::PollMode, previously in file /tmp/.tmpiyxp8q/eventcore/src/projection.rs:101
--- failure function_parameter_count_changed: pub fn parameter count changed ---
Description:
A publicly-visible function now takes a different number of parameters.
ref: https://doc.rust-lang.org/cargo/reference/semver.html#fn-change-arity
impl: https://github.com/obi1kenobi/cargo-semver-checks/tree/v0.47.0/src/lints/function_parameter_count_changed.ron
Failed in:
eventcore::run_projection now takes 3 parameters instead of 2, in /tmp/.tmp9Ta52e/eventcore/eventcore/src/projection.rs:586
--- failure struct_missing: pub struct removed or renamed ---
Description:
A publicly-visible struct cannot be imported by its prior path. A `pub use` may have been removed, or the struct itself may have been renamed or removed entirely.
ref: https://doc.rust-lang.org/cargo/reference/semver.html#item-remove
impl: https://github.com/obi1kenobi/cargo-semver-checks/tree/v0.47.0/src/lints/struct_missing.ron
Failed in:
struct eventcore::NoCheckpointStore, previously in file /tmp/.tmpiyxp8q/eventcore/src/projection.rs:161
struct eventcore::ProjectionRunner, previously in file /tmp/.tmpiyxp8q/eventcore/src/projection.rs:141
struct eventcore::PollConfig, previously in file /tmp/.tmpiyxp8q/eventcore/src/projection.rs:26
struct eventcore::EventRetryConfig, previously in file /tmp/.tmpiyxp8q/eventcore/src/projection.rs:72
```
### ⚠ `eventcore-memory` breaking changes
```text
--- failure struct_with_no_pub_fields_changed_type: public API struct with no public fields is no longer a struct ---
Description:
A struct without pub fields became an enum or union, breaking pattern matching.
ref: https://internals.rust-lang.org/t/rest-patterns-foo-should-match-non-struct-types/21607
impl: https://github.com/obi1kenobi/cargo-semver-checks/tree/v0.47.0/src/lints/struct_with_no_pub_fields_changed_type.ron
Failed in:
struct eventcore_memory::InMemoryCheckpointError became enum in file /tmp/.tmp9Ta52e/eventcore/eventcore-memory/src/lib.rs:324
```
<details><summary><i><b>Changelog</b></i></summary><p>
## `eventcore-macros`
<blockquote>
##
[0.7.0](eventcore-macros-v0.6.0...eventcore-macros-v0.7.0)
- 2026-04-13
### Bug Fixes
- improve error message consistency, context, and safety across all
crates ([#352](#352))
### Features
- enhance require! macro to accept typed error values
([#335](#335))
- add required event_type_name() to Event trait for stable storage
([#344](#344))
### Miscellaneous Tasks
- adopt han plugins, blueprints, and project conventions
([#330](#330))
- consolidate workspace lints and enforce strict lint policy
([#351](#351))
### Refactoring
- expose projection config via free function API, then reduce public
surface ([#357](#357))
</blockquote>
## `eventcore-types`
<blockquote>
##
[0.7.0](eventcore-types-v0.6.0...eventcore-types-v0.7.0)
- 2026-04-13
### Bug Fixes
- add Send+Sync bounds to CommandLogic for Send futures
([#332](#332))
- improve error message consistency, context, and safety across all
crates ([#352](#352))
### Features
- enhance require! macro to accept typed error values
([#335](#335))
- add required event_type_name() to Event trait for stable storage
([#344](#344))
### Miscellaneous Tasks
- consolidate workspace lints and enforce strict lint policy
([#351](#351))
### Refactoring
- replace into_inner() with into() for nutype domain types
([#334](#334))
</blockquote>
## `eventcore-postgres`
<blockquote>
##
[0.7.0](eventcore-postgres-v0.6.0...eventcore-postgres-v0.7.0)
- 2026-04-13
### Bug Fixes
- improve error message consistency, context, and safety across all
crates ([#352](#352))
### Features
- add required event_type_name() to Event trait for stable storage
([#344](#344))
### Miscellaneous Tasks
- adopt han plugins, blueprints, and project conventions
([#330](#330))
- consolidate workspace lints and enforce strict lint policy
([#351](#351))
</blockquote>
## `eventcore-sqlite`
<blockquote>
##
[0.7.0](eventcore-sqlite-v0.6.0...eventcore-sqlite-v0.7.0)
- 2026-04-13
### Bug Fixes
- apply PRAGMA key before WAL mode in SQLite encrypted stores
([#333](#333))
- improve error message consistency, context, and safety across all
crates ([#352](#352))
### Miscellaneous Tasks
- consolidate workspace lints and enforce strict lint policy
([#351](#351))
</blockquote>
## `eventcore`
<blockquote>
##
[0.7.0](eventcore-v0.6.0...eventcore-v0.7.0)
- 2026-04-13
### Bug Fixes
- improve error message consistency, context, and safety across all
crates ([#352](#352))
### Features
- enhance require! macro to accept typed error values
([#335](#335))
- add required event_type_name() to Event trait for stable storage
([#344](#344))
### Miscellaneous Tasks
- adopt han plugins, blueprints, and project conventions
([#330](#330))
- consolidate workspace lints and enforce strict lint policy
([#351](#351))
### Refactoring
- replace into_inner() with into() for nutype domain types
([#334](#334))
- extract pure state machines from execute() and run()
([#349](#349))
- expose projection config via free function API, then reduce public
surface ([#357](#357))
</blockquote>
## `eventcore-memory`
<blockquote>
##
[0.7.0](eventcore-memory-v0.6.0...eventcore-memory-v0.7.0)
- 2026-04-13
### Bug Fixes
- make InMemoryEventStore error on read_stream type mismatch
([#342](#342))
- improve error message consistency, context, and safety across all
crates ([#352](#352))
### Features
- add required event_type_name() to Event trait for stable storage
([#344](#344))
### Miscellaneous Tasks
- consolidate workspace lints and enforce strict lint policy
([#351](#351))
</blockquote>
## `eventcore-testing`
<blockquote>
##
[0.7.0](eventcore-testing-v0.6.0...eventcore-testing-v0.7.0)
- 2026-04-13
### Bug Fixes
- make InMemoryEventStore error on read_stream type mismatch
([#342](#342))
- improve error message consistency, context, and safety across all
crates ([#352](#352))
### Features
- add required event_type_name() to Event trait for stable storage
([#344](#344))
- add TestScenario GWT testing helpers to eventcore-testing
([#346](#346))
### Miscellaneous Tasks
- consolidate workspace lints and enforce strict lint policy
([#351](#351))
### Refactoring
- expose projection config via free function API, then reduce public
surface ([#357](#357))
</blockquote>
## `eventcore-examples`
<blockquote>
##
[0.7.0](eventcore-examples-v0.6.0...eventcore-examples-v0.7.0)
- 2026-04-13
### Bug Fixes
- improve error message consistency, context, and safety across all
crates ([#352](#352))
### Features
- add required event_type_name() to Event trait for stable storage
([#344](#344))
- add TestScenario GWT testing helpers to eventcore-testing
([#346](#346))
### Miscellaneous Tasks
- consolidate workspace lints and enforce strict lint policy
([#351](#351))
### Refactoring
- replace into_inner() with into() for nutype domain types
([#334](#334))
- expose projection config via free function API, then reduce public
surface ([#357](#357))
</blockquote>
</p></details>
---
This PR was generated with
[release-plz](https://github.com/release-plz/release-plz/).
Merged
jwilger-ai-bot
pushed a commit
that referenced
this pull request
Apr 17, 2026
## 🤖 New release * `eventcore-macros`: 0.7.0 -> 0.7.1 * `eventcore-types`: 0.7.0 -> 0.7.1 (✓ API compatible changes) * `eventcore-postgres`: 0.7.0 -> 0.7.1 (✓ API compatible changes) * `eventcore-sqlite`: 0.7.0 -> 0.7.1 (✓ API compatible changes) * `eventcore`: 0.7.0 -> 0.7.1 (✓ API compatible changes) * `eventcore-memory`: 0.7.0 -> 0.7.1 (✓ API compatible changes) * `eventcore-testing`: 0.7.0 -> 0.7.1 (✓ API compatible changes) * `eventcore-examples`: 0.7.0 -> 0.7.1 <details><summary><i><b>Changelog</b></i></summary><p> ## `eventcore-macros` <blockquote> ## [0.7.0](eventcore-macros-v0.6.0...eventcore-macros-v0.7.0) - 2026-04-13 ### Bug Fixes - improve error message consistency, context, and safety across all crates ([#352](#352)) ### Features - enhance require! macro to accept typed error values ([#335](#335)) - add required event_type_name() to Event trait for stable storage ([#344](#344)) ### Miscellaneous Tasks - adopt han plugins, blueprints, and project conventions ([#330](#330)) - consolidate workspace lints and enforce strict lint policy ([#351](#351)) ### Refactoring - expose projection config via free function API, then reduce public surface ([#357](#357)) </blockquote> ## `eventcore-types` <blockquote> ## [0.7.1](eventcore-types-v0.7.0...eventcore-types-v0.7.1) - 2026-04-15 ### Bug Fixes - filter read_events by event_type to prevent projection stalls ([#373](#373)) </blockquote> ## `eventcore-postgres` <blockquote> ## [0.7.1](eventcore-postgres-v0.7.0...eventcore-postgres-v0.7.1) - 2026-04-15 ### Bug Fixes - filter read_events by event_type to prevent projection stalls ([#373](#373)) ### Features - add load-testing/stress-testing suite ([#370](#370)) </blockquote> ## `eventcore-sqlite` <blockquote> ## [0.7.1](eventcore-sqlite-v0.7.0...eventcore-sqlite-v0.7.1) - 2026-04-15 ### Bug Fixes - filter read_events by event_type to prevent projection stalls ([#373](#373)) </blockquote> ## `eventcore` <blockquote> ## [0.7.1](eventcore-v0.7.0...eventcore-v0.7.1) - 2026-04-15 ### Bug Fixes - filter read_events by event_type to prevent projection stalls ([#373](#373)) ### Features - add load-testing/stress-testing suite ([#370](#370)) </blockquote> ## `eventcore-memory` <blockquote> ## [0.7.1](eventcore-memory-v0.7.0...eventcore-memory-v0.7.1) - 2026-04-15 ### Bug Fixes - filter read_events by event_type to prevent projection stalls ([#373](#373)) </blockquote> ## `eventcore-testing` <blockquote> ## [0.7.1](eventcore-testing-v0.7.0...eventcore-testing-v0.7.1) - 2026-04-15 ### Features - add load-testing/stress-testing suite ([#370](#370)) </blockquote> ## `eventcore-examples` <blockquote> ## [0.7.0](eventcore-examples-v0.6.0...eventcore-examples-v0.7.0) - 2026-04-13 ### Bug Fixes - improve error message consistency, context, and safety across all crates ([#352](#352)) ### Features - add required event_type_name() to Event trait for stable storage ([#344](#344)) - add TestScenario GWT testing helpers to eventcore-testing ([#346](#346)) ### Miscellaneous Tasks - consolidate workspace lints and enforce strict lint policy ([#351](#351)) ### Refactoring - replace into_inner() with into() for nutype domain types ([#334](#334)) - expose projection config via free function API, then reduce public surface ([#357](#357)) </blockquote> </p></details> --- This PR was generated with [release-plz](https://github.com/release-plz/release-plz/).
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.
Summary
TestScenariotoeventcore-testingwith Given-When-Then fluent APIgiven_events(stream_id, events)seeds precondition events into the storewhen(command)executes a command and returnsScenarioResultfor assertionsScenarioResultprovidessucceeded(),failed_with_business_rule(),then_events(),then_event_count()eventcore-examplesdemonstrate the APIThe "remove fluent StreamWrites API" part of #241 does not apply to the current codebase —
register_stream/appendis the core write mechanism used byexecute().Test plan
Closes #241