# tasty: one test tree for Haskell unit, golden and property tests

> tasty is a Haskell testing framework that puts unit tests, golden tests and QuickCheck or SmallCheck properties into a single test tree, runs them in parallel while reporting in a fixed order, and lets you add your own providers and ingredients.

**UnkindPartition/tasty** — Modern and extensible testing framework for Haskell

- Repository: https://github.com/UnkindPartition/tasty
- Stars: 661 · Forks: 123
- Language: Haskell
- License: not declared
- Published: 2026-10-21 · Updated: 2026-10-21 · Language: en
- Canonical page: https://hysenlabs.com/projects/unkindpartition-tasty

## A test tree that mixes test styles

The idea behind tasty is a single suite. A project that has HUnit cases, golden tests and QuickCheck or SmallCheck properties normally ends up with several runners and several output formats, and a build script that invokes all of them. tasty replaces that with one test tree, a group of providers that contribute the tests, and a group of ingredients that decide what to do with the tree. The core package on Hackage, called tasty, holds the basic definitions and APIs and a console runner, and it is not enough on its own. As the documentation puts it, to create a test suite you also need to install one or more providers. The repository reflects that split, with the core implementation in core/, its tests in core-tests/, and separate directories for the hunit, quickcheck and smallcheck integrations.

## Parallel execution with a deterministic report order

The first feature in the list is the one that changes how a suite feels. Tests run in parallel, but the results are reported in a deterministic order. Without that property, a suite that runs its cases concurrently produces output that changes from run to run, which makes a failing test hard to find in a log and makes golden output comparisons unreliable. tasty separates the two concerns: the schedule is parallel, the presentation is not. Alongside that there is filtering of the tests to be run using patterns specified on the command line, a hierarchical and coloured display of the results, and reporting of test statistics. The options section adds that the run-time behaviour is customised through options, including the mode of operation, whether to run the tests, list the test names, or run them quietly.

## Ingredients are the actions applied to your suite

Ingredients are the other half of the model. An ingredient represents an action that can be performed on the test suite, and the obvious one is the ingredient that runs the tests and reports progress and results, while another standard one simply prints the names of all the tests. Beyond those, the documentation lists ingredients that change how results leave the suite. tasty-ant-xml writes the results in a machine-readable XML format understood by various CI systems and IDEs. tasty-rerun adds support for minimal test reruns by recording previous test runs and using that information to filter the test tree, so you can run only the failed tests or only the tests that threw an exception. tasty-html writes the results as an HTML file, and tasty-stats collects statistics about the suite into a CSV file. Ingredients are also extensible, through the API in Test.Tasty.Runners.

## Providers: one package per style of test

Providers supply the tests themselves, and the ecosystem is broad. tasty-hunit covers unit tests based on HUnit. tasty-golden covers golden tests, which are unit tests whose results are kept in files. tasty-smallcheck provides exhaustive property-based testing on top of smallcheck, while tasty-quickcheck and tasty-hedgehog provide randomized property-based testing on top of QuickCheck and Hedgehog respectively. tasty-hspec runs Hspec tests, tasty-leancheck covers enumerative property-based testing, and tasty-program runs an external program and checks whether it terminates successfully. There are narrower ones: tasty-wai for testing wai endpoints, tasty-inspection-testing for compile-time testing of code properties, and tasty-flaky, which adds delay and retry logic to any test known to fail intermittently. Custom providers are written against the API in Test.Tasty.Providers, so a house style of test can be packaged once and reused.

## Resources acquired once and shared by several tests

One feature is easy to overlook and hard to do without. tasty can acquire and release resources, such as sockets and temporary files, that are shared among several tests. In a Haskell project, a test that needs a listening socket or a scratch directory usually ends up with a bracket in every single test, or with a global that is never cleaned up. Sharing the resource through the framework means the setup and teardown live in one place, and the tests that need it declare that they need it. That is a small feature on paper and a meaningful reduction in duplication in a suite that starts a server for a group of tests.

## Test discovery, or writing the tree by hand

By itself tasty forces you to write out the TestTree explicitly, which is the traditional Haskell style and gives you complete control over grouping and ordering. If you would rather not, three packages write tests at the top level and collect them into a single TestTree automatically: tasty-th, tasty-discover and tasty-autocollect. For code that already has tests, tasty-hunit-adapter converts existing HUnit test suites into tasty test suites, which is the migration path for a project that wants one runner without rewriting its cases. The documentation also lists tasty-expected-failure, which provides test markers for when you expect failures or want to ignore a test, and tasty-bench, which covers performance regression testing and extends tasty into a benchmark framework similar to criterion and gauge.

## Writing a test.hs and running it

The example in the documentation shows the shape of a test file. The imports pull in the core module, SmallCheck and QuickCheck as providers, and HUnit, and the entry point hands the tree to the runner:
```haskell
main = defaultMain tests

tests :: TestTree
tests = testGroup "Tests" [properties, unitTests]
```
Below that, properties are grouped the same way, and unit tests are written as ordinary HUnit cases:
```haskell
unitTests = testGroup "Unit tests"
  [ testCase "List comparison (different length)" $
      [1, 2, 3] `compare` [1,2] @?= GT
```
The example deliberately includes a property that does not hold, and the documentation notes that whether QuickCheck finds a counterexample to that third property is determined by chance, which is a fair description of randomised testing in general. What to read from the example is the grouping. A property group and a unit test group sit side by side in the same tree, and the runner reports them in the same output.

## Where tasty is the wrong tool

Two boundaries stand out. The first is dependency count. The core package is a framework, not a test library, so a project that only wants HUnit cases ends up depending on tasty, tasty-hunit and a runner, where a plain HUnit setup would have needed one package. The pay-off appears when a project actually mixes styles, and the cost is paid whether or not you do. The second is the release story. The repository has no GitHub releases, and the documentation points to the change log inside the core package for what is new, so version tracking happens at the Hackage level rather than through tagged releases. On a project where the test framework version is pinned across a large workspace, that difference is real. Neither point is a reason to avoid tasty, but both are reasons to pin the version deliberately instead of accepting whatever the solver picks.

## Conclusion

tasty fits Haskell projects that already mix HUnit cases with QuickCheck or SmallCheck properties, or that want golden tests and property tests in the same run, and that value a runner where parallel execution does not scramble the output. It does not fit a team that wants a single dependency with no provider packages, nor a project that relies on a stable release cadence, since the repository publishes no GitHub releases and the change log lives in the core package. Before adopting it, read core/CHANGELOG.md for the version you intend to pin, decide whether you will use tasty-discover or an explicit TestTree, and check that the provider you need is on Hackage rather than planned, because the core package alone runs nothing.

## FAQ

### What is tasty and what kinds of test can it combine?

tasty is a modern testing framework for Haskell that lets you combine unit tests, golden tests, QuickCheck or SmallCheck properties and other kinds of test into a single test suite, with parallel execution, deterministic reporting order and command line pattern filtering.

### Which providers does tasty have?

The providers include tasty-hunit for unit tests, tasty-golden for golden tests, tasty-smallcheck, tasty-quickcheck and tasty-hedgehog for property-based testing, tasty-hspec, tasty-leancheck, tasty-program, tasty-wai, tasty-inspection-testing and tasty-flaky.

### How do I run only part of a tasty test suite?

You filter the tests with patterns given on the command line. There are also ingredients for more: tasty-rerun records previous test runs and uses that information to filter the tree, so you can run only the failed tests or only the ones that threw an exception.

### Can tasty run my existing HUnit tests?

Yes. The tasty-hunit-adapter package converts existing HUnit test suites into tasty test suites, and the tasty-hunit provider is the one that supplies HUnit style unit tests to a tasty tree.

### What is the difference between a provider and an ingredient in tasty?

A provider supplies tests, and an ingredient is an action performed on the test suite, such as running the tests or writing the results as XML, HTML or CSV. Both are extensible, through the APIs in Test.Tasty.Providers and Test.Tasty.Runners.

## Sources

- [Issues](https://github.com/UnkindPartition/tasty/issues)
- [README](https://github.com/UnkindPartition/tasty/blob/master/README.md)
- [UnkindPartition/tasty on GitHub](https://github.com/UnkindPartition/tasty)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/unkindpartition-tasty
