Props Now On PyPI
Props (PyPI, GitHub) provides property-based testing for Python à la QuickCheck.
There are other QuickCheck-like libraries for Python:
However, I’m not sure how to add instances of Arbitrary (in the Haskell sense) for any of them! That’s where Props comes in.
In Haskell’s QuickCheck, Arbitrary is a typeclass:
class Arbitrary a where
arbitrary :: Gen a
Typeclasses are like interfaces, but for types instead of classes. The way to read this definition is “Any class a
which implements the Arbitrary
interface must provide a method arbitrary
which returns a Gen a
.” Think of Gen a
as a container which can be turned into random instances of a
.1 To create new instance of Arbitrary
2:
instance Arbitrary Bool where
arbitrary = choose (False, True)
In Python, we define a class which provides arbitrary
as a classmethod which raises NotImplementedError
since we don’t have interfaces:
class ArbitraryInterface(object):
@classmethod
def arbitrary(cls):
raise NotImplementedError
To implement an instance:
class bool(ArbitraryInterface):
@classmethod
def arbitrary():
return random.choice([False, True])
However, in this case, bool
is already defined, and we do not want to shadow that definition. Classmethods are just functions which dispatch on the type given, so we can define arbitrary somewhat like this3:
arbitrary_dict = {
bool: lambda: random.choice([False, True]),
...
}
def arbitrary(cls):
if issubclass(cls, ArbitraryInterface):
return cls.arbitrary()
return arbitrary_dict[bool]()
This way we can provide implementations of arbitrary for already defined types (either in the standard library or in external libraries) in arbitrary_dict
, and also handle instances of ArbitraryInterface
for our own classes.