[](https://circleci.com/gh/haskell-works/tasty-discover/tree/master)
[](http://stackage.org/nightly/package/tasty-discover)
[](http://stackage.org/lts/package/tasty-discover)
[](http://hackage.haskell.org/package/tasty-discover)
[](https://raw.githubusercontent.com/haskell-works/tasty-discover/main/LICENSE)
# tasty-discover
- [Getting Started](#getting-started)
* [Create Test Driver File](#create-test-driver-file)
* [Configure Cabal or Hpack Test Suite](#configure-cabal-or-hpack-test-suite)
- [Write Tests](#write-tests)
* [Test Transformations (Flavored, skip, platform)](#test-transformations-flavored-skip-platform)
- [Flavored (test transformations)](#flavored-test-transformations)
- [Skipping Tests](#skipping-tests)
- [Platform-Specific Tests](#platform-specific-tests)
- [Combining skip and platform](#combining-skip-and-platform)
- [Using skip and platform (guidelines)](#using-skip-and-platform-guidelines)
* [Comment Handling](#comment-handling)
- [Customise Discovery](#customise-discovery)
* [No Arguments](#no-arguments)
* [With Arguments](#with-arguments)
* [Custom Main Function](#custom-main-function)
- [Example Project](#example-project)
- [Change Log](#change-log)
- [Deprecation Policy](#deprecation-policy)
- [Contributing](#contributing)
- [FAQ](#frequently-asked-questions)
- [Maintenance](#maintenance)
- [Releasing](#releasing)
- [Acknowledgements](#acknowledgements)
- [AI Guidelines](AI_GUIDELINES.md)
- [Coding Style](CODING_STYLE.md)
Haskell auto-magic test discovery and runner for the [tasty test framework].
[tasty test framework]: https://github.com/feuerbach/tasty
Prefix your test case names and `tasty-discover` will discover, collect and run
them. All popular Haskell test libraries are covered. Configure once then just
write your tests. Remember to add your test modules to your Cabal/Hpack
files. Tasty ingredients are included along with various configuration options
for different use cases.
**Recent improvements include:**
- New `--no-main` option for custom test runners
- **Platform-specific test filtering** with `platform` function and logical expressions
- **Skip test functionality** with `skip` function and yellow `[SKIPPED]` output
- **`Flavored` type** for general-purpose test transformations with extensible design
- Enhanced support for custom test types with `Tasty` instances
- Better handling of backup files and directories in test discovery
- Intelligent block comment handling to prevent false test discovery
- Comprehensive documentation with more test examples
See below for full documentation and examples.
# Getting Started
There are 4 simple steps:
1. [Create a test driver file in the test directory](#create-test-driver-file)
2. [Mark the driver file as the `main-is` in the test suite](#configure-cabal-or-hpack-test-suite)
3. [Mark tests with the correct prefixes](#write-tests)
4. [Customise test discovery as needed](#customise-discovery)
Check out the [example project](#example-project) to get moving quickly.
## Create Test Driver File
You can name this file anything you want but it must contain the correct
preprocessor definition for `tasty-discover` to run and to detect the
configuration. It should be at the top level of the test directory.
For example (in `test/Driver.hs`):
```
{-# OPTIONS_GHC -F -pgmF tasty-discover #-}
```
following example, the test driver file is called `Driver.hs`:
```
test-suite test
type: exitcode-stdio-1.0
main-is: Driver.hs
hs-source-dirs: test
build-depends: base
```
If you use [hpack], that might look like:
[hpack]: https://github.com/sol/hpack
``` yaml
tests:
test:
main: "Driver.hs"
source-dirs: "test"
dependencies:
- "base"
```
To ensure that `tasty-discover` is available even without installation, add this
to the test suite in your cabal file:
```
build-tool-depends:
tasty-discover:tasty-discover
```
See [`hpack` documentation](https://github.com/sol/hpack) for `stack` equivalent.
# Write Tests
Create test modules and prefix the test function name with an identifier that
corresponds to the testing library you wish to run the test with:
- **prop_**: [QuickCheck](http://hackage.haskell.org/package/tasty-quickcheck) properties.
- **scprop_**: [SmallCheck](http://hackage.haskell.org/package/tasty-smallcheck) properties.
- **hprop_**: [Hedgehog](http://hackage.haskell.org/package/tasty-hedgehog) properties.
- **unit_**: [HUnit](http://hackage.haskell.org/package/tasty-hunit) test cases.
- **spec_**: [Hspec](http://hackage.haskell.org/package/tasty-hspec) specifications.
- **test_**: [Tasty](http://hackage.haskell.org/package/tasty) TestTrees.
- **tasty_**: Custom tests with [Tasty](http://hackage.haskell.org/package/tasty) instances.
Here is an example test module with a bunch of different tests:
``` haskell
{-# LANGUAGE ScopedTypeVariables #-}
module ExampleTest where
import Data.List
import Test.Tasty
import Test.Tasty.Discover
import Test.Tasty.HUnit
import Test.Tasty.Hspec
import Test.Tasty.QuickCheck
import Test.Tasty.SmallCheck
import qualified Test.Tasty.Hedgehog as TH
import qualified Hedgehog as H
import qualified Hedgehog.Gen as G
import qualified Hedgehog.Range as R
-- HUnit test case
unit_listCompare :: IO ()
unit_listCompare = [1, 2, 3] `compare` [1,2] @?= GT
-- HUnit test case with additional info
unit_listInfo :: IO String
unit_listInfo = return "This test provides info"
-- HUnit test case with steps
unit_listSteps :: (String -> IO ()) -> IO ()
unit_listSteps step = do
step "Setting up test data"
step "Running the test"
[1, 2, 3] `compare` [1,2] @?= GT
-- QuickCheck property
prop_additionCommutative :: Int -> Int -> Bool
prop_additionCommutative a b = a + b == b + a
-- SmallCheck property
scprop_sortReverse :: [Int] -> Bool
scprop_sortReverse list = sort list == sort (reverse list)
-- Hedgehog property
hprop_reverseReverse :: H.Property
hprop_reverseReverse = H.property $ do
xs <- H.forAll $ G.list (R.linear 0 100) G.alpha
reverse (reverse xs) H.=== xs
-- Hspec specification
spec_prelude :: Spec
spec_prelude = describe "Prelude.head" $ do
it "returns the first element of a list" $ do
head [23 ..] `shouldBe` (23 :: Int)
-- Simple Tasty TestTree
test_addition :: TestTree
test_addition = testProperty "Addition commutes" $ \(a :: Int) (b :: Int) -> a + b == b + a
-- List of Tasty TestTrees
test_multiplication :: [TestTree]
test_multiplication =
[ testProperty "Multiplication commutes" $ \(a :: Int) (b :: Int) -> a * b == b * a
, testProperty "One is identity" $ \(a :: Int) -> a * 1 == a
]
-- IO Tasty TestTree
test_generateTree :: IO TestTree
test_generateTree = do
input <- pure "Some input"
pure $ testCase input $ pure ()
-- IO List of Tasty TestTrees
test_generateTrees :: IO [TestTree]
test_generateTrees = do
inputs <- pure ["First input", "Second input"]
pure $ map (\s -> testCase s $ pure ()) inputs
-- Custom test with Tasty instance
--
-- Write a test for anything with a Tasty instance
-- In order to use Flavored with tasty_ functions, add tasty-discover as a library
-- dependency to your test component in the cabal file.
data CustomTest = CustomTest String Assertion
instance Tasty CustomTest where
tasty info (CustomTest prefix act) =
pure $ testCase (prefix ++ descriptionOf info) act
tasty_myTest :: CustomTest
tasty_myTest = CustomTest "Custom: " $ pure ()
-- Custom Tasty TestTree (can be any TestTree)
tasty_customGroup :: TestTree
tasty_customGroup = testGroup "Custom Test Group"
[ testCase "nested test 1" $ return ()
, testCase "nested test 2" $ (1 + 1) @?= (2 :: Int)
]
```
## Test Transformations (Flavored, skip, platform)
This section covers how to transform tests using the Flavored pattern and how to apply skip and platform filters effectively.
### Flavored (test transformations)
The `Flavored` type provides a general-purpose mechanism for transforming `TestTree`s generated by `tasty_` functions before they are added to the test suite. This allows you to apply various options and modifications to your tests.
You can create flavored tests using the `flavored` constructor:
```haskell
flavored :: (TestTree -> TestTree) -> a -> Flavored a
```
#### Examples
```haskell
import Test.Tasty.Discover (Flavored, flavored, skip)
-- Skip a custom property test
tasty_skipProperty :: Flavored Property
tasty_skipProperty = flavored skip $ property $ do
-- This test will be skipped and show as [SKIPPED] in yellow
H.failure
```
When tests are skipped, they will show as `[SKIPPED]` in yellow in the test output and won't actually execute.
### Skipping Tests
You can skip tests using the skip functionality provided by tasty-discover. There are multiple ways to skip tests:
For a high-level overview of when to use flavored vs direct application, see
[Using skip and platform (guidelines)](#using-skip-and-platform-guidelines).
#### Using the `skip` function
You can use the `skip` function to skip any TestTree:
```haskell
import Test.Tasty.Discover (skip)
-- Skip a simple test
test_skipThis :: TestTree
test_skipThis = skip $ testCase "this will be skipped" $ pure ()
-- Skip a property test
prop_skipThis :: Property -> TestTree
prop_skipThis p = skip $ testProperty "skipped property" p
```
**Potential future uses:**
The `Flavored` mechanism is designed to be extensible and could be used for other `TestTree` transformations such as:
- Setting test timeouts
- Adding test metadata or descriptions
- Grouping tests under custom names
- Setting resource dependencies
- Applying multiple transformations in sequence
#### Important: How to skip a tasty_ test
Guideline (TL;DR): To skip a `tasty_` test so it shows `[SKIPPED]` and doesn’t run, wrap it with `flavored skip`:
```haskell
import Test.Tasty.Discover (Flavored, flavored, skip)
-- Skips at the TestTree level (preferred for tasty_ tests)
tasty_mySkipped :: Flavored TestTree
tasty_mySkipped = flavored skip $ testCase "will be skipped" $ pure ()
```
Details (why this matters): Applying `skip` directly to an already-constructed
`TestTree` marks only that subtree as skipped. The test body can detect it via
`askOption`, but the outer `Tasty` instance (used by `tasty_` functions) may not
render a top-level `[SKIPPED]` placeholder because the option is applied after
the instance decides how to wrap the node. Using `flavored skip` applies the
transformation early so the instance can short-circuit and substitute a skipped
placeholder.
For completeness, a direct `skip` example that observes the option inside the test:
```haskell
-- Direct skip on a TestTree: the test can read SkipTest via askOption, but the
-- outer instance may not show a top-level [SKIPPED] marker for this node.
test_directSkip :: TestTree
test_directSkip = skip $ askOption $ \(TD.SkipTest shouldSkip) ->
testCase "observes SkipTest inside" $ assertBool "expected SkipTest" shouldSkip
```
Using `Flavored` ensures the `skip` is visible to the `Tasty` instance early enough to short-circuit with a skipped placeholder.
```
### Platform-Specific Tests
You can conditionally run tests based on the current operating platform using the `platform` function provided by tasty-discover. This is useful for tests that only work on specific operating systems or need to be excluded from certain platforms.
For general guidance and composition patterns with `skip`, see
[Using skip and platform (guidelines)](#using-skip-and-platform-guidelines).
The `platform` function takes a platform expression string and a `TestTree`, returning a `TestTree` that will only run if the expression evaluates to true for the current platform:
```haskell
import Test.Tasty.Discover (platform)
-- Run only on Linux
tasty_linuxOnly :: TestTree
tasty_linuxOnly = platform "linux" $ testCase "Linux-specific functionality" $ do
-- This test only runs on Linux
pure ()
-- Run on all platforms except Windows
tasty_notWindows :: TestTree
tasty_notWindows = platform "!windows" $ testCase "Non-Windows functionality" $ do
-- This test runs on all platforms except Windows
pure ()
-- Run on Unix-like systems (Linux or Darwin)
tasty_unixLike :: TestTree
tasty_unixLike = platform "unix" $ testCase "Unix-like systems" $ do
-- This test runs on Linux and Darwin (Unix-like systems)
pure ()
```
#### Platform Expression Syntax
Platform expressions support the following syntax:
**Platform Names:**
- `"linux"` - Linux systems
- `"darwin"` - macOS systems
- `"windows"` - Windows systems (mapped to "mingw32" internally)
- `"mingw32"` - Windows systems (actual System.Info.os value)
- `"unix"` - Unix-like systems (matches both "linux" and "darwin")
**Logical Operators:**
- `"!"` (NOT) - Negation, e.g., `"!windows"` means "not Windows"
- `"&"` (AND) - Conjunction, e.g., `"!windows & !darwin"` means "neither Windows nor Darwin"
- `"|"` (OR) - Disjunction, e.g., `"linux | darwin"` means "Linux or Darwin"
**Complex Examples:**
```haskell
-- Run on platforms that are neither Windows nor Darwin (e.g., Linux)
tasty_complexPlatform1 :: TestTree
tasty_complexPlatform1 = platform "!windows & !darwin" $ testCase "Neither Windows nor Darwin" $ do
pure ()
-- Run on either Linux or Darwin, but not Windows
tasty_complexPlatform2 :: TestTree
tasty_complexPlatform2 = platform "linux | darwin" $ testCase "Linux or Darwin only" $ do
pure ()
```
#### Using `Flavored` with Platform Filtering
You can combine platform filtering with other test transformations using the `Flavored` type:
```haskell
import Test.Tasty.Discover (Flavored, flavored, platform)
-- Apply platform filtering to custom test types
tasty_platformFlavored :: Flavored TestTree
tasty_platformFlavored = flavored (platform "!windows") $ testCase "Advanced platform test" $ do
pure ()
-- Platform-specific property test
tasty_platformProperty :: Flavored Property
tasty_platformProperty = flavored (platform "unix") $ property $ do
-- This hedgehog property only runs on Unix-like systems
x <- H.forAll $ G.int (R.linear 1 100)
x H.=== x
```
#### Combining skip and platform
Platform filtering can be combined with other tasty-discover features:
```haskell
-- Platform filtering with test skipping
tasty_platformAndSkip :: TestTree
tasty_platformAndSkip = platform "linux" $ skip $ testCase "Linux test that's also skipped" $ do
-- This would only run on Linux, but it's also skipped
pure ()
-- Platform filtering with test groups
tasty_platformGroup :: TestTree
tasty_platformGroup = platform "unix" $ testGroup "Unix-only tests"
[ testCase "Unix test 1" $ pure ()
, testCase "Unix test 2" $ pure ()
, testProperty "Unix property" $ \(x :: Int) -> x >= 0 || x < 0
]
```
Platform filtering works by checking the current platform against the expression at runtime. If the expression evaluates to `False`, the test is automatically skipped using the same mechanism as the `skip` function.
#### Skipping entire test trees with `applySkips`
When you want to skip an entire test tree (such as a group of tests) and have each individual test show as `[SKIPPED]` in the output, use the `applySkips` function:
```haskell
import Test.Tasty.Discover (Flavored, flavored, platform, applySkips)
-- Skip an entire test group on Darwin
tasty_testTree_no_darwin :: Flavored (IO TestTree)
tasty_testTree_no_darwin =
flavored (platform "!darwin") $ pure $
applySkips $ testGroup "Non-Darwin group"
[ testProperty "Test 1" $ \(x :: Int) -> x == x
, testCase "Test 2" $ pure ()
, testProperty "Test 3" $ \(x :: Int) -> x >= 0 || x < 0
]
```
On Darwin, this will display all tests as skipped in yellow:
```
Non-Darwin group
Test 1 [SKIPPED]: OK
Test 2 [SKIPPED]: OK
Test 3 [SKIPPED]: OK
```
The `applySkips` function:
- Checks the `SkipTest` option (set by functions like `skip` or `platform`)
- Traverses the entire test tree and replaces each individual test with a skipped placeholder
- Preserves the test group structure
- Shows `[SKIPPED]` in yellow for each test
This is particularly useful for platform-specific test suites where you want to see which tests would run on other platforms, rather than hiding the entire group.
### Using skip and platform (guidelines)
TL;DR:
- For tests exposed via `tasty_` functions, prefer the `Flavored` pattern to apply
transformations like `skip` and `platform` so they take effect at the TestTree level and can short-circuit execution.
- Applying `skip` directly to an already-constructed `TestTree` marks the subtree as skipped. The test can observe this via `askOption`, but the outer `Tasty` instance may not show a top-level `[SKIPPED]` placeholder.
Examples:
```haskell
import Test.Tasty.Discover (Flavored, flavored, skip, platform)
import Test.Tasty (TestTree, testCase)
-- Skip (preferred for tasty_ tests):
tasty_mySkipped :: Flavored TestTree
tasty_mySkipped = flavored skip $ testCase "will be skipped" $ pure ()
-- Platform filter with Flavored:
tasty_linuxOnly :: Flavored TestTree
tasty_linuxOnly = flavored (platform "linux") $ testCase "Linux only" $ pure ()
-- Compose platform and skip:
tasty_linuxButSkipped :: Flavored TestTree
tasty_linuxButSkipped = flavored (platform "linux") $ flavored skip $ testCase "won't run" $ pure ()
-- Direct skip on a TestTree (observed inside the test):
test_directSkip :: TestTree
test_directSkip = skip $ askOption $ \(TD.SkipTest shouldSkip) ->
testCase "observes SkipTest inside" $ assertBool "expected SkipTest" shouldSkip
```
Platform expressions:
- Names: "linux", "darwin", "windows" (mapped to "mingw32"), "mingw32", and "unix" (matches both linux and darwin)
- Operators: `!` (NOT), `&` (AND), `|` (OR)
- Examples:
- `platform "!windows & !darwin"` — neither Windows nor Darwin
- `platform "linux | darwin"` — Linux or Darwin
- `platform "unix"` — Linux or Darwin
## Test Type Variations
### HUnit Tests (`unit_` prefix)
The `unit_` prefix supports three different function signatures:
### Tasty TestTrees (`test_` prefix)
- `unit_testName :: IO ()` - Basic test case
- `unit_testName :: IO String` - Test case that provides additional info
- `unit_testName :: (String -> IO ()) -> IO ()` - Test case with steps
### Tasty TestTrees (`test_` prefix)
The `test_` prefix supports four different function signatures:
- `test_testName :: TestTree` - A single test tree
- `test_testName :: [TestTree]` - A list of test trees (automatically grouped)
- `test_testName :: IO TestTree` - A test tree generated in IO
- `test_testName :: IO [TestTree]` - A list of test trees generated in IO
### Custom Tests (`tasty_` prefix)
The `tasty_` prefix works with any type that has a `Tasty` instance:
- Built-in instances for `TestTree`, `[TestTree]`, `IO TestTree`, `IO [TestTree]`
- Custom instances for your own data types
- Provides access to test metadata through `TastyInfo`
### Organizing Tests with `testGroup`
The `testGroup` function is Tasty's way of organizing tests into hierarchical groups. You can use it in several ways:
**In `test_` functions:**
```haskell
test_arithmeticTests :: TestTree
test_arithmeticTests = testGroup "Arithmetic Operations"
[ testCase "addition" $ 2 + 2 @?= 4
, testCase "multiplication" $ 3 * 4 @?= 12
, testProperty "commutativity" $ \a b -> a + b == b + (a :: Int)
]
```
**In `tasty_` functions:**
```haskell
tasty_myTestSuite :: TestTree
tasty_myTestSuite = testGroup "My Test Suite"
[ testGroup "Unit Tests"
[ testCase "test 1" $ pure ()
, testCase "test 2" $ pure ()
]
, testGroup "Properties"
[ testProperty "prop 1" $ \x -> x == (x :: Int)
]
]
```
**In list form with `test_` functions:**
```haskell
test_groupedTests :: [TestTree]
test_groupedTests =
[ testGroup "Group 1" [testCase "test A" $ pure ()]
, testGroup "Group 2" [testCase "test B" $ pure ()]
]
```
This creates nested test hierarchies that make test output more organized and easier to navigate.
## Comment Handling
`tasty-discover` intelligently handles Haskell comments during test discovery to prevent false positives:
### Block Comments
Tests inside multiline block comments are automatically ignored:
```haskell
module MyTest where
-- This test will be discovered
unit_validTest :: IO ()
unit_validTest = pure ()
{- This test will be ignored
unit_commentedOut :: IO ()
unit_commentedOut = pure ()
-}
{- Nested comments are also handled correctly
{- Even deeply nested ones
unit_deeplyNested :: IO ()
unit_deeplyNested = pure ()
-}
unit_alsoIgnored :: IO ()
unit_alsoIgnored = pure ()
-}
```
### Line Comments
Line comments (starting with `--`) are handled by the Haskell lexer and don't interfere with test discovery:
```haskell
-- unit_thisIsIgnored :: IO ()
unit_thisIsFound :: IO () -- This test will be discovered
unit_thisIsFound = pure ()
```
This feature prevents compilation errors that would occur if `tasty-discover` tried to reference tests that are commented out, making it easier to temporarily disable tests during development.
# Customise Discovery
You configure `tasty-discover` by passing options to the test driver file.
## No Arguments
Example: `{-# OPTIONS_GHC -F -pgmF tasty-discover -optF --debug #-}`
- **--debug**: Output the contents of the generated module while testing.
- **--tree-display**: Display the test output results hierarchically.
- **--no-main**: Generate a module without a main function, exporting `tests` and `ingredients` instead.
## With Arguments
Example: `{-# OPTIONS_GHC -F -pgmF tasty-discover -optF --modules="*CustomTest.hs" #-}`
- **--modules**: Which test modules to discover (with glob pattern).
- **--search-dir**: Where to look for tests. This is a directory relative
to the location of the source file. By default, this is the directory
of the source file."
- **--ignores**: Which test modules to ignore (with glob pattern).
- **--generated-module**: The name of the generated test module.
- **--ingredient**: Tasty ingredients to add to your test runner.
- **--inplace**: Has the generated code written to the source file.
It is also possible to override [tasty test options] with `-optF`:
[tasty test options]: https://github.com/feuerbach/tasty#options
``` bash
{-# OPTIONS_GHC -F -pgmF tasty-discover -optF --hide-successes #-}
```
## Custom Main Function
The `--no-main` option allows you to write your own custom main function while still using tasty-discover for test discovery. This is useful when you need to:
- Apply custom test transformations or wrappers
- Add custom logging or output formatting
- Integrate with custom test runners or CI systems
- Control exactly how tests are executed
### Example Usage
Create your test discovery file (e.g., `test/Tests.hs`):
```haskell
{-# OPTIONS_GHC -F -pgmF tasty-discover -optF --no-main -optF --generated-module -optF Tests #-}
```
Then create your custom main file (e.g., `test/Main.hs`):
```haskell
module Main where
import qualified Tests
import qualified Test.Tasty as T
main :: IO ()
main = do
putStrLn "=== Custom Test Runner ==="
-- Get discovered tests and ingredients
discoveredTests <- Tests.tests
-- Apply custom transformations
let wrappedTests = T.testGroup "My Custom Tests" [discoveredTests]
-- Run with custom configuration
T.defaultMainWithIngredients Tests.ingredients wrappedTests
```
Configure your cabal test suite to use the custom main:
```
test-suite my-tests
type: exitcode-stdio-1.0
main-is: Main.hs
other-modules: Tests
hs-source-dirs: test
build-depends: base, tasty
build-tool-depends: tasty-discover:tasty-discover
```
# Example Project
See the [testing for this package] for a fully configured example.
[testing for this package]: https://github.com/haskell-works/tasty-discover/tree/main/test
# Change Log
Please see the [CHANGELOG.md] for the latest changes.
We try to keep [tagged releases] in our release process, if you care about that.
[CHANGELOG.md]: https://github.com/haskell-works/tasty-discover/blob/main/CHANGELOG.md
[tagged releases]: https://github.com/haskell-works/tasty-discover/releases
# Releasing
This project's release flow is automated via GitHub Actions and triggered by pushing version tags.
Release checklist:
1) Prepare notes
- Update `CHANGELOG.md`: move items from "Unreleased" to a new version section with the current date.
2) Bump version
- Edit `tasty-discover.cabal` and set `version:` to the new version (e.g., `5.x.y`).
3) Commit changes
- Commit the changes: `git commit -m "Release X.Y.Z"`
- Push the commit: `git push origin main`
4) Create and push tag
- Create a git tag: `git tag -a vX.Y.Z -m "Release version X.Y.Z"`
- Push the tag: `git push origin vX.Y.Z`
5) CI does the rest (automated)
- When the tag is pushed, GitHub Actions automatically:
- Runs the full test suite
- Validates the cabal project with `cabal check`
- Builds source distributions (`cabal v2-sdist`)
- Uploads to Hackage (requires repo secrets `HACKAGE_USER`/`HACKAGE_PASS`)
- Creates a draft GitHub Release for the tag
6) Publish release
- Go to https://github.com/haskell-works/tasty-discover/releases
- Edit the draft GitHub Release notes if needed and publish
Notes:
- The workflow is defined in `.github/workflows/haskell.yml`.
- The release workflow only triggers on tags matching `v[0-9]+.[0-9]+.[0-9]+` (e.g., v5.2.0).
- Keep `tested-with` in the cabal file up to date with CI's GHC matrix.
# Deprecation Policy
If a breaking change is implemented, you'll see a major version increase, an
entry in the [change log] and a compile-time error with a deprecation warning
and clear instructions on how to upgrade. Please do complain if we're doing
this too much.
[change log]: https://github.com/haskell-works/tasty-discover/blob/main/CHANGELOG.md
# Contributing
All contributions welcome! The continuous integration suite is pretty
comprehensive, so just get hacking and add a test case - there are *plenty* of
examples, so this should be simple - and I'll get to review your change ASAP.
Please follow the guidelines in [CODING_STYLE.md](CODING_STYLE.md) for consistent code formatting and patterns.
For AI assistants and detailed development guidelines, see [AI_GUIDELINES.md](AI_GUIDELINES.md).
# Frequently Asked Questions
## Deleting Tests Breaks The Test Run
This is a known limitation and has been reported. No fix is planned unless you have time.
Please see [#145](https://github.com/haskell-works/tasty-discover/issues/145) for more information.
# Maintenance
If you're interested in helping maintain this package, please let [@newhoggy] know!
It doesn't take much time (max ~3 hours a month) and all we need to do is:
* Triage issues that are raised.
* Review pull requests from contributors.
* Fix bugs when present.
* Make releases.
* Manage bounds issues on Stackage.
You can [create an issue] or drop him a line at **lukewm AT riseup DOT NET**.
[@newhoggy]: https://twitter.com/newhoggy
[create an issue]: https://github.com/haskell-works/tasty-discover/issues/new
# Acknowledgements
Thanks to [hspec-discover] and [tasty-auto] for making this possible.
A huge thanks to the growing list of contributors.
[hspec-discover]: https://hspec.github.io/hspec-discover.html
[tasty-auto]: https://github.com/minad/tasty-auto