target alternatives and similar packages
Based on the "Testing" category.
Alternatively, view target alternatives based on common mentions on social networks and blogs.

curlrunnings
A declarative test framework for quickly and easily writing integration tests against JSON APIs. 
quickcheckarbitraryadt
Typeclass for generating a list of each instance of a sum type's constructors 
testframeworkth
Automagically (using Template Haskell) generates the Haskellcode you need when using HUnit 
tastyantxml
A tasty ingredient to output test results in XML, using the Ant schema. This XML can be consumed by the Jenkins continuous integration framework.
InfluxDB  Power RealTime Data Analytics at Scale
Do you think we are missing an alternative of target or a related project?
README
Target
Target is a library for testing Haskell functions based on refinement type specifications.
Getting Started
First things first, get Target from Hackage
$ cabal install target
You'll also need a recent version of Z3 or CVC4.
Testing with Target
To get acquainted with refinement types and Target, let's examine
a small grading library called Scores
.
First Steps
We'll need to import two modules from Target.
Test.Target
exports the main testing API, and
Test.Target.Targetable
exports the
Targetable
typeclass, which represents types for which we can
generate constrained values. We'll need the latter module for one of
the later examples when we define our own datatype.
module Scores where
import Test.Target
import Test.Target.Targetable
Refinement Types
A refinement type decorates the basic Haskell types with logical predicates drawn from an efficiently decidable theory. For example,
{@ type Nat = {v:Int  0 <= v} @}
{@ type Pos = {v:Int  0 < v} @}
{@ type Rng N = {v:Int  0 <= v && v < N} @}
are refinement types describing the set of integers that are
nonnegative, strictly positive, and in the interval [0, N)
respectively. We will also build up function and collection
types over base refinement types like the above.
Base Types
Let's write a function rescale
that takes a source range [0,r1)
,
a target range [0,r2)
, and a score n
from the source range,
and returns the linearly scaled score in the target range.
For example, rescale 5 100 2
should return 40
.
Here's a first attempt at rescale
{@ rescale :: r1:Nat > r2:Nat > s:Rng r1 > Rng r2 @}
rescale r1 r2 s = s * (r2 `div` r1)
Let's load our code into GHCi and test it!
ghci> :set XTemplateHaskell
ghci> :l Scores.hs
ghci> target rescale 'rescale "Scores.hs"
The main function Target exports is
target
target :: Testable f => f > TH.Name > FilePath > IO ()
which drives the entire testing process. It also provides
targetWith
to customize some of the options, and
targetResult
which returns the test outcome instead of printing it.
(Since the refinement type specifications are given in special comments, we use Template Haskell to give target the exact name of the function we want to test. Unfortunately we can't extract the path to the module from the Template Haskell name, so we have to provide it separately..)
Unfortunately, target quickly responds with
Found counterexample: (1, 0, 0)
Indeed, rescale 1 0 0
results in 0
which is not in the target
Rng 0
, as the latter is empty! We could fix this in various ways,
e.g. by requiring the ranges are nonempty:
{@ rescale :: r1:Pos > r2:Pos > s:Rng r1 > Rng r2 @}
Now, Target accepts the function and reports
ghci> target rescale 'rescale "Scores.hs"
OK. Passed all tests.
Using the refinement type specification for rescale
,
Target systematically tests the implementation by generating
all valid inputs up to a given depth bound (defaulting to 5)
that respect the preconditions, running the function, and
checking that the output satisfies the postcondition.
Containers
Suppose we have normalized all scores to be out of 100
{@ type Score = Rng 100 @}
Now we'll write a function to compute a weighted average of a list of scores.
{@ average :: [(Int, Score)] > Score @}
average [] = 0
average wxs = total `div` n
where
total = sum [w * x  (w, x) < wxs ]
n = sum [w  (w, _) < wxs ]
It can be tricky to verify this function as it requires nonlinear reasoning about an unbounded collection. However, we can gain a great degree of confidence by systematically testing it using the type specification; indeed, Target responds:
ghci> target average 'average "Scores.hs"
Found counterexample: [(0,0)]
Clearly, an unfortunate choice of weights can trigger a dividebyzero; we can fix this by requiring the weights be nonzero:
{@ average :: [({v:Int  v /= 0}, Score)] > Score @}
but now Target responds with
ghci> target average 'average "Scores.hs"
Found counterexample: [(3,3),(3,0)]
which also triggers the dividebyzero! Let's play it safe and require positive weights,
{@ average :: [(Pos, Score)] > Score @}
at which point Target reports that all tests pass.
Ordered Containers
The very nature of our business requires that at the end of the day,
we order students by their scores. We can represent ordered lists by
requiring the elements of the tail t
to be greater than the head h
:
{@ data OrdList a
= ONil
 OCons {h :: a, t :: OrdList {v:a  h <= v}}
@}
Target can only test functions that operate on Targetable
types, so we'll
also need to make OrdList
Targetable
. We could write our own instance, but
they turn out to be quite mechanical, so instead we'll use GHC.Generics
to
derive an instance automatically.
data OrdList a = ONil  OCons a (OrdList a)
deriving Generic
instance Targetable a => Targetable (OrdList a)
We can now write a function to insert a score into an ordered list:
{@ insert :: (Ord a) => a > OrdList a > OrdList a @}
Target automatically generates all ordered lists (up to a given depth)
and executes insert
to check for any errors.
Structured Containers
Everyone has a few bad days. Let us write a function that takes the
best k
scores for a particular student. That is, the output
must satisfy a structural constraint  that its size
equals k
. We can encode the size of a list with a logical
measure function:
{@ measure len :: [a] > Int
len [] = 0
len (x:xs) = 1 + len xs
@}
Now, we can stipulate that the output indeed has k
scores:
{@ best :: k:Nat > [Score] > {v:[Score]  k = len v} @}
best k xs = take k $ reverse $ sort xs
Now, Target quickly finds a counterexample:
ghci> target best 'best "Scores.hs"
Found counterexample: (2,[])
Of course  we need to have at least k
scores to start with!
{@ best :: k:Nat > {v:[Score]  k <= len v}
> {v:[Score]  k = len v}
@}
and now, Target is assuaged and reports no counterexamples.
Note that we don't have to write a custom Targetable
instance
to generate lists of a specific length, the standard one suffices!
Higherorder Functions
Perhaps instead of taking the k
best grades, we would like
to pad each individual grade, and, furthermore, we want to
be able to experiment with different padding functions. Let's
rewrite average
to take a functional argument, and
stipulate that it can only increase a Score
.
{@ padAverage :: (s:Score > {v:Score  s <= v}) > [(Pos, Score)] > Score @}
padAverage f [] = f 0
padAverage f wxs = total `div` n
where
total = sum [w * f x  (w, x) < wxs ]
n = sum [w  (w, _) < wxs ]
Target automatically checks that padAverage
is
a safe generalization of average
. Randomized
testing tools can also generate functions, but those
functions are unlikely to satisfy nontrivial constraints,
thereby burdening the user with custom generators.
Moving On
You can specify a lot of interesting properties with refinement types and we've only scratched the surface here. Check out the LiquidHaskell blog for more examples; Target uses the same specification language as LiquidHaskell so the examples should all be testable.