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 aTypeclasses 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 Arbitrary2:
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 NotImplementedErrorTo 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.
kms