Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Iterable assertion builder with constraint-based order matching #302

Open
wants to merge 7 commits into
base: main
Choose a base branch
from

Conversation

DSteve595
Copy link

@DSteve595 DSteve595 commented Aug 3, 2024

I've come across a few test scenarios where I want to assert ordering on an iterable, but contains, containsExactly, and containsExactlyInAnyOrder don't quite cut it. Two particular cases that come to mind are asserting lifecycle callbacks and asserting connection state. What they have in common is that some aspects of their order matter, but not all.

I've generally gone about solving these cases by either mangling the result list before asserting on it (e.g. filtering or reordering elements), or creating a combinatorial explosion of valid results and asserting that the result is one of them. Both leave my tests a lot uglier than I'd like.

This is my take on an assertion builder for iterables that can assert fuzzy ordering rules.
The API is a block in which the user asserts elements in the subject, and constraints for those elements' positions relative to other elements.

Here's an example of its usage, illustrating my most recent use case:

enum class LifecycleCall { Created, Started, Stopped, Destroyed, Attached, Detached }

/**
 *  Assert that:
 *  - Created comes first
 *  - Destroyed comes last
 *  - In between Created and Destroyed, we get Started and Stopped
 *  - Attached comes after Created, but it doesn't matter if it's before or after Started
 *  - Detached comes before Destroyed, and after Attached,
 *    but it doesn't matter if it's before or after Stopped
 */
@Test
fun properLifecycleCallsAfterStartAndStop() {
  val result = thingWithLifecycle.collectLifecycleCalls()
  expectThat(result)
    .containsWithOrderingConstraints {
      expect(Created).first()
      expect(Started)
        .after(Created)
      expect(Attached)
        .before(Stopped)

      // About to stop
      expect(Detached)
        .after(Attached)
      expect(Stopped)
        .after(Started)
      expect(Destroyed).last()
    }
}

I realize this is a rather opinionated addition to the assertion library, so if this isn't a good fit, feel free to close.

@DSteve595 DSteve595 force-pushed the ordering-constraints branch from f3c9e82 to 9d78529 Compare August 5, 2024 20:22
@robfletcher
Copy link
Owner

That's neat. I dig it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants