This post announces the new genvalidity-hspec-optics
test-suite combinator library.
It is a new companion package for genvalidity-hspec
and contains test-suite combinators for testing optics.
Background
Lenses, as specified in Control.Lens.Lens have laws. They are specified as follows:
- Law 1: You get back what you put in:
view l (set l v s) == v
- Law 2: Putting back what you got does not change anything:
set l (view l s) s == s
- Law 3: Setting twice is the same as setting once:
set l v' (set l v s) = set l v' s
Contents
The new genvalidity-hspec-optics
library has the following test-suite combinators for lenses:
- lensSpec: A test suite combinator for the lens laws of a lens, for unchecked values.
- lensSpecOnValid: A test suite combinator for the lens laws of a lens, for valid values.
- lensSpecOnArbitrary: A test suite combinator for the lens laws of a lens, for arbitrary values.
- lensSpecOnGen: A test suite combinator for the lens laws of a lens, for values generated by custom generators.
That means that now you can test whether your lenses follow the lens laws with a single line of code.
Example
Suppose you have a simple record, with two fields and two corresponding lenses:
data MyRecord = MyRecord
{ myBool :: Bool
, myRational :: Rational
}
myBoolLens :: Lens' MyRecord Bool
myRationalLens :: Lens' MyRecord Rational
Now you can write a very simple property test suite using genvalidity-hspec-optics
that test whether the lenses follow the lens laws, and are otherwise sensible.
import Test.Validity.Optics
spec :: Spec
spec = do
describe "myBoolLens" $
lensSpec myBoolLens -- For any unchecked value, prefer this version if you can.
describe "myRationalLens" $
lensSpecOnValid myRationalLens -- Only for valid values
Running the test suite gets you pretty output as follows:
myBoolLens
satisfies the first lens law for unchecked values and unchecked values
satisfies the second lens law for unchecked values
satisfies the third lens law for unchecked values and unchecked values
gets valid values from unchecked values values
produces valid values when it is used to set unchecked values values on unchecked values values
myRationalLens
satisfies the first lens law for valid values and valid values
satisfies the second lens law for valid values
satisfies the third lens law for valid values and valid values
gets valid values from unchecked values values
produces valid values when it is used to set unchecked values values on unchecked values values