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

Check if throws #128

Open
cmeeren opened this issue Oct 10, 2017 · 10 comments
Open

Check if throws #128

cmeeren opened this issue Oct 10, 2017 · 10 comments

Comments

@cmeeren
Copy link
Contributor

cmeeren commented Oct 10, 2017

Is it possible to check if a function throws an exception without having try ... with in the property and explicitly returning true or false?

@moodmosaic
Copy link
Member

Would it be possible to provide an example?

@cmeeren
Copy link
Contributor Author

cmeeren commented Oct 10, 2017

This works, but feels rather heavy-handed:

[<Fact>]
let ``throws if hour is < 0 or > 23`` () =
  Property.check <| property {
    let! dt = Gen.dateTime
    let! hr = Range.linearBounded() |> Gen.int |> Gen.filter (fun hr -> hr < 0 || hr > 23)
    try
      nextOClock hr dt |> ignore
      return false
    with
      :? ArgumentException -> return true
  }

@cmeeren
Copy link
Contributor Author

cmeeren commented Oct 10, 2017

Ideally there'd be some kind of Property.checkThrows<'exn> that I could use. For example:

[<Fact>]
let ``throws if hour is < 0 or > 23`` () =
  Property.checkThrows<ArgumentException> <| property {
    let! dt = Gen.dateTime
    let! hr = Range.linearBounded() |> Gen.int |> Gen.filter (fun hr -> hr < 0 || hr > 23)
    nextOClock hr dt

@moodmosaic
Copy link
Member

What happens when you replace Property.checkThrows<ArgumentException> with Property.check?

@moodmosaic
Copy link
Member

Oh, now I see what you mean; you want the exception to be thrown, and in this case, the property to pass.

@cmeeren
Copy link
Contributor Author

cmeeren commented Oct 10, 2017

👍

@moodmosaic
Copy link
Member

@cmeeren, we recently added an internal function which does what you describe:

/// Converts a possibly-throwing function to
/// a property by treating "no exception" as success.
let internal fromThrowing (f : 'a -> unit) (x : 'a) : Property<unit> =
try
f x
success ()
with
| _ -> failure

AFAICT, this function does exactly what you need. If so, we can make it public in the next release.

@cmeeren
Copy link
Contributor Author

cmeeren commented Nov 13, 2017

No, that does the opposite. It treats throws as failures. I want to test that a function does indeed throw an exception (the test should fail if nothing is thrown). Furthermore, it should check the type of exception (the test should fail if the wrong exception is thrown). And ideally, the user should be able to choose whether it needs to match the exception exactly or if a subclass of the specified exception is fine.

IIRC FsCheck does this nicely.

@moodmosaic
Copy link
Member

moodmosaic commented Nov 13, 2017

OK, then it's the opposite of that function plus pattern matching on the type of exception.

@cmeeren
Copy link
Contributor Author

cmeeren commented Nov 13, 2017

Yes. See my example above for a suggestion of a nice and short syntax:

Property.checkThrows<ArgumentException>

I suggest that the default behavior is that the test passes if ArgumentException or any subclass of ArgumentException is thrown, and fails otherwise. If the user wants the test to pass for only ArgumentException (not a subclass), they can use another function:

Property.checkThrowsExact<ArgumentException>

@ghost ghost added this to the 0.11.0 milestone Jan 31, 2021
@ghost ghost removed this from the 0.11.0 milestone Sep 11, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants