Announcing genvalidity-hspec-optics

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
Previous
Announcing exchangerates

Start your Haskell project from a template

Haskell templates
Next
Speaking