fast-check
fast-check copied to clipboard
Arbitraries for Symbols
🚀 Feature Request
Symbol is one of the native data types in JavaScript, so it would be nice to have some arbitraries for them. It's easy enough to compose them with the existing primitives, but nevertheless, I think it would be nice to have them built-in to fast-check.
I'm thinking that two arbitraries would suffice. One for symbols created with the Symbol
constructor and one for globals created with Symbol.for
.
Similarly, it would be great if fc.anything()
could create them (perhaps with a withSymbol
option, similarly to BigInts, Maps and Sets).
Motivation
Right now, I'm writing property tests for an isEquals
-type function, and having symbols wired to fc.anything()
would make the code cleaner.
Would definitely be a good idea!
I see at least 7 missing arbitraries or options:
- one for unique symbols - one using
Symbol()
1 - one for named symbols - one using
Symbol.for()
- support for
symbol
as keys forrecord
- an option in
anything
to generatesymbol
- an option in
dictionary
to generatesymbol
as possible keys - an option in
anything
(or the same as above) to generate objects havingsymbol
as possible keys - support for
symbol
as keys forrecord
- https://github.com/dubzzz/fast-check/issues/240
1 If we use this one when talking about symbols as keys of objects we will never be able to recreate twice the same value. Maybe we should have a flag withUniqueSymbol
too 🤔 Today with fc.dedup(fc.anything(), 2)
we can create twice the same instance in terms of equality (not ===
but deeply equal). We would need to think about ways (if feasible) to achieve that with this arbitrary based on Symbol()
.
One problem with generators for symbols is that they are inherently leaky - generating a symbol consumes space irrecoverably
Having a very large set of symbols generated can bring v8 to its knees
A more severe example of this is when erlang quickcheck was new, they tried to offer a generator that'd make atom
s, which are roughly analogous to symbols. The thing is, breaking the one million line will halt an erlang VM, so, they had to take that back out, and start only generating existing ones rather than novel ones
Another is that a lot of Javascript's internals are implemented in terms of symbols now, so if you chose to iterate the global symbol registry, you'd end up firing prototype[@@toPrimitive]
, or species
, or unscopables
, which could break the test rig in action and invalidate other results silently, which would be bad.
The way around this would be to use local symbols and .getOwnPropertySymbols
, but that would fail to catch things involving the global registry, which is a lot of what people use Symbol
for, or to try to manually screen defined symbols, because I don't think vanilla has a way to separate Well Known Symbols from stuff the programmer made up
You can't really just make a list of @@unscopables
and so on because the browsers are free to make their own, and do, and there's no guaranteed namespace or naming pattern, nor a method for distinguishing their nativity
As a symbol generator does not seem that simple to make re-usable, let's close that ticket for now. It's still feasible on user-land to create such generator if needed and tailor it for the exact needs of the user.
My current idea with the feature was to generate symbols using Symbol(label)
and Symbol.for(label)
but they might not be that useful for most users. Most users might one to have very precise symbols and not fully random ones.