Skip to content

Add wantCase and isCase to Expect module#526

Merged
farlee2121 merged 3 commits into
haf:mainfrom
jwosty:want-case
Dec 15, 2025
Merged

Add wantCase and isCase to Expect module#526
farlee2121 merged 3 commits into
haf:mainfrom
jwosty:want-case

Conversation

@jwosty

@jwosty jwosty commented Dec 3, 2025

Copy link
Copy Markdown
Contributor

Adds two helper functions (wantCase and isCase) to simplify extracting and matching a case of a discriminated union, along with flipped versions. This is accomplished via code quotations, similar to Argu's approach in GetResult for matching and extracting case data.

This lets you write things like:

type MyDu = | SomeCase of string * string | SomeOtherCase of int

testCase "some test case" (fun () ->
    let actual = SomeCase ("foo", "bar")
    let (string1, string2) = Expect.wantCase actual <@ SomeCase @> "test message"
    // then do stuff with string1 and string2
)

instead of the cumbersome:

type MyDu = | SomeCase of string * string | SomeOtherCase of int

testCase "some test case" (fun () ->
    let actual = SomeCase ("foo", "bar")
    match actual with
    | SomeCase (string1, string2) -> // ...
    | _ -> failtestf "Expected SomeCase, was %A" actual
)

I have been using this in my own test suite recently and figured this could be a useful addition to the library.

NOTE: it would be nice to be able to use [<ReflectionDefinition>] on it so that the user doesn't have to wrap it in an explicit quotation (i.e. SomeCase instead of <@ SomeCase @>), but unfortunately this is only supported in methods, not functions, and I didn't want to break from the established pattern. But I am open to ideas.

@farlee2121

Copy link
Copy Markdown
Collaborator

Hmm. I agree keeping these as functions with quotations over methods with ReflectionDefinition feels like the right call.

I'm ok with merging this, unless you had some ideas you wanted to discuss?

@farlee2121

Copy link
Copy Markdown
Collaborator

It's worth noting that F# unions now have built-in properties for determining if a value belongs to a certain case.

An existing alternative to isCase would be something like this

type Answer = Yes | No

...

let actual = Answer.Yes

Expect.isTrue actual.IsYes "should be yes"

This doesn't help with unwrapping, and I think there's a style/readability argument for isCase.

@jwosty

jwosty commented Dec 15, 2025

Copy link
Copy Markdown
Contributor Author

This doesn't help with unwrapping, and I think there's a style/readability argument for isCase.

Right - and the main argument IMO is that you get nicer error messages out of the test with isCase.

I'm happy with it as is if nobody has any objections or ideas for further improvement.

@farlee2121 farlee2121 merged commit f1422f3 into haf:main Dec 15, 2025
2 checks passed
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