-
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
Convention-based Arbitrary registration #334
Comments
I empathize with the suggestion. I'd like to understand how this would improve things over using Especially interested in how you estimate the cost of adding another way to do the same thing compared to its convenience and applications. One seeming restriction of the above approach is that it would not work if you want to define an Also consider we'd need to define how the different ways of associating an |
You always do a good job making me question my own ideas 😳 It's always good with some feedback, because one can quickly get into a rut if only thinking about things for oneself. I do have a bit of a roundabout motive for this suggestion, but perhaps there are other ways to address them as well. I'll get back to that later... I no longer use the part of the FsCheck API that relies on That also partly explains my dislike for In any case, I thought you wanted to get rid of that as well, but perhaps I misunderstood your paragraph about that in #198? In any case, coming back to my actual motivation for this: It'd be nice to be able to design a mechanism for Arbitrary discovery that's a bit more flexible than the current. My problem today is actually mostly with the FsCheck source code itself. As you know. I'm attempting to add support for The above suggestion is an attempt at addressing this problem, because it might enable us to move many of the above-mentioned 'signal' types to later in the code base. Perhaps there's another way; if there is, I'd be happy to hear about it. |
Thanks very much for that. I'm trying to not be so vocal about my a priori opinions on things. I have been playing that game for so long, and it mostly ends up with everyone in their corner refusing to come out... Anyway.
Agree - this is a worrying part of the code.
Exactly. This already bit us: I made the arbitrary instances thread local. I also didn't feel "safe" accepting a PR to add some support for async, because it was unpredictable how the
You didn't, although for that I was more focused on getting rid of the global mutable
That is true, though I must say that the But I do still like the suggestion. I think actually if we can make the end-game I described above for fscheck 3 work, this kind of feature would be a no-brainer. |
Couldn't this be done using the State monad?
I think you have 😲 The list of cultures, as well as the list of top-level domain names, is not it What bothers me about the size of The fact that I'm working on a four-year old laptop with F# Power Tools in Visual Studio means that I can actually feel that the computer is struggling to keep up with a largish F# code base. I don't think my computer would be able to deal with a 40 kLoC code base at all... There's also the concern that larger code files could scare away potential new contributors. On the other hand, if the F# compiler has 40 kLoC files, that concerns is most likely unfounded - AFAICT, there are plenty of contributors to that. |
I know this is an old issue entry but I'm looking for a solution to pre-define arbitraries for my own types (and could not find anything for that within docs / issues so far). Here's my use case and some ideas to solve this (and I hope that this is a valid issue to add this): I have a classlib A with one or more custom types, packaged via nuget. Could be something like I have another project B where I use those types. My favorite solution would be that the pre-defined arbitrary from that other packages is automatically used (when not overridden) for any property based test using this type. From what I know currently I need to do two things:
Ideas to solve the first issue: a) Fiddle with something like b) Use something like duck typing If this is interesting then one would need to define the allowed signature(s). Maybe we should use instance methods here to allow creating generators elsewhere using extensions methods (not sure, whether they can be found by reflection). Second issue (avoid registering / using default Edit: (if realized this way) I would expect that I could even have generic types in my package (classlib A) like PS: Thanks to all contributors / creators of this great library. |
For problem 1
How about creating a separate "test support" NuGet package which depends on package A and FsCheck? No matter the structure, the question I guess is always how do you make it so that the For these reasons for a long time I've wanted to move to a more explicit mechanism. This is slightly more work on the test side, i.e. for the |
Thanks for your answer. Ok, I see the point of the extra package (which probably is worth going this way). For problem 2 (resolving): Generally I don't like "automagic" and IMO being type-safe, explicit, dependency-free etc. is a good thing. I'm not sure whether this approach "scales". What if all built-in types would need this explicit declarative approach, too? Which are the problems of automagic: Values get created and you don't know why / maybe is inconsistent You don't know which generator is used More work to create companion package Having some extra generator package (I don't see a big problem that mechanism within the Just my two cents as an FsCheck user. Please don't see this as request, just want to add some thoughts from a consumer / type creator perspective. Happy holidays, everyone. |
Since this is really constructing a type to function mapping, it's instructive to look at what other languages have done in this space - the "orphan rules". For example, in Rust, traits can only be implemented if either the trait or the type is local to the crate. A mechanism where default An equivalent mechanism for FsCheck, that also takes into account the desire to not have a dependency on FsCheck in the "real" assembly, could look something like this:
Note however that this includes a pretty significant amount of magic. For example, how does FsCheck let the user know that it looked for an assembly with |
FsCheck's current architecture gives preferential treatment of the built-in Arbitraries in
Arb.Default
. This extends to the built-in 'signal' types, likeNonNegativeInt
,PositiveInt
,NonNull
,NonEmptySet
, etc.Such 'signal' types are invaluable because they enable one to declaratively state that a value should be constrained in some way.
In a
gen
expression, one can write:With FsCheck.Xunit (and, I suppose, FsCheck.NUnit) one can likewise pattern match in the test function itself:
Unfortunately, as useful as that is, one is constrained to those 'signal' types that ship with FsCheck itself. Imagine, for example, that I have a need for generating a string between 1 and 32 characters.
It'd be trivial for me to create a single-case discriminated 'signal' type in my test, but even if I define a generator (or Arbitrary) for it, I can't use it in the same way as above. (Well, perhaps I could if I'd be willing to entertain the idea of using
Arb.register
, but I don't think that's a proper alternative.)I'd like to suggest a convention-based approach instead. If a requested type has a static member that returns an Arbitrary of that type, then use that Arbitrary.
For the above example, it could look like this:
Whenever asked for an instance of the
ShortString
type, FsCheck would look for, and find, theArb
method, and use the Arbitrary returned by the method.This could also replace much of the internal implementation that currently relies on
Arb.Default
...The text was updated successfully, but these errors were encountered: