The quickcheck-monoid-subclasses
library provides:
- QuickCheck support for testing instances of type classes defined in the
monoid-subclasses
library. - Compatibility with the
quickcheck-classes
library. - Reusable properties for type class laws, in the form of
Laws
definitions.
In general, usage is identical to that of the quickcheck-classes
library. If you're already familiar with quickcheck-classes
, then using this library should be straightforward.
To test that the laws of a particular class hold for a particular type, use the lawsCheck
function with the Laws
definition for the class you wish to test.
To test that the
Monus
laws hold for theSum
Natural
type:import Data.Monoid (Sum) import Data.Proxy (Proxy (Proxy)) import Numeric.Natural (Natural) import Test.QuickCheck.Classes (lawsCheck) import Test.QuickCheck.Classes.Monoid.Monus (monusLaws) lawsCheck (monusLaws (Proxy :: Proxy (Sum Natural)))If all tests pass, you should see output similar to:
Monus: axiom1 +++ OK, passed 100 tests. Monus: axiom2 +++ OK, passed 100 tests. Monus: axiom3 +++ OK, passed 100 tests. Monus: axiom4 +++ OK, passed 100 tests. Monus: stripPrefixOverlap +++ OK, passed 100 tests. Monus: stripSuffixOverlap +++ OK, passed 100 tests.
To test that the laws of multiple classes hold for a particular type, use the lawsCheckOne
function with the Laws
definitions for the classes you wish to test.
To test that the
Sum
Natural
type satisfies the laws ofSemigroup
and its subclasses:import Data.Monoid (Sum) import Data.Proxy (Proxy (Proxy)) import Numeric.Natural (Natural) import Test.QuickCheck.Classes import Test.QuickCheck.Classes.Monoid.GCD import Test.QuickCheck.Classes.Monoid.LCM import Test.QuickCheck.Classes.Monoid.Monus import Test.QuickCheck.Classes.Monoid.Null import Test.QuickCheck.Classes.Semigroup.Cancellative import Test.QuickCheck.Classes.Semigroup.Factorial lawsCheckOne (Proxy :: Proxy (Sum Natural)) [ cancellativeLaws , commutativeLaws , distributiveGCDMonoidLaws , distributiveLCMMonoidLaws , factorialLaws , factorialMonoidLaws , gcdMonoidLaws , lcmMonoidLaws , leftCancellativeLaws , leftDistributiveGCDMonoidLaws , leftGCDMonoidLaws , leftReductiveLaws , monoidLaws , monoidNullLaws , monusLaws , overlappingGCDMonoidLaws , positiveMonoidLaws , reductiveLaws , rightCancellativeLaws , rightDistributiveGCDMonoidLaws , rightGCDMonoidLaws , rightReductiveLaws , semigroupLaws , stableFactorialLaws ]
Each of the Laws
definitions provided by this library corresponds to exactly one type class, and includes just the laws for that class. Laws for subclasses and superclasses are not automatically included. Therefore, you'll need to explicitly test the laws of every single class you wish to cover.
This library includes coverage checks to ensure that important cases are covered, and to reduce the probability of test passes that are false positives. These coverage checks are performed automatically.
To increase coverage of interesting and important cases, this library also checks that laws hold for combinations of generated arbitrary values.
Suppose we are testing the following law:
isPrefixOf a b == isJust (stripPrefix a b)
This library will also test that the following derived laws hold:
isPrefixOf a (a <> a) == isJust (stripPrefix a (a <> a)) isPrefixOf a (a <> b) == isJust (stripPrefix a (a <> b)) isPrefixOf a (b <> a) == isJust (stripPrefix a (b <> a))