-
Notifications
You must be signed in to change notification settings - Fork 157
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
Improve interaction with Unquote #130
Comments
Great idea. This would probably work even better with the automatic quoting of arguments introduced in F# 4.
|
The combination of FsCheck and Unquote is fantastic! I use it all the time. What do you need that isn't already possible? Here's a test that combines the two: [<Property>]
let ``run returns StoppedState when it occurs`` (states : State list) =
states |> List.exists isStopped ==> lazy
let actual : State = run states
let expected = states |> List.find isStopped
expected =! actual This test uses the FsCheck.Xunit Glue Library, and Unquote, which you can see in action because of the If I change the function being tested so that the test fails, I get output like this when I run the property:
(This particular test is taken from my Type-Driven Development with F# Pluralsight course, which contains more than an hour of footage showcasing the combination of FsCheck and Unquote.) What more do you need? I'd consider it a poor idea to do anything in FsCheck that explicitly couples it to any other library (even one as excellent as Unquote), but if it's possible to do it in a way where the FsCheck library (think: the NuGet package) is still independent of Unquote, it'd be fine. Adding a hypothetical FsCheck.Unquote Glue Library wouldn't hurt, then, but I wonder what it would add... |
Wouldn't you somehow want the whole property (i.e. in your example, everything inside your outer let) passed into Unquote so it could analyze as a whole? @ploeh why would you dislike taking a dependency on Unquote - do you feel like it's shoving it down the user's throat? Must admit I have a soft spot for this, before Unquote existed I started on something similar on my own but never got nearly as far as Unquote. |
If you add Unquote as a dependency to FsCheck, kittens will die 🙀 With a high-quality library, this can be a difficult point to make, but consider this:
Why not add both NUnit and xUnit to FsCheck itself? I hope the answer to this question is obvious. Some users of FsCheck may not want Unquote. What if people for some unconceivable reason want to use something else? What if development of Unquote stops? This may seem like a moot point at the moment, because with its minimal API, Unquote already feels quite done. Still, things may happen in the future that requires further development. As an example, does Unquote work on .NET Core? Who knows? It's not done yet. This is only an example of the sort of trouble taking a dependency can get you into. What if someone wants to use FsCheck, but together with some other library that indirectly depends on Unquote? This could lead to dependency hell if the version of Unquote that library depends on is incompatible with the version of Unquote FsCheck depends on. As I commented above, I wouldn't mind adding a new FsCheck.Unquote Glue Library, but I think it would be a grave mistake adding Unquote (or any other non-essential dependency) to FsCheck itself. It's basic library dependency hygiene. That said, I also don't understand what this particular suggestion adds that not already possible, but that just me being dim, I suppose. |
Yes, point(s) taken. I don't think a separate glue library is really an option either though, because now you get into combinatorial dependency hell, e.g. I want to use FsCheck with both xunit and Unquote, so now I need to install FsCheck.Xunit and FsCheck.Unquote. And maybe some of the glue libraries have integration amongst themselves, so then should we create FsCheck.Xunit.Unquote? Madness. Incidentally, Unquote itself afaik detects dynamically whether xunit et al are loaded and then uses the appropriate assert. I.e. without actually taking a static dependency. Sounds pretty brittle though. I've also thought a bit more about using the auto-quoting feature in F# 4, but it can only be used on methods, so presumably an overload method on the Also another suggestion in this vein I've heard before is to make the So with all that I am now inclined to close this as "nothing much to do", unless @cloudRoutine would like to provide more specific use cases? Again on the whole I really like Unquote and would be happy to make changes to make it easier to use with FsCheck. I'm just having trouble finding something to do :) |
That precisely describes the situation we have with AutoFixture. You can for example combine AutoFixture.Xunit with AutoFixture.AutoMoq. This works extremely well; I've never had any problems with this. AutoFixture offers a lot of packages you can choose and combine as you like it: https://github.com/AutoFixture/AutoFixture#downloads Some of those packages are more than four years old. My experience with this design has been overwhelmingly positive. |
Sorry if I'm being a pest about this, but it's only because I like FsCheck so much that I care so much 😳 |
I've been trying out some of Unquote's operators like @ploeh suggested, but the results are mixed. e.g. -
I'm really not sure how to approach this but I'll take a shot in the dark. It might be possible to do it as a kind of glue library/ plugin if FsCheck was tweaked a bit. Instead of having It might be "useful" in general to have FsCheck output data structures containing the values involved in its tests (generated arguments, labels, classifications, collected data values, observations, etc.) so that it could function as a part of a pipeline, sending stuff into a logging system, a charting/visualization system, a fitness function for a genetic algorithm, storing results of complex test with a low probability of failure in a database like Hypothesis , or whatever other esoteric uses people conjure up. |
Interesting, not sure what happened there. It occurs to me I probably haven't actually used vanilla FsCheck with just Unquote (at least not that I can remember), so it looks like something in the interaction between FsCheck and Unquote gets confused. I am definitely interested in an exploration of what is going wrong there. I also like your idea of having |
I also see FsCheck as the main/core library exposing the basic building blocks for other Glue Libraries (e.g. FsCheck.Xunit, a hypothetical FsCheck.Unquote, and so on). In fact, it's awesome that xUnit.net1, FsCheck, and Unquote can all work autonomously:
Does FsCheck needs Unquote to work? – Not really, as far as I can tell... 1And also NUnit |
I can't reproduce what you are getting with the property there. When I run it as is, the output is:
Also, the operators are applied after quoting, in other words, Unquote doesn't see the quoted arguments. It's easy to improve things at the expense of some speed though:
And now you get the reduction that makes Unquote so useful (although a bit silly in this example):
So that all plays pretty well with FsCheck. If you wanted something like being able to see the whole body of |
I am going to close this; note that the aspect of having FsCheck output data structures as a result of test (effectively, re-think the way the runner works) is captured in the FsCheck 3.0 issue #198. I'm unclear if this contains anything else that is unresolved. Upon re-reading, I couldn't remember why I kept it open, seems to me like the interaction with Unquote is as expected. Feel free to re-open and clarify if I missed anything. |
FsCheck and Unquote are by far my favorite testing libraries and it would be great if it were easier to use the two of them together.
It seems like it'd be possible to pass the args returned by a failing case to the property inside a quotation and return the unquoted evaluation as part of the failure message.
An
?unquote:bool
optional parameter could be added toCheck
's methods, or a newUnquoteCheck
class could be added with the same methods asCheck
The text was updated successfully, but these errors were encountered: