Safe Haskell | None |
---|---|
Language | Haskell2010 |
Synopsis
- sydTest :: Spec -> IO ()
- sydTestWith :: Settings -> Spec -> IO ()
- describe :: String -> TestDefM a b () -> TestDefM a b ()
- it :: forall outers test. (HasCallStack, IsTest test, Arg1 test ~ ()) => String -> test -> TestDefM outers (Arg2 test) ()
- itWithOuter :: (HasCallStack, IsTest test) => String -> test -> TestDefM (Arg2 test ': l) (Arg1 test) ()
- itWithBoth :: (HasCallStack, IsTest test) => String -> test -> TestDefM (Arg1 test ': l) (Arg2 test) ()
- itWithAll :: (HasCallStack, IsTest test, Arg1 test ~ HList l) => String -> test -> TestDefM l (Arg2 test) ()
- specify :: forall outers test. (HasCallStack, IsTest test, Arg1 test ~ ()) => String -> test -> TestDefM outers (Arg2 test) ()
- specifyWithOuter :: (HasCallStack, IsTest test) => String -> test -> TestDefM (Arg2 test ': l) (Arg1 test) ()
- specifyWithBoth :: (HasCallStack, IsTest test) => String -> test -> TestDefM (Arg1 test ': l) (Arg2 test) ()
- specifyWithAll :: (HasCallStack, IsTest test, Arg1 test ~ HList l) => String -> test -> TestDefM l (Arg2 test) ()
- xdescribe :: String -> TestDefM a b () -> TestDefM a b ()
- xit :: forall outers test. (HasCallStack, IsTest test, Arg1 test ~ ()) => String -> test -> TestDefM outers (Arg2 test) ()
- xitWithOuter :: (HasCallStack, IsTest test) => String -> test -> TestDefM (Arg2 test ': l) (Arg1 test) ()
- xitWithBoth :: (HasCallStack, IsTest test) => String -> test -> TestDefM (Arg1 test ': l) (Arg2 test) ()
- xitWithAll :: (HasCallStack, IsTest test, Arg1 test ~ HList l) => String -> test -> TestDefM l (Arg2 test) ()
- xspecify :: forall outers test. (HasCallStack, IsTest test, Arg1 test ~ ()) => String -> test -> TestDefM outers (Arg2 test) ()
- xspecifyWithOuter :: (HasCallStack, IsTest test) => String -> test -> TestDefM (Arg2 test ': l) (Arg1 test) ()
- xspecifyWithBoth :: (HasCallStack, IsTest test) => String -> test -> TestDefM (Arg1 test ': l) (Arg2 test) ()
- xspecifyWithAll :: (HasCallStack, IsTest test, Arg1 test ~ HList l) => String -> test -> TestDefM l (Arg2 test) ()
- pending :: String -> TestDefM a b ()
- pendingWith :: String -> String -> TestDefM a b ()
- eit :: HasCallStack => String -> ReaderT env IO () -> TestDef l env
- withTestEnv :: env -> ReaderT env IO a -> IO a
- pureGoldenByteStringFile :: FilePath -> ByteString -> GoldenTest ByteString
- goldenByteStringFile :: FilePath -> IO ByteString -> GoldenTest ByteString
- pureGoldenTextFile :: FilePath -> Text -> GoldenTest Text
- goldenTextFile :: FilePath -> IO Text -> GoldenTest Text
- pureGoldenStringFile :: FilePath -> String -> GoldenTest String
- goldenStringFile :: FilePath -> IO String -> GoldenTest String
- goldenShowInstance :: Show a => FilePath -> a -> GoldenTest String
- goldenPrettyShowInstance :: Show a => FilePath -> a -> GoldenTest String
- shouldBe :: (HasCallStack, Show a, Eq a) => a -> a -> IO ()
- shouldNotBe :: (HasCallStack, Show a, Eq a) => a -> a -> IO ()
- shouldSatisfy :: (HasCallStack, Show a) => a -> (a -> Bool) -> IO ()
- shouldSatisfyNamed :: (HasCallStack, Show a) => a -> String -> (a -> Bool) -> IO ()
- shouldNotSatisfy :: (HasCallStack, Show a) => a -> (a -> Bool) -> IO ()
- shouldNotSatisfyNamed :: (HasCallStack, Show a) => a -> String -> (a -> Bool) -> IO ()
- shouldReturn :: (HasCallStack, Show a, Eq a) => IO a -> a -> IO ()
- shouldNotReturn :: (HasCallStack, Show a, Eq a) => IO a -> a -> IO ()
- shouldStartWith :: (HasCallStack, Show a, Eq a) => [a] -> [a] -> Expectation
- shouldEndWith :: (HasCallStack, Show a, Eq a) => [a] -> [a] -> Expectation
- shouldContain :: (HasCallStack, Show a, Eq a) => [a] -> [a] -> Expectation
- expectationFailure :: HasCallStack => String -> IO a
- context :: String -> IO a -> IO a
- type Expectation = IO ()
- shouldThrow :: forall e a. (HasCallStack, Exception e) => IO a -> Selector e -> Expectation
- type Selector a = a -> Bool
- anyException :: Selector SomeException
- anyErrorCall :: Selector ErrorCall
- errorCall :: String -> Selector ErrorCall
- anyIOException :: Selector IOException
- anyArithException :: Selector ArithException
- stringShouldBe :: HasCallStack => String -> String -> IO ()
- textShouldBe :: HasCallStack => Text -> Text -> IO ()
- stringsNotEqualButShouldHaveBeenEqual :: String -> String -> Assertion
- textsNotEqualButShouldHaveBeenEqual :: Text -> Text -> Assertion
- bytestringsNotEqualButShouldHaveBeenEqual :: ByteString -> ByteString -> Assertion
- data Assertion
- beforeAll :: IO a -> TestDefM (a ': l) c e -> TestDefM l c e
- beforeAll_ :: IO () -> TestDefM a b e -> TestDefM a b e
- beforeAllWith :: (b -> IO a) -> TestDefM (a ': (b ': l)) c e -> TestDefM (b ': l) c e
- afterAll :: (a -> IO ()) -> TestDefM (a ': l) b e -> TestDefM (a ': l) b e
- afterAll' :: (HList l -> IO ()) -> TestDefM l b e -> TestDefM l b e
- afterAll_ :: IO () -> TestDefM a b e -> TestDefM a b e
- aroundAll :: ((a -> IO ()) -> IO ()) -> TestDefM (a ': l) c e -> TestDefM l c e
- aroundAll_ :: (IO () -> IO ()) -> TestDefM a b e -> TestDefM a b e
- aroundAllWith :: forall a b c l r. ((a -> IO ()) -> b -> IO ()) -> TestDefM (a ': (b ': l)) c r -> TestDefM (b ': l) c r
- before :: IO c -> TestDefM a c e -> TestDefM a () e
- before_ :: IO () -> TestDefM a c e -> TestDefM a c e
- after :: (c -> IO ()) -> TestDefM a c e -> TestDefM a c e
- after_ :: IO () -> TestDefM a c e -> TestDefM a c e
- around :: ((c -> IO ()) -> IO ()) -> TestDefM a c e -> TestDefM a () e
- around_ :: (IO () -> IO ()) -> TestDefM a c e -> TestDefM a c e
- aroundWith :: forall a c d r. ((c -> IO ()) -> d -> IO ()) -> TestDefM a c r -> TestDefM a d r
- setupAround :: SetupFunc () c -> TestDefM a c e -> TestDefM a () e
- setupAroundWith :: SetupFunc d c -> TestDefM a c e -> TestDefM a d e
- setupAroundWith' :: HContains l a => (a -> SetupFunc d c) -> TestDefM l c e -> TestDefM l d e
- newtype SetupFunc b a = SetupFunc {
- unSetupFunc :: forall r. (a -> IO r) -> b -> IO r
- makeSimpleSetupFunc :: (forall r. (a -> IO r) -> IO r) -> SetupFunc () a
- useSimpleSetupFunc :: SetupFunc () a -> forall r. (a -> IO r) -> IO r
- connectSetupFunc :: SetupFunc c b -> SetupFunc b a -> SetupFunc c a
- composeSetupFunc :: SetupFunc b a -> SetupFunc c b -> SetupFunc c a
- wrapSetupFunc :: (b -> SetupFunc () a) -> SetupFunc b a
- unwrapSetupFunc :: SetupFunc b a -> b -> SetupFunc () a
- modifyMaxSuccess :: (Int -> Int) -> TestDefM a b c -> TestDefM a b c
- modifyMaxDiscardRatio :: (Int -> Int) -> TestDefM a b c -> TestDefM a b c
- modifyMaxSize :: (Int -> Int) -> TestDefM a b c -> TestDefM a b c
- modifyMaxShrinks :: (Int -> Int) -> TestDefM a b c -> TestDefM a b c
- modifyRunSettings :: (TestRunSettings -> TestRunSettings) -> TestDefM a b c -> TestDefM a b c
- data TestRunSettings = TestRunSettings {}
- sequential :: TestDefM a b c -> TestDefM a b c
- parallel :: TestDefM a b c -> TestDefM a b c
- withParallelism :: Parallelism -> TestDefM a b c -> TestDefM a b c
- data Parallelism
- randomiseExecutionOrder :: TestDefM a b c -> TestDefM a b c
- doNotRandomiseExecutionOrder :: TestDefM a b c -> TestDefM a b c
- withExecutionOrderRandomisation :: ExecutionOrderRandomisation -> TestDefM a b c -> TestDefM a b c
- data ExecutionOrderRandomisation
- runIO :: IO e -> TestDefM a b e
- newtype TestDefM a b c = TestDefM {
- unTestDefM :: RWST TestRunSettings (TestForest a b) () IO c
- type TestDef a b = TestDefM a b ()
- execTestDefM :: Settings -> TestDefM a b c -> IO (TestForest a b)
- runTestDefM :: Settings -> TestDefM a b c -> IO (c, TestForest a b)
- data TDef v = TDef {
- testDefVal :: v
- testDefCallStack :: CallStack
- type TestForest a c = SpecDefForest a c ()
- type TestTree a c = SpecDefTree a c ()
- type SpecDefForest (a :: [Type]) c e = [SpecDefTree a c e]
- data SpecDefTree (a :: [Type]) c e where
- DefSpecifyNode :: Text -> TDef (((HList a -> c -> IO ()) -> IO ()) -> IO TestRunResult) -> e -> SpecDefTree a c e
- DefPendingNode :: Text -> Maybe Text -> SpecDefTree a c e
- DefDescribeNode :: Text -> SpecDefForest a c e -> SpecDefTree a c e
- DefWrapNode :: (IO () -> IO ()) -> SpecDefForest a c e -> SpecDefTree a c e
- DefBeforeAllNode :: IO a -> SpecDefForest (a ': l) c e -> SpecDefTree l c e
- DefAroundAllNode :: ((a -> IO ()) -> IO ()) -> SpecDefForest (a ': l) c e -> SpecDefTree l c e
- DefAroundAllWithNode :: ((b -> IO ()) -> a -> IO ()) -> SpecDefForest (b ': (a ': l)) c e -> SpecDefTree (a ': l) c e
- DefAfterAllNode :: (HList a -> IO ()) -> SpecDefForest a c e -> SpecDefTree a c e
- DefParallelismNode :: Parallelism -> SpecDefForest a c e -> SpecDefTree a c e
- DefRandomisationNode :: ExecutionOrderRandomisation -> SpecDefForest a c e -> SpecDefTree a c e
- type ResultForest = SpecForest (TDef (Timed TestRunResult))
- type ResultTree = SpecTree (TDef (Timed TestRunResult))
- shouldExitFail :: ResultForest -> Bool
- type Spec = SpecWith ()
- type SpecWith a = SpecM a ()
- type SpecM a b = TestDefM '[] a b
- ppShow :: Show a => a -> String
- module Test.Syd.Def
- module Test.Syd.Expectation
- module Test.Syd.HList
- module Test.Syd.Modify
- module Test.Syd.Output
- module Test.Syd.Run
- module Test.Syd.Runner
- module Test.Syd.SpecDef
- module Test.Syd.SpecForest
- module Control.Monad.IO.Class
Top level API functions
sydTest :: Spec -> IO () Source #
Evaluate a test suite definition and then run it, with default Settings
sydTestWith :: Settings -> Spec -> IO () Source #
Evaluate a test suite definition and then run it, with given Settings
Defining a test suite
Declaring tests
describe :: String -> TestDefM a b () -> TestDefM a b () Source #
Declare a test group
Example usage:
describe "addition" $ do it "adds 3 to 5 to result in 8" $ 3 + 5 `shouldBe` 8 it "adds 4 to 7 to result in 11" $ 4 + 7 `shouldBe` 11
it :: forall outers test. (HasCallStack, IsTest test, Arg1 test ~ ()) => String -> test -> TestDefM outers (Arg2 test) () Source #
Declare a test
Note: Don't look at the type signature unless you really have to, just follow the examples.
Example usage:
Tests without resources
Pure test
describe "addition" $ it "adds 3 to 5 to result in 8" $ 3 + 5 == 8
IO test
describe "readFile and writeFile" $ it "reads back what it wrote for this example" $ do let cts = "hello world" let fp = "test.txt" writeFile fp cts cts' <- readFile fp cts' `shouldBe` cts
Pure Property test
describe "sort" $ it "is idempotent" $ forAllValid $ \ls -> sort (sort ls) `shouldBe` (sort (ls :: [Int]))
IO Property test
describe "readFile and writeFile" $ it "reads back what it wrote for any example" $ do forAllValid $ \fp -> forAllValid $ \cts -> do writeFile fp cts cts' <- readFile fp cts' `shouldBe` cts
Tests with an inner resource
Pure test
This is quite a rare use-case but here is an example anyway:
before (pure 3) $ describe "addition" $ it "adds 3 to 5 to result in 8" $ \i -> i + 5 == 8
IO test
This test sets up a temporary directory as an inner resource, and makes it available to each test in the group below.
let setUpTempDir func = withSystemTempDir $ \tempDir -> func tempDir in around setUpTempDir describe "readFile and writeFile" $ it "reads back what it wrote for this example" $ \tempDir -> do let cts = "hello world" let fp = tempDir </> "test.txt" writeFile fp cts cts' <- readFile fp cts' `shouldBe` cts
Pure property test
This is quite a rare use-case but here is an example anyway:
before (pure 3) $ describe "multiplication" $ it "is commutative for 5" $ \i -> i * 5 == 5 * 3
IO property test
let setUpTempDir func = withSystemTempDir $ \tempDir -> func tempDir in around setUpTempDir describe "readFile and writeFile" $ it "reads back what it wrote for this example" $ \tempDir -> property $ \cts -> do let fp = tempDir </> "test.txt" writeFile fp cts cts' <- readFile fp cts' `shouldBe` cts
itWithOuter :: (HasCallStack, IsTest test) => String -> test -> TestDefM (Arg2 test ': l) (Arg1 test) () Source #
Declare a test that uses an outer resource
Example usage:
Tests with an outer resource
Pure test
This is quite a rare use-case but here is an example anyway:
beforeAll (pure 3) $ describe "addition" $ itWithBoth "adds 3 to 5 to result in 8" $ \i -> i + 5 == 8
IO test
This test sets up a temporary directory as an inner resource, and makes it available to each test in the group below.
let setUpTempDir func = withSystemTempDir $ \tempDir -> func tempDir in aroundAll setUpTempDir describe "readFile and writeFile" $ itWithBoth "reads back what it wrote for this example" $ \tempDir -> do let cts = "hello world" let fp = tempDir </> "test.txt" writeFile fp cts cts' <- readFile fp cts' `shouldBe` cts
Pure property test
This is quite a rare use-case but here is an example anyway:
beforeAll (pure 3) $ describe "multiplication" $ itWithBoth "is commutative for 5" $ \i -> i * 5 == 5 * 3
IO property test
let setUpTempDir func = withSystemTempDir $ \tempDir -> func tempDir in aroundAll setUpTempDir describe "readFile and writeFile" $ itWithBoth "reads back what it wrote for this example" $ \tempDir -> property $ \cts -> do let fp = tempDir </> "test.txt" writeFile fp cts cts' <- readFile fp cts' `shouldBe` cts
itWithBoth :: (HasCallStack, IsTest test) => String -> test -> TestDefM (Arg1 test ': l) (Arg2 test) () Source #
Declare a test that uses both an inner and an outer resource
Example usage:
Tests with both an inner and an outer resource
Pure test
This is quite a rare use-case but here is an example anyway:
beforeAll (pure 3) $ before (pure 5) $ describe "addition" $ itWithBoth "adds 3 to 5 to result in 8" $ \i j -> i + j == 8
IO test
This test sets up a temporary directory as an inner resource, and makes it available to each test in the group below.
let setUpTempDir func = withSystemTempDir $ \tempDir -> func tempDir in aroundAll setUpTempDir describe "readFile and writeFile" $ before (pure "hello world") $ itWithBoth "reads back what it wrote for this example" $ \tempDir cts -> do let fp = tempDir </> "test.txt" writeFile fp cts cts' <- readFile fp cts' `shouldBe` cts
Pure property test
This is quite a rare use-case but here is an example anyway:
beforeAll (pure 3) $ before (pure 5) $ describe "multiplication" $ itWithBoth "is commutative" $ \i j -> i * j == 5 * 3
IO property test
let setUpTempDir func = withSystemTempDir $ \tempDir -> func tempDir in aroundAll setUpTempDir describe "readFile and writeFile" $ before (pure "test.txt") $ itWithBoth "reads back what it wrote for this example" $ \tempDir fileName -> property $ \cts -> do let fp = tempDir </> fileName writeFile fp cts cts' <- readFile fp cts' `shouldBe` cts
itWithAll :: (HasCallStack, IsTest test, Arg1 test ~ HList l) => String -> test -> TestDefM l (Arg2 test) () Source #
Declare a test that uses all outer resources
You will most likely never need this function, but in case you do:
Note that this will always require a type annotation, along with the GADTs
and ScopedTypeVariables
extensions.
Example usage
beforeAll (pure 'a') $ beforeAll (pure 5) $ itWithAll "example" $ \(HCons c (HCons i HNil) :: HList '[Char, Int]) () -> (c, i) `shouldeBe` ('a', 5)
specify :: forall outers test. (HasCallStack, IsTest test, Arg1 test ~ ()) => String -> test -> TestDefM outers (Arg2 test) () Source #
A synonym for it
specifyWithOuter :: (HasCallStack, IsTest test) => String -> test -> TestDefM (Arg2 test ': l) (Arg1 test) () Source #
A synonym for itWithOuter
specifyWithBoth :: (HasCallStack, IsTest test) => String -> test -> TestDefM (Arg1 test ': l) (Arg2 test) () Source #
A synonym for itWithBoth
specifyWithAll :: (HasCallStack, IsTest test, Arg1 test ~ HList l) => String -> test -> TestDefM l (Arg2 test) () Source #
A synonym for itWithAll
Commented-out tests
xit :: forall outers test. (HasCallStack, IsTest test, Arg1 test ~ ()) => String -> test -> TestDefM outers (Arg2 test) () Source #
xitWithOuter :: (HasCallStack, IsTest test) => String -> test -> TestDefM (Arg2 test ': l) (Arg1 test) () Source #
xitWithBoth :: (HasCallStack, IsTest test) => String -> test -> TestDefM (Arg1 test ': l) (Arg2 test) () Source #
xitWithAll :: (HasCallStack, IsTest test, Arg1 test ~ HList l) => String -> test -> TestDefM l (Arg2 test) () Source #
xspecify :: forall outers test. (HasCallStack, IsTest test, Arg1 test ~ ()) => String -> test -> TestDefM outers (Arg2 test) () Source #
xspecifyWithOuter :: (HasCallStack, IsTest test) => String -> test -> TestDefM (Arg2 test ': l) (Arg1 test) () Source #
xspecifyWithBoth :: (HasCallStack, IsTest test) => String -> test -> TestDefM (Arg1 test ': l) (Arg2 test) () Source #
xspecifyWithAll :: (HasCallStack, IsTest test, Arg1 test ~ HList l) => String -> test -> TestDefM l (Arg2 test) () Source #
Pending tests
pendingWith :: String -> String -> TestDefM a b () Source #
Declare a test that has not been written yet for the given reason.
Environment-based tests
eit :: HasCallStack => String -> ReaderT env IO () -> TestDef l env Source #
For defining a part of a test suite in 'ReaderT IO' instead of in IO
.
This way you can write this:
spec :: Spec spec = around withConnectionPool $ it "can read what it writes" $ \pool -> let person = Person { name = "Dave", age = 25 } i <- runSqlPool (insert person) pool person' <- runSqlPool (get i) pool person' `shouldBe` person
like this instead:
spec :: Spec spec = around withConnectionPool $ eit "can read what it writes" $ do let person = Person { name = "Dave", age = 25 } i <- runDB $ insert person person' <- runDB $ get i liftIO $ person' `shouldBe` person runDB :: ReaderT ConnectionPool IO a -> IO a
Note that you use eit
with a property test. In that case you would have to write it like this:
spec :: Spec spec = around withConnectionPool $ it "can read what it writes" $ \pool -> do forAllValid $ \person -> withTestEnv pool $ do i <- runDB $ insert person person' <- runDB $ get i liftIO $ person' `shouldBe` person
withTestEnv :: env -> ReaderT env IO a -> IO a Source #
Helper function to run a property test with an env
.
withTestEnv = flip runReaderT
Golden tests
pureGoldenByteStringFile :: FilePath -> ByteString -> GoldenTest ByteString Source #
Test that the given bytestring is the same as what we find in the given golden file.
goldenByteStringFile :: FilePath -> IO ByteString -> GoldenTest ByteString Source #
Test that the produced bytestring is the same as what we find in the given golden file.
pureGoldenTextFile :: FilePath -> Text -> GoldenTest Text Source #
Test that the given text is the same as what we find in the given golden file.
goldenTextFile :: FilePath -> IO Text -> GoldenTest Text Source #
Test that the produced text is the same as what we find in the given golden file.
pureGoldenStringFile :: FilePath -> String -> GoldenTest String Source #
Test that the given string is the same as what we find in the given golden file.
goldenStringFile :: FilePath -> IO String -> GoldenTest String Source #
Test that the produced string is the same as what we find in the given golden file.
goldenShowInstance :: Show a => FilePath -> a -> GoldenTest String Source #
Test that the show instance has not changed for the given value.
goldenPrettyShowInstance :: Show a => FilePath -> a -> GoldenTest String Source #
Test that the show instance has not changed for the given value, via ppShow
.
Expectations
shouldBe :: (HasCallStack, Show a, Eq a) => a -> a -> IO () infix 1 Source #
Assert that two values are equal according to ==
.
shouldNotBe :: (HasCallStack, Show a, Eq a) => a -> a -> IO () infix 1 Source #
Assert that two values are not equal according to ==
.
shouldSatisfy :: (HasCallStack, Show a) => a -> (a -> Bool) -> IO () infix 1 Source #
Assert that a value satisfies the given predicate.
shouldSatisfyNamed :: (HasCallStack, Show a) => a -> String -> (a -> Bool) -> IO () Source #
Assert that a value satisfies the given predicate with the given predicate name.
shouldNotSatisfy :: (HasCallStack, Show a) => a -> (a -> Bool) -> IO () infix 1 Source #
Assert that a value does not satisfy the given predicate.
shouldNotSatisfyNamed :: (HasCallStack, Show a) => a -> String -> (a -> Bool) -> IO () Source #
Assert that a value does not satisfy the given predicate with the given predicate name.
shouldReturn :: (HasCallStack, Show a, Eq a) => IO a -> a -> IO () infix 1 Source #
Assert that computation returns the given value (according to ==
).
shouldNotReturn :: (HasCallStack, Show a, Eq a) => IO a -> a -> IO () infix 1 Source #
Assert that computation returns the given value (according to ==
).
shouldStartWith :: (HasCallStack, Show a, Eq a) => [a] -> [a] -> Expectation infix 1 Source #
Assert that the given list has the given prefix
shouldEndWith :: (HasCallStack, Show a, Eq a) => [a] -> [a] -> Expectation infix 1 Source #
Assert that the given list has the given suffix
shouldContain :: (HasCallStack, Show a, Eq a) => [a] -> [a] -> Expectation infix 1 Source #
Assert that the given list has the given infix
expectationFailure :: HasCallStack => String -> IO a Source #
Make a test fail
Note that this is mostly backward compatible, but it has return type a
instead of ()
because execution will not continue beyond this function.
In this way it is not entirely backward compatible with hspec because now there could be an ambiguous type error.
context :: String -> IO a -> IO a Source #
Annotate a given action with a context, for contextual assertions
type Expectation = IO () Source #
For easy hspec migration
shouldThrow :: forall e a. (HasCallStack, Exception e) => IO a -> Selector e -> Expectation infix 1 Source #
Assert that a given IO action throws an exception that matches the given exception
String expectations
stringShouldBe :: HasCallStack => String -> String -> IO () Source #
textShouldBe :: HasCallStack => Text -> Text -> IO () Source #
For throwing raw assertions
bytestringsNotEqualButShouldHaveBeenEqual :: ByteString -> ByteString -> Assertion Source #
An assertion that says two ByteString
s should have been equal according to ==
.
Instances
Declaring test dependencies
Dependencies around all of a group of tests
beforeAll :: IO a -> TestDefM (a ': l) c e -> TestDefM l c e Source #
Run a custom action before all spec items in a group, to set up an outer resource a
.
beforeAll_ :: IO () -> TestDefM a b e -> TestDefM a b e Source #
Run a custom action before all spec items in a group without setting up any outer resources.
beforeAllWith :: (b -> IO a) -> TestDefM (a ': (b ': l)) c e -> TestDefM (b ': l) c e Source #
Run a custom action before all spec items in a group, to set up an outer resource b
by using the outer resource a
.
afterAll :: (a -> IO ()) -> TestDefM (a ': l) b e -> TestDefM (a ': l) b e Source #
Run a custom action after all spec items, using the outer resource a
.
afterAll' :: (HList l -> IO ()) -> TestDefM l b e -> TestDefM l b e Source #
Run a custom action after all spec items, using all the outer resources.
afterAll_ :: IO () -> TestDefM a b e -> TestDefM a b e Source #
Run a custom action after all spec items without using any outer resources.
aroundAll :: ((a -> IO ()) -> IO ()) -> TestDefM (a ': l) c e -> TestDefM l c e Source #
Run a custom action before and/or after all spec items in group, to provide access to a resource a
.
See the FOOTGUN
note in the docs for around_
.
aroundAll_ :: (IO () -> IO ()) -> TestDefM a b e -> TestDefM a b e Source #
Run a custom action before and/or after all spec items in a group without accessing any resources.
FOOTGUN
This combinator gives the programmer a lot of power. In fact, it gives the programmer enough power to break the test framework. Indeed, you can provide a wrapper function that just _doesn't_ run the function like this:
spec :: Spec spec = do let don'tDo :: IO () -> IO () don'tDo _ = pure () aroundAll_ don'tDo $ do it "should pass" True
During execution, you'll then get an error like this:
thread blocked indefinitely in an MVar operation
The same problem exists when using around_
.
Something even more pernicious goes wrong when you run the given action more than once like this:
spec :: Spec spec = do let doTwice :: IO () -> IO () doTwice f = f >> f aroundAll_ doTwice $ do it "should pass" True
In this case, the test will "just work", but it will be executed twice even if the output reports that it only passed once.
Note: If you're interested in fixing this, talk to me, but only after GHC has gotten impredicative types because that will likely be a requirement.
aroundAllWith :: forall a b c l r. ((a -> IO ()) -> b -> IO ()) -> TestDefM (a ': (b ': l)) c r -> TestDefM (b ': l) c r Source #
Run a custom action before and/or after all spec items in a group to provide access to a resource a
while using a resource b
See the FOOTGUN
note in the docs for around_
.
Dependencies around each of a group of tests
before :: IO c -> TestDefM a c e -> TestDefM a () e Source #
Run a custom action before every spec item, to set up an inner resource c
.
before_ :: IO () -> TestDefM a c e -> TestDefM a c e Source #
Run a custom action before every spec item without setting up any inner resources.
after :: (c -> IO ()) -> TestDefM a c e -> TestDefM a c e Source #
Run a custom action after every spec item, using the inner resource c
.
after_ :: IO () -> TestDefM a c e -> TestDefM a c e Source #
Run a custom action after every spec item without using any inner resources.
around :: ((c -> IO ()) -> IO ()) -> TestDefM a c e -> TestDefM a () e Source #
Run a custom action before and/or after every spec item, to provide access to an inner resource c
.
See the FOOTGUN
note in the docs for around_
.
around_ :: (IO () -> IO ()) -> TestDefM a c e -> TestDefM a c e Source #
Run a custom action before and/or after every spec item without accessing any inner resources.
It is important that the wrapper function that you provide runs the action that it gets _exactly once_.
FOOTGUN
This combinator gives the programmer a lot of power. In fact, it gives the programmer enough power to break the test framework. Indeed, you can provide a wrapper function that just _doesn't_ run the function like this:
spec :: Spec spec = do let don'tDo :: IO () -> IO () don'tDo _ = pure () around_ don'tDo $ do it "should pass" True
During execution, you'll then get an error like this:
thread blocked indefinitely in an MVar operation
The same problem exists when using aroundAll_
.
The same thing will go wrong if you run the given action more than once like this:
spec :: Spec spec = do let doTwice :: IO () -> IO () doTwice f = f >> f around_ doTwice $ do it "should pass" True
Note: If you're interested in fixing this, talk to me, but only after GHC has gotten impredicative types because that will likely be a requirement.
aroundWith :: forall a c d r. ((c -> IO ()) -> d -> IO ()) -> TestDefM a c r -> TestDefM a d r Source #
Run a custom action before and/or after every spec item, to provide access to an inner resource c
while using the inner resource d
.
See the FOOTGUN
note in the docs for around_
.
Setup functions
Using setup functions
setupAroundWith :: SetupFunc d c -> TestDefM a c e -> TestDefM a d e Source #
Use aroundWith
with a SetupFunc
setupAroundWith' :: HContains l a => (a -> SetupFunc d c) -> TestDefM l c e -> TestDefM l d e Source #
Use aroundWith'
with a SetupFunc
Creating setup functions
newtype SetupFunc b a Source #
A function that can provide an a
given a b
.
You can think of this as a potentially-resource-aware version of 'b -> IO a'.
SetupFunc | |
|
makeSimpleSetupFunc :: (forall r. (a -> IO r) -> IO r) -> SetupFunc () a Source #
Turn a simple provider function into a SetupFunc
.
This works together nicely with most supplier functions. Some examples:
useSimpleSetupFunc :: SetupFunc () a -> forall r. (a -> IO r) -> IO r Source #
Use a 'SetupFunc ()' as a simple provider function.
This is the opposite of the makeSimpleSetupFunc
function
connectSetupFunc :: SetupFunc c b -> SetupFunc b a -> SetupFunc c a Source #
Connect two setup functions.
This is basically 'flip (.)' but for SetupFunc
s.
It's exactly 'flip composeSetupFunc'.
wrapSetupFunc :: (b -> SetupFunc () a) -> SetupFunc b a Source #
Wrap a function that produces a SetupFunc
to into a SetupFunc
.
This is useful to combine a given 'SetupFunc b' with other 'SetupFunc ()'s as follows:
mySetupFunc :: SetupFunc B A mySetupFunc = wrapSetupFunc $ \b -> do r <- setupSomething c <- setupSomethingElse b r pure $ somehowCombine c r setupSomething :: SetupFunc () R setupSomething :: B -> R -> SetupFunc () C somehowCombine :: C -> R -> A
unwrapSetupFunc :: SetupFunc b a -> b -> SetupFunc () a Source #
Unwrap a SetupFunc
into a function that produces a SetupFunc
This is the opposite of wrapSetupFunc
.
Declaring different test settings
modifyRunSettings :: (TestRunSettings -> TestRunSettings) -> TestDefM a b c -> TestDefM a b c Source #
data TestRunSettings Source #
Instances
Declaring parallelism
sequential :: TestDefM a b c -> TestDefM a b c Source #
Declare that all tests below must be run sequentially
parallel :: TestDefM a b c -> TestDefM a b c Source #
Declare that all tests below may be run in parallel. (This is the default.)
withParallelism :: Parallelism -> TestDefM a b c -> TestDefM a b c Source #
Declaring randomisation order
randomiseExecutionOrder :: TestDefM a b c -> TestDefM a b c Source #
doNotRandomiseExecutionOrder :: TestDefM a b c -> TestDefM a b c Source #
withExecutionOrderRandomisation :: ExecutionOrderRandomisation -> TestDefM a b c -> TestDefM a b c Source #
Doing IO during test definition
Test definition types
newtype TestDefM a b c Source #
The test definition monad
This type has three parameters:
a
: The type of the result ofaroundAll
b
: The type of the result ofaround
c
: The result
In practice, all of these three parameters should be ()
at the top level.
TestDefM | |
|
Instances
execTestDefM :: Settings -> TestDefM a b c -> IO (TestForest a b) Source #
runTestDefM :: Settings -> TestDefM a b c -> IO (c, TestForest a b) Source #
Test suite types
TDef | |
|
Instances
Functor TDef Source # | |
Foldable TDef Source # | |
Defined in Test.Syd.SpecDef fold :: Monoid m => TDef m -> m # foldMap :: Monoid m => (a -> m) -> TDef a -> m # foldMap' :: Monoid m => (a -> m) -> TDef a -> m # foldr :: (a -> b -> b) -> b -> TDef a -> b # foldr' :: (a -> b -> b) -> b -> TDef a -> b # foldl :: (b -> a -> b) -> b -> TDef a -> b # foldl' :: (b -> a -> b) -> b -> TDef a -> b # foldr1 :: (a -> a -> a) -> TDef a -> a # foldl1 :: (a -> a -> a) -> TDef a -> a # elem :: Eq a => a -> TDef a -> Bool # maximum :: Ord a => TDef a -> a # | |
Traversable TDef Source # | |
type TestForest a c = SpecDefForest a c () Source #
type TestTree a c = SpecDefTree a c () Source #
type SpecDefForest (a :: [Type]) c e = [SpecDefTree a c e] Source #
data SpecDefTree (a :: [Type]) c e where Source #
DefSpecifyNode :: Text -> TDef (((HList a -> c -> IO ()) -> IO ()) -> IO TestRunResult) -> e -> SpecDefTree a c e | |
DefPendingNode :: Text -> Maybe Text -> SpecDefTree a c e | |
DefDescribeNode :: Text -> SpecDefForest a c e -> SpecDefTree a c e | |
DefWrapNode :: (IO () -> IO ()) -> SpecDefForest a c e -> SpecDefTree a c e | |
DefBeforeAllNode :: IO a -> SpecDefForest (a ': l) c e -> SpecDefTree l c e | |
DefAroundAllNode :: ((a -> IO ()) -> IO ()) -> SpecDefForest (a ': l) c e -> SpecDefTree l c e | |
DefAroundAllWithNode :: ((b -> IO ()) -> a -> IO ()) -> SpecDefForest (b ': (a ': l)) c e -> SpecDefTree (a ': l) c e | |
DefAfterAllNode :: (HList a -> IO ()) -> SpecDefForest a c e -> SpecDefTree a c e | |
DefParallelismNode :: Parallelism -> SpecDefForest a c e -> SpecDefTree a c e | |
DefRandomisationNode :: ExecutionOrderRandomisation -> SpecDefForest a c e -> SpecDefTree a c e |
Instances
Functor (SpecDefTree a c) Source # | |
Defined in Test.Syd.SpecDef fmap :: (a0 -> b) -> SpecDefTree a c a0 -> SpecDefTree a c b # (<$) :: a0 -> SpecDefTree a c b -> SpecDefTree a c a0 # | |
Foldable (SpecDefTree a c) Source # | |
Defined in Test.Syd.SpecDef fold :: Monoid m => SpecDefTree a c m -> m # foldMap :: Monoid m => (a0 -> m) -> SpecDefTree a c a0 -> m # foldMap' :: Monoid m => (a0 -> m) -> SpecDefTree a c a0 -> m # foldr :: (a0 -> b -> b) -> b -> SpecDefTree a c a0 -> b # foldr' :: (a0 -> b -> b) -> b -> SpecDefTree a c a0 -> b # foldl :: (b -> a0 -> b) -> b -> SpecDefTree a c a0 -> b # foldl' :: (b -> a0 -> b) -> b -> SpecDefTree a c a0 -> b # foldr1 :: (a0 -> a0 -> a0) -> SpecDefTree a c a0 -> a0 # foldl1 :: (a0 -> a0 -> a0) -> SpecDefTree a c a0 -> a0 # toList :: SpecDefTree a c a0 -> [a0] # null :: SpecDefTree a c a0 -> Bool # length :: SpecDefTree a c a0 -> Int # elem :: Eq a0 => a0 -> SpecDefTree a c a0 -> Bool # maximum :: Ord a0 => SpecDefTree a c a0 -> a0 # minimum :: Ord a0 => SpecDefTree a c a0 -> a0 # sum :: Num a0 => SpecDefTree a c a0 -> a0 # product :: Num a0 => SpecDefTree a c a0 -> a0 # | |
Traversable (SpecDefTree a c) Source # | |
Defined in Test.Syd.SpecDef traverse :: Applicative f => (a0 -> f b) -> SpecDefTree a c a0 -> f (SpecDefTree a c b) # sequenceA :: Applicative f => SpecDefTree a c (f a0) -> f (SpecDefTree a c a0) # mapM :: Monad m => (a0 -> m b) -> SpecDefTree a c a0 -> m (SpecDefTree a c b) # sequence :: Monad m => SpecDefTree a c (m a0) -> m (SpecDefTree a c a0) # | |
MonadWriter (TestForest a b) (TestDefM a b) Source # | |
Defined in Test.Syd.Def.TestDefM writer :: (a0, TestForest a b) -> TestDefM a b a0 # tell :: TestForest a b -> TestDefM a b () # listen :: TestDefM a b a0 -> TestDefM a b (a0, TestForest a b) # pass :: TestDefM a b (a0, TestForest a b -> TestForest a b) -> TestDefM a b a0 # |
type ResultForest = SpecForest (TDef (Timed TestRunResult)) Source #
type ResultTree = SpecTree (TDef (Timed TestRunResult)) Source #
shouldExitFail :: ResultForest -> Bool Source #
Hspec synonyms
Utilities
Reexports
module Test.Syd.Def
module Test.Syd.Expectation
module Test.Syd.HList
module Test.Syd.Modify
module Test.Syd.Output
module Test.Syd.Run
module Test.Syd.Runner
module Test.Syd.SpecDef
module Test.Syd.SpecForest
module Control.Monad.IO.Class