packages feed

extrapolate-0.2.0: README.md

Extrapolate
===========

[![Extrapolate Build Status][build-status]][build-log]
[![Extrapolate on Hackage][hackage-version]][extrapolate-on-hackage]

Extrapolate is a [property-based testing] library for [Haskell]
capable of reporting generalized counter-examples.


Installing Extrapolate
----------------------

To install the latest version of [Extrapolate from Hackage] using [cabal], just:

	$ cabal update
	$ cabal install extrapolate

To test if it installed correctly, follow through the next section.


Using Extrapolate
-----------------

To use Extrapolate, you first import the [`Test.Extrapolate`] module,
then pass any properties you with to test to the function [`check`]:

	$ ghci
	> import Test.Extrapolate
	> check $ \x y -> x + y == y + (x :: Int)
	+++ OK, passed 360 tests.

	> import Data.List (nub)
	> check $ \xs -> nub xs == (xs :: [Int])
	*** Failed! Falsifiable (after 3 tests):
	[0,0]

	Generalization:
	x:x:_

The operator [`+`] is commutative.  The function [`nub`] is not an identity.


### Configuring the number of tests

To increase the number of tests, use the [`for`] combinator:

	$ ghci
	> import Test.Extrapolate
	> check `for` 1000 $ \x y -> x + y == y + (x :: Int)
	+++ OK, passed 1000 tests.


### Customizing the background functions (allowed in side-conditions)

To customize the background functions, use the [`withBackground`] combinator:

	$ ghci
	> import Test.Extrapolate
	> import Data.List (nub)
	> let hasDups xs  =  nub xs /= (xs :: [Int])
	> check `withBackground` [constant "hasDups" hasDups] $ \xs -> nub xs == (xs :: [Int])
	*** Failed! Falsifiable (after 3 tests):
	[0,0]

	Generalization:
	x:x:_

	Conditional Generalization:
	xs  when  hasDups xs

Perhaps the example above is silly (`hasDups` is the negation of the property
itself!), but it illustrates the use of [`withBackground`].


The combinators [`for`] and [`withBackground`] can be used in conjunction:

	> check `for` 100 `withBackground` [...] $ property

Don't forget the dollar sign [`$`].


Another Example
---------------

Consider the following (faulty) sort function and a property about it:

    sort :: Ord a => [a] -> [a]
    sort []      =  []
    sort (x:xs)  =  sort (filter (< x) xs)
                 ++ [x]
                 ++ sort (filter (> x) xs)

    prop_sortCount :: Ord a => a -> [a] -> Bool
    prop_sortCount x xs  =  count x (sort xs) == count x xs
      where
      count x = length . filter (== x)

After testing the property, Extrapolate returns a fully defined counter-example
along with a generalization:

    > import Test.Extrapolate
    > check (prop_sortCount :: Int -> [Int] -> Bool)
    *** Failed! Falsifiable (after 4 tests):
    0 [0,0]

    Generalization:
    x (x:x:_)

This hopefully makes it easier to find the source of the bug.  In this case,
the faulty sort function discards repeated elements.


Further reading
---------------

For more examples, see the [eg](eg) folder.
For type signatures, other options and uses,
see [Extrapolate's API documentation].

[extrapolate-on-hackage]:          https://hackage.haskell.org/package/extrapolate
[Extrapolate from Hackage]:        https://hackage.haskell.org/package/extrapolate
[Extrapolate's API documentation]: https://hackage.haskell.org/package/extrapolate/docs/Test-Extrapolate.html
[`Test.Extrapolate`]:              https://hackage.haskell.org/package/extrapolate/docs/Test-Extrapolate.html
[`check`]:                         https://hackage.haskell.org/package/extrapolate/docs/Test-Extrapolate.html#v:check
[`for`]:                           https://hackage.haskell.org/package/extrapolate/docs/Test-Extrapolate.html#v:for
[`withBackground`]:                https://hackage.haskell.org/package/extrapolate/docs/Test-Extrapolate.html#v:withBackground
[`$`]:                             https://hackage.haskell.org/package/base-4.10.0.0/docs/Prelude.html#v:-36-
[`+`]:                             https://hackage.haskell.org/package/base/docs/Prelude.html#v:-43-
[`nub`]:                           https://hackage.haskell.org/package/base/docs/Data-List.html#v:nub
[Haskell]:                         https://www.haskell.org/
[cabal]:                           https://www.haskell.org/cabal/
[property-based testing]:          https://github.com/rudymatela/leancheck/blob/master/doc/tutorial.md

[build-status]:    https://travis-ci.org/rudymatela/extrapolate.svg?branch=master
[build-log]:       https://travis-ci.org/rudymatela/extrapolate
[hackage-version]: https://img.shields.io/hackage/v/extrapolate.svg