hspec 1.8.3 → 2.11.17
raw patch · 48 files changed
Files
- CHANGES.markdown +812/−0
- LICENSE +1/−1
- example/Spec.hs +0/−16
- hspec-discover/src/Config.hs +0/−43
- hspec-discover/src/Main.hs +0/−8
- hspec-discover/src/Run.hs +0/−132
- hspec-discover/test-data/empty-dir/Foo/Bar/Baz/.placeholder +0/−0
- hspec-discover/test-data/nested-spec/Foo/Bar/BazSpec.hs +0/−0
- hspec-discover/test-data/nested-spec/Foo/BarSpec.hs +0/−0
- hspec-discover/test-data/nested-spec/FooSpec.hs +0/−0
- hspec-discover/test/ConfigSpec.hs +0/−47
- hspec-discover/test/RunSpec.hs +0/−100
- hspec-discover/test/Spec.hs +0/−1
- hspec.cabal +36/−148
- src/Test/Hspec.hs +52/−49
- src/Test/Hspec/Compat.hs +0/−79
- src/Test/Hspec/Config.hs +0/−118
- src/Test/Hspec/Core.hs +0/−73
- src/Test/Hspec/Core/QuickCheckUtil.hs +0/−28
- src/Test/Hspec/Core/Type.hs +0/−176
- src/Test/Hspec/Discover.hs +35/−0
- src/Test/Hspec/FailureReport.hs +0/−36
- src/Test/Hspec/Formatters.hs +7/−233
- src/Test/Hspec/Formatters/Internal.hs +0/−263
- src/Test/Hspec/HUnit.hs +0/−39
- src/Test/Hspec/Monadic.hs +0/−53
- src/Test/Hspec/Options.hs +0/−157
- src/Test/Hspec/QuickCheck.hs +39/−38
- src/Test/Hspec/Runner.hs +2/−163
- src/Test/Hspec/Runner/Eval.hs +0/−125
- src/Test/Hspec/Timer.hs +0/−14
- src/Test/Hspec/Util.hs +0/−106
- test/Helper.hs +0/−81
- test/Mock.hs +0/−15
- test/Spec.hs +0/−1
- test/Test/Hspec/CompatSpec.hs +0/−33
- test/Test/Hspec/Core/TypeSpec.hs +0/−133
- test/Test/Hspec/FailureReportSpec.hs +0/−39
- test/Test/Hspec/FormattersSpec.hs +0/−220
- test/Test/Hspec/HUnitSpec.hs +0/−79
- test/Test/Hspec/OptionsSpec.hs +0/−44
- test/Test/Hspec/QuickCheckSpec.hs +0/−19
- test/Test/Hspec/RunnerSpec.hs +0/−393
- test/Test/Hspec/TimerSpec.hs +0/−29
- test/Test/Hspec/UtilSpec.hs +0/−108
- test/Test/HspecSpec.hs +0/−146
- test/doctests.hs +0/−6
- version.yaml +7/−0
+ CHANGES.markdown view
@@ -0,0 +1,812 @@+## Changes in 2.11.17 (2026-03-04)+ - Compatibility with QuickCheck 2.18++## Changes in 2.11.16 (2025-12-12)+ - Add support for MicroHs++## Changes in 2.11.15 (2025-12-08)+ - Remove redundant `tf-random` dependency++## Changes in 2.11.14 (2025-09-30)+ - Make sure that `--pretty` completes in *O(n)* time++## Changes in 2.11.13 (2025-09-15)+ - Make diff algorithm line based+ - Improve pretty-printing of nested records++## Changes in 2.11.12 (2025-03-17)+ - Add `--no-rerun` and `--no-rerun-all-on-success`++## Changes in 2.11.11 (2025-02-17)+ - Compatibility with GHC 9.12++## Changes in 2.11.10 (2024-11-16)+ - Add (experimental) extensions API+ - Handle small terminal sizes more gracefully when reporting progress+ - Correctly indent multi-line pending messages+ - Use "erase in line" ANSI sequence to clear transient output (instead of+ overwriting it with spaces)++## Changes in 2.11.9 (2024-05-24)+ - Compatibility with GHC 9.10.1+ - Drop support for GHC 7.10.3++## Changes in 2.11.8 (2024-04-22)+ - Make the build pass with QuickCheck 2.15++## Changes in 2.11.7 (2023-10-22)+ - Include `--seed` in the note on how to rurun a failing item.++## Changes in 2.11.6 (2023-10-11)+ - Compatibility with GHC 9.8.1+ - Run cleanup actions on `--fail-fast` (see #860)++## Changes in 2.11.5 (2023-09-20)+ - Add `--show-exceptions` and `--display-exceptions`++## Changes in 2.11.4 (2023-07-20)+ - Depend on `hspec-expectations-0.8.4`++## Changes in 2.11.3 (2023-07-10)+ - Suppress informational output from QuickCheck when+ `Test.QuickCheck.Args.chatty` is `False` (#840)++## Changes in 2.11.2 (2023-07-06)+ - Add `--expert` mode++## Changes in 2.11.1 (2023-05-28)+ - Depend on `hspec-expectations-0.8.3`++## Changes in 2.11.0.1 (2023-04-28)+ - Don't crash when home directories are unsupported (WASM/WASI) (thanks+ @amesgen)++## Changes in 2.11.0 (2023-04-21)+ - Drop support for GHC < 7.10.3+ - Improve coloring of whitespace-only segments on `--diff`+ - Add `ColorizedReason` constructor to `FailureReason`+ - Provide a new package `hspec-api`, a stable API that can be used to extend+ Hspec's functionality.+ - Deprecate `Test.Hspec.Core.Formatters.V1` in favor of+ `Test.Hspec.Api.Formatters.V1`+ - Add `--fail-on=empty-description`+ - Print slow spec items to `stderr` instead of `stdout`+ - Handle quoting/escaping in `.hspec` files+ - Flush output handle after reporting progress on `-fprogress`++## Changes in 2.10.10 (2023-03-07)+ - Re-export `sequential` from `Test.Hspec`+ - Rerun `beforeAll` / `afterAll` on `--rerun-all-on-success` (#768)++## Changes in 2.10.9 (2023-01-13)+ - Print error message on `-—fail-on=empty`+ - Only fail on `-—fail-on=empty` if at least one spec item has been filtered+ - Re-export more types from `Test.Hspec.Core.Runner`+ - Fix a pretty-printing bug where `[]` would be pretty-printed as `""`+ - Don't pretty-print if the expected and actual value would be equal after+ pretty-printing+ - Prevent deadlocks on unguarded exceptions in runner (#771)++## Changes in 2.10.8 (2022-12-19)+ - Add pretty-printing support for rational numbers+ - Force / evaluate exceptions recursively (#763)+ - Add `xprop` and `fprop`, which use `xit` and `fit` (thanks @lehins)++## Changes in 2.10.7 (2022-12-03)+ - Do not depend on `ghc` for pretty-printing (#750, #752)++## Changes in 2.10.6 (2022-09-13)+ - Suppress excessive diff output (#449)+ - Allow the use of an external diff program. This can e.g. be used by+ setting `HSPEC_DIFF_COMMAND="diff -u --color -L expected -L actual"` or+ `HSPEC_DIFF_COMMAND="git diff"`+ - Do not imply `--fail-on=empty` on `--strict`++## Changes in 2.10.5 (2022-09-09)+ - Add `--fail-on`. This subsums `--fail-on-focused` and `--fail-on-pending`.+ - Add `--fail-on=empty` (#650)+ - Add `registerFormatter` and `registerDefaultFormatter` to+ `Test.Hspec.Runner`.+ - Revert deprecation of `Test.Hspec.Formatters` and+ `Test.Hspec.Core.Formatters`. Instead the module documentation now says+ that they are deprecated in favor of `Test.Hspec.Core.Formatters.V1`.++## Changes in 2.10.4 (2022-09-06)+ - Make sure that whitespace-only diff output is colorized properly (#660)++## Changes in 2.10.3 (2022-09-05)+ - Deprecate `Test.Hspec.Formatters` and `Test.Hspec.Core.Formatters`+ - Disable (most) warnings in files generated by `hspec-discover` (#702)++## Changes in 2.10.2 (2022-09-03)+ - Add `--strict`+ - Add `--fail-on-pending`+ - Do not depend on `clock`++## Changes in 2.10.1 (2022-08-22)+ - Support for GHC 9.4.1+ - Generated modules now include an export list++## Changes in 2.10.0.1 (2022-08-06)+ - Fix a deadlock with nested failed `aroundAll`s (see #679)++## Changes in 2.10.0 (2022-05-12)+ - Allow to transform the config in `SpecM`+ - Allow to customize pretty-printing (via `configPrettyPrintFunction`)+ - Add `getSpecDescriptionPath` (#637, thanks @srid)+ - Do not treat `afterAll` as another spec item (fixes #414, #364, #363)+ - Change type of `paramsSmallCheckDepth` to Maybe (see #345)++## Changes in 2.9.7+ - Ensure that interim output does not interfere with output from tests This+ facilitates using `print` when debugging test cases.++## Changes in 2.9.6+ - Ensure color codes don't span newlines (#346, thanks @robx)+ - Disable progress reporting on Buildkite+ - Improve error messages on exceptions in hooks++## Changes in 2.9.5+ - Assume `--color` by default when running on GitHub Actions. Use+ `HSPEC_COLOR=no` or `--no-color` to opt out of this behavior.+ - Disable progress reporting on GitHub Actions.+ - Retain source formatting of numbers when pretty-printing.++## Changes in 2.9.4+ - Compatibility with GHCJS (see #599)++## Changes in 2.9.3+ - Pretty-print Haskell values in failure messages++## Changes in 2.9.2+ - Show multi-line diffs for string literals (disable with `--no-pretty`)++## Changes in 2.9.1+ - Recover unicode from `ExpectedButGot`+ - Preserve unicode in `To rerun use: --match ...` output++## Changes in 2.9.0+ - Add ASCII fallbacks to "checks" formatter (fixes #512)+ - Use `checks` formatter by default (to restore the old behavior use+ `--format specdoc`)+ - Allow to extend the list of available formatters for `--format`+ (`configAvailableFormatters`)+ - Add `getExpectedTotalCount` to `Test.Hspec.Core.Formatters.V2`+ - Rename `formatConfigItemCount` to `formatConfigExpectedTotalCount`+ - Rename `configFastFail` to `configFailFast`++## Changes in 2.8.5+ - hspec-core: Include help.txt in package tarball (close #568)+ - hspec-discover: Require base >=4.5.0.0 (fixes #554)++## Changes in 2.8.4+ - Better support for GHC 9.2.1+ - Support for setting options by individual environment variables, e.g.+ `HSPEC_COLOR=yes` will set `--color`++## Changes in 2.8.3+ - Better support for `--color=auto` on Windows+ - Add support for spec hooks to `hspec-discover` (via `SpecHook.hs`)+ - Propagate exceptions from `Test.Hspec.Core.Format.monadic`+ - Re-export `aroundAll_` from `Test.Hspec`++## Changes in 2.8.2+ - Add `mapSubject` and `ignoreSubject`++## Changes in 2.8.1+ - Take the environment variable `NO_COLOR` into account++## Changes in 2.8.0+ - Add `--times` to print times for individual spec items+ - Add `--print-slow-items`+ - Use `-XNoImplicitPrelude` and do not rely on `base` for `hspec-discover`+ generated test drivers. This ensures full compatibility with custom+ preludes.+ - Add new APIs for formatters `Test.Hspec.Core.Format` and+ `Test.Hspec.Core.Formatters.V2`+ - Add `getItemCount` to `Formatter` API+ - Add `--qc-max-shrinks` (see #380)+ - Add location information for failing `afterAll`-hooks+ - hspec-discover: Deprecate `--no-main` and `--formatter` (use+ `--module-name` instead) (#196)+ - Remove `--verbose` option (this has been a noop since at least 2013)+ - Remove `--out` option (use shell output redirection instead)++## Changes in 2.7.10+ - Add a new formatter (can be used with `--format checks`)+ - Add `exampleStarted` to `Formatter` API++## Changes in 2.7.9+ - Re-export `aroundAll` and `aroundAllWith` from `Test.Hspec`++## Changes in 2.7.8+ - Add `aroundAll` / `aroundAllWith` (see #255)++## Changes in 2.7.7+ - Add `aroundAll_` (see #255)+ - Correctly handle pending for `afterAll` actions++## Changes in 2.7.6+ - Add `beforeAllWith` (see #447)++## Changes in 2.7.5+ - Extract source locations from `NoMethodError` and `AssertionFailed`++## Changes in 2.7.4+ - Apply `--randomize` recursively++## Changes in 2.7.3+ - Add `--randomize`++## Changes in 2.7.2+ - Interrupt diff calculation if it takes longer than two seconds (see #415)++## Changes in 2.7.1+ - Add compatibility with QuickCheck 2.13.1 (see #410)++## Changes in 2.7.0+ - Add `--focused-only` (see #390)+ - Add `--fail-on-focused` (see #389)++## Changes in 2.6.1+ - Add `Test.Hspec.Runner.runSpec` (see #216)++## Changes in 2.6.0+ - Allow to focus individual spec items (see #319)+ - Do not calculate diff on `--no-diff` (see #332)+ - Remove deprecated module Test.Hspec.Core++## Changes in 2.5.9+ - Extract source locations from RecConError (see #375)++## Changes in 2.5.8+ - Add `modifyArgs` and `modifyMaxShrinks` to `Test.Hspec.QuickCheck` (see #380)++## Changes in 2.5.7+ - GHC 8.6.1 related changes++## Changes in 2.5.6+ - Compatibility with `QuickCheck-2.12`++## Changes in 2.5.5+ - Use `module[line:column]` instead of `module:line:column` as default label+ for `describe`/`it` (fixes #366)++## Changes in 2.5.4+ - Show how to rerun individual spec items on test failures (see #205)++## Changes in 2.5.3+ - Treat character escapes like `\NUL` as single tokens on `--diff` (see #351)+ - Allow a `/` at the beginning and at the end of an absolute path that is+ passed to `--match` or `--skip`++## Changes in 2.5.2+ - Use module:line:column as default label for describe/it (see #250)+ - Warn if user is affected by https://ghc.haskell.org/trac/ghc/ticket/13285 (see #329)++## Changes in 2.5.1+ - Disable tests for Test.Hspec.Core.Timer (see #352)++## Changes in 2.5.0+ - Add `sequential` (see #311)+ - Add support for `--diff` when `shouldBe` is uesd with+ `QuickCheck`-properties+ - Add source locations when `shouldBe` is uesd with `QuickCheck` properties+ - Print `QuickCheck` labels on success (see #297)+ - Retain output of `verbose`, `label`, `collect`, `classify`, etc. for+ `QuickCheck` properties (see #257)+ - Extract source location from error / undefined (see #316)+ - Parse source locations from pattern match failures+ - Include source column when formatting source locations+ - Colorize whitespaces with background color instead of foreground color with+ `--diff`+ - Run `Test.Hspec.Core.Formatters.exampleProgress` in `FormatM` instead of+ `IO`+ - Make sure that progress output is always cleared (fixes #301)+ - Add location information to `pending` (not used by any formatter yet)+ - Include duration for each spec item in new formatter API (see #315) (not yet exposed)+ - Removed deprecated module `Test.Hspec.HUnit`, use+ `Test.Hspec.Contrib.HUnit` instead+ - Deprecate `--out`+ - Remove `BestEffort` source locations++## Changes in 2.4.8+ - compatibility with GHC 8.4.1-alpha3++## Changes in 2.4.7+ - compatibility with `QuickCheck-2.11.3` and up (note that `QuickCheck`+ versions `2.11` to `2.11.2` are not fully supported)++## Changes in 2.4.6+ - compatibility with the upcoming version `4.11.0.0` of `base`++## Changes in 2.4.5+ - `hspec-discover`: Sort specs using natural sort order++## Changes in 2.4.4+ - Require quickcheck-io >= 0.2.0++## Changes in 2.4.3+ - Read command-line options from environment variable `HSPEC_OPTIONS`++## Changes in 2.4.2+ - Use `--diff` by default+ - Add `--failure-report` (see #266)++## Changes in 2.4.1+ - Compatibility with HUnit < 1.3++## Changes in 2.4.0+ - Read command-line options from config files `~/.hspec` and `.hspec`+ - Add support for `--diff`+ - Add `xit`, `xspecify`, `xdescribe` and `xcontext` (see #252)+ - Add `--rerun-all-on-success`+ - Report exceptions in `beforeAll` operations only once+ - Add indentation when actual/expected contain newlines (see #263)+ - More graceful shutdown on ctrl-c (see #270)+ - Run around-hook for Bool and Result (see #252)+ - Include `CHANGES.markdown` in package tarball++Internal changes:++ - Rename `Fail` constructor of `Result`-type to `Failure`+ - Add `FailureReason` type+ - Add `Test.Hspec.Core.Spec.safeEvaluateExample`++## Changes in 2.3.2+ - Compatibility with HUnit 1.5++## Changes in 2.3.1+ - Fix build for HUnit < 1.4++## Changes in 2.3.0+ - Proper support for GHC 8 call stacks++## Changes in 2.2.4+ - Compatibility with QuickCheck-2.9++## Changes in 2.2.3+ - Make sure that `cabal haddock` works for `hspec-discover`+ - Forward compatibility for HUnit 1.4+ - Fix tests for GHC 8.0.1-rc1++## Changes in 2.2.2+ - Fix compilation for GHC 8.0.1-rc1++## Changes in 2.2.1+ - Make sure that Vim's default `errorformat` recognizes exact locations+ - GHCJS compatibility++## Changes in 2.2.0+ - Add source locations to test `Result`++## Changes in 2.1.10+ - GHC 7.0.* compatibility++## Changes in 2.1.9+ - Make use of GHC 7.10.2 source locations+ - Add `--jobs`++## Changes in 2.1.8+ - Depend on `hspec-expectations-0.7.0"++## Changes in 2.1.7+ - Add `beforeAll_`++## Changes in 2.1.6+ - If there were no previous failures, run all spec items on `--rerun`++## Changes in 2.1.5+ - Compatibility with QuickCheck-2.8++## Changes in 2.1.4+ - Make `hspec-discover` ignore modules with invalid module names, this fixes+ issues with `flycheck`'s temporary files++## Changes in 2.1.3+ - Format source locations like gcc does++## Changes in 2.1.2+ - Re-export `before_` from `Test.Hspec`++## Changes in 2.1.1+ - Add `before_`+ - Add command-line option `--skip`++## Changes in 2.1.0+ - Generalize `after_`, `afterAll_` and `around_`++## Changes in 2.0.2+ - Indent error messages for failed examples (fixes #186)+ - Export `defaultParams` from `Test.Hspec.Core.Example`+ - Bring back `Test.Hspec.HUnit` and deprecate it to provide a smother upgrade+ path++## Changes in 2.0.1+ - Add missing extra source files to for `hspec-discover`++## Changes in 2.0.0+ - Split package into `hspec`, `hspec-core` and `hspec-discover`+ - Allow hooks (`before`, `around`, etc.) to pass arguments to spec items+ - Do not print `-` in front of spec items with `specdoc` formatter+ - Move `Test.Hspec.HUnit` to `hspec-contrib`++## Changes in 1.12.4+ - Add `specGroup` and `specItem` to `Test.Hspec.Core`+ - Deprecate `Test.Hspec.Core.it` and `Test.Hspec.Core.describe`++## Changes in 1.12.3+ - Make `hspec-discover` work with `-XNoImplicitPrelude`++## Changes in 1.12.2+ - Include `IOErrorType` when printing uncaught `IOException`s (see #204)++## Changes in 1.12.1+ - Add `--module-name` option to `hspec-discover` (see #168)++## Changes in 1.12.0+ - Add optional source location to spec items+ - Move item requirement text from `SpecItem` constructor to `Item` data type+ - Remove `BuildSpecs` constructor from `SpecTree`, having `runIO` this is not+ really needed+ - Add `mapSpecTree` to `Test.Hspec.Core`+ - Add `afterAll` (see #188)+ - Do not return `Result` from `hspecWith` and accept command-line options+ (the old behavior is still available as `hspecWithResult`)+ - Rename `configHandle` to `configOutputFile`+ - Omit empty `describe` groups from report+ - Do not pass position to `Formatter.exampleGroupStarted` (we can not support+ this with the upcomming cleanup actions #188)+ - Do not print empty lines before/after spec groups+ - Deprecate `Test.Hspec.Formatters.newParagraph`++## Changes in 1.11.4+ - Make test suite independent from QuickCheck seed (see #187)++## Changes in 1.11.3+ - Depend on `hspec-expectations-0.6.1`++## Changes in 1.11.2+ - Add `beforeAll`++## Changes in 1.11.1+ - Add `specify` as an alias for `it`++## Changes in 1.11.0+ - Add `BuildSpecs` constructor to internal `SpecTree` data structure. This+ allows you to do `IO` while constructing the spec tree.+ - Add `runIO`++## Changes in 1.10.0+ - Do not use exception type to distinguish between synchronous/asynchronous+ exceptions (thanks to Michael Snoyman)+ - Remove `Example` instance for `Test.HUnit.Test` (#101), use+ `Test.Hspec.HUnit.fromHUnitTest` instead.+ - Do not reexport `property` from `Test.Hspec.QuickCheck`+ - Move `ProgressCallback` out of `Params`+ - Add show instance for `Params`+ - Move requirement text from `Item` to `SpecItem` constructor+ - Remove deprecated modules and functions++## Changes in 1.9.5+ - Make sure that ctrl-c works properly with GHC 7.8.* and QuickCheck-2.6++## Changes in 1.9.4+ - Compatibility with transformers-0.4.0.0++## Changes in 1.9.3+ - Make internal Tree data structure more strict (#169)++## Changes in 1.9.2+ - Print type of exceptions that are raised from QuickCheck properties (#94)++## Changes in 1.9.1+ - Bring back compatibility with older versions of QuickCheck (#166)++## Changes in 1.9.0+ - Depend on QuickCheck 2.7++## Changes in 1.8.3+ - Do not use color if `TERM=dumb` (see #158)++## Changes in 1.8.2+ - `hspec-discover` now accepts `--no-main` which results in a top-level spec+ being generated instead of a test driver (thanks @DanielG)+ - Make sure that `after` is run on failing tests (see #159)++## Changes in 1.8.1+ - Add `shouldMatchList`++## Changes in 1.8.0+ - Run `before`/`after`/`around` for each single check of a QuickCheck property+ - Add `Test.Hspec.Core.mapSpecItem`+ - Add `modifyMaxSuccess`, `modifyMaxDiscardRatio` and `modifyMaxSize` to+ `Test.Hspec.QuickCheck`+ - Don't fail if callback is not called in `around`+ - `hspec-discover`: Remove `--nested` option+ - `hspec-discover`: Ignore `Spec.hs`/`Spec.lhs`++## Changes in 1.7.2+ - Add `after` and `around`++## Changes in 1.7.1+ - Add `shouldContain` (thanks to Alfredo Di Napoli)+ - When printing progress, skip total if it is 0+ - Do not colorize the description/requirement in failure list++## Changes in 1.7.0+ - Add `--depth` for use with `hspec-smallcheck`++## Change in 1.6.2+ - Add `before`+ - Add `--qc-max-discard` and `--qc-max-size`++## Changes in 1.6.1+ - Allow to specify the output file with `--out`++## Changes in 1.6.0+ - Add support for parallelization+ - Change license to MIT+ - Add MonadIO instance for FormatM+ - Add support for custom formatters to hspec-discover+ - Add hspecResult+ - Rename `--re-run` to `--rerun` + add documentation (#95)+ - Remove `configVerbose`+ - Use same `--qc-max-success` on `--rerun` (#125)+ - Add command-line option `--no-color`, `--color` does not accept arguments+ anymore (#130)++## Changes in 1.5.4+ - Make sure that QuickCheck is never chatty+ - Make sure progress for QuickCheck examples is shown++## Changes in 1.5.3+ - Print "Randomized with seed ..." only once++## Changes in 1.5.2+ - Add `--seed`, it can be used to specify the seed for QuickCheck properties+ - Reuse previous seed on `--re-run`++## Changes in 1.5.1+ - Depend on quickcheck-io++## Changes in 1.5.0+ - Allow to use expectations as QuickCheck properties (#80)+ - Do not suppress output to `stdout`+ - Change type of `pending` to `Expectation`, add `pendingWith` (#121)+ - Add the `example` function, it fixes the type of an Expectation (#86)+ - Rename `--fast-fail` to `--fail-fast` (for consistency with RSpec)+ - Do not clutter Cabal test suite logs with QuickCheck output (#112)+ - Skip redundant output from QuickCheck failure messages (#102)++## Changes in 1.4.5+ - hspec-discover now discovers .lhs files, too++## Changes in 1.4.4+ - Visually distinguish error message from requirements in the summary (#100)+ - Export `formatException` from `Test.Hspec.Formatters`+ - Add `--fast-fail` (#82)+ - Print a summary on UserInterrupt/ctrl-c (#107)++## Changes in 1.4.3+ - Add `--dry-run` (#111)++## Changes in 1.4.2+ - Properly handle ctrl-c while running QuickCheck properties (#93)+ - Default to `--color=always` when `--color` is used without argument (#106)+ - treat `--qc-max-success` as an alias for `--maximum-generated-tests`++## Changes in 1.4.1+ - Used CPU time is now only included in the test summary if run with+ `--print-cpu-time`.++## Changes in 1.4.0+ - We now have a manual at https://hspec.github.io/. The sources are in+ `doc/`. It's still work in progress. Contributions are very welcome!+ - The Haddock documentation now indicates the stability of each exposed+ module. `Test.Hspec` is now considered stable.+ - `hspec` now supports command-line options+ - `--color` can be used to enable/disable colored output+ - `--format` can be used to pick a specific formatter+ - `--html` can be used to produce an HTML report+ - `--maximum-generated-tests` can be used to specify QuickCheck's+ `maxSuccess`+ - `--match` only runs spec items that match a given string+ - `--re-run` only runs spec items that previously failed. This is+ undocumented,+ experimental and only works within GHCi (use `:reload` / `:main`)!+ - Runner functions exported from `Test.Hspec.Runner` new expect a monadic+ spec.+ - `fromHUnitTest` has been added. It can be used to run existing HUnit test+ suites with Hspec.+ - The `Example` instance for HUnit `Test`s has been deprecated.+ `fromHUnitTest` can be used instead. The primary motivation is, that+ `fromHUnitTest` gives more detailed reporting for nested HUnit test suites.+ - `Test.Hspec.Monadic` has been deprecated, all functionality is available+ through one of `Test.Hspec`, `Test.Hspec.Core` or `Test.Hspec.Runner`.+ - More of Hspec's internals are now exposed from `Test.Hspec.Core`+ - All runner functions for the core spec type (aka as non-monadic spec) have+ been deprecated, use e.g. `Test.Hspec.hspec . fromSpecList` instead. The+ motivation is to provide an API that does not expose colliding names.+ - Some other stuff from `Test.Hspec.Core` that collides with other parts of+ the API has been deprecated. Compatible alternatives are given in each+ deprecation message.+ - The default formatter now produces less whitespace (#73) + other minor+ improvements+ - The formatter API has been revamped.+ - The exception type is now printed if an example fails due to an exception+ (#50)+ - The number of pending examples is now printed after each test run (#85)+ - `--verbose` has been added (#87)++## Changes in 1.3.0++ - `Test.Hspec` now re-exports the monadic API. If you still use the+ non-monadic API, you can use `Test.Hspec.Core` as a drop-in replacement.++ - `hspec-expectations`, a set of combinators that allow to express+ expectations about the outcome of code examples, is now included with Hspec.+ Have a look at the [README of `hspec-expectations`]+ (https://github.com/sol/hspec-expectations#readme)+ for a short introduction.++ - `hspec-discover`, a mechanism for automatic spec discovery, is now an+ official part of Hspec.+ Have a look at [`hspec-discover`'s README]+ (https://github.com/hspec/hspec/tree/main/hspec-discover#readme)+ for a short introduction.++## Changes in 1.2.0++ - `hspec` has been removed, and `hspecX` has been renamed to `hspec` (see+ [#71](https://github.com/hspec/hspec/issues/71))++ - `hHspec` now returns a summary of the test run.++ - The time reporting after a test run is not colored anymore.++## Changes in 1.1.3++ - `Test.Hspec` warns now about future changes: It will re-export+ `Test.Hspec.Monadic` in the future. If you still use the non-monadic API,+ you can either use `Test.Hspec.Core` as a drop-in replacement, or migrate your+ code to the monadic API.++ The monadic API is more stable and easier to use. Now is a good time to+ switch!++ - `Test.Hspec.Core` is now a proper superset of `Test.Hspec`++## Changes in 1.1.2++ * All descriptions of nested examples are now included in summary for failing+ examples++ * `context` is now an alias for `describe`++## Changes in 1.1.1++ * Specs from Test.Hspec.Monadic has been renamed to Spec. For backward+ compatibility Specs is still kept as an alias.++## Changes in 1.1.0++### The reason for pending examples is now optional++With this change, both of the following code snippets work.++```haskell+it "some behavior" $+ pending -- no reason given+```++```haskell+it "some other behavior" $+ pending "some reason"+```++### Hspec does not rely on ExistentialQuantification anymore++### The type used to represent specs is now abstract++This should give more useful error messages when adapting old specs that use+the non-monadic API for `hspec-1.0`/`hspec-1.1`.++### Several internal types and functions have been deprecated++Those are internal functions, and they will be removed/hidden with the next+release. If you use any of those, update your code. If you really need them,+[open a ticket](https://github.com/hspec/hspec/issues) and describe your use+case.++## Changes in 1.0.0++### Hspec now re-uses QuickCheck's property function++`Test.Hspec.QuickCheck.property` is now simply a re-exports of+`Test.QuickCheck.property`. This has the advantage that you do not get a name+collision if you import both, `Test.Hspec.QuickCheck` and `Test.QuickCheck`.++### Better support for nested specs++*NOTE: This is a breaking change to the non-monadic API. The monadic API is+not affected.*++In some situations parent descriptions for nested specs were not included in+the generated report. Solving this required a change to the data structure+that is used to represent specs (it was not a proper tree, now it is).++#### Updating specs that use the non-monadic API++The runner functions (`hspec`, `hspecB` and `hspecX`) now take a list of+descriptions.++The following works with `hspec-0.9`, but not with `hspec-1.0`.++```haskell+main = hspecX $+ describe "reverse" [+ it "reverses a list" $+ reverse [1, 2, 3] == [3, 2, 1],++ it "gives the original list, if applied twice" $ property $+ \xs -> reverse (reverse xs) == (xs :: [Int])+ ]++```++For `hspec-1.0`, you need to wrap it into a list.++```haskell+main = hspecX [+ describe "reverse" [+ it "reverses a list" $+ reverse [1, 2, 3] == [3, 2, 1],++ it "gives the original list, if applied twice" $ property $+ \xs -> reverse (reverse xs) == (xs :: [Int])+ ]+ ]+```++Specs consisting of several *describes*, combined with `descriptions`, continue+to work unchanged. But `descriptions` is now a noop, and it will be removed in+a future release. So it is a good idea to drop it.++The following works with both `hspec-0.9` and `hspec-1.0`.++```haskell+main = hspecX $ descriptions [ -- descriptions is redundant+ describe "Foo" [+ it "has some behavior" True+ ]+ , describe "Bar" [+ it "has some behavior" True+ ]+ ]+```++But the following is recommended instead.++```haskell+main = hspecX [+ describe "Foo" [+ it "has some behavior" True+ ]+ , describe "Bar" [+ it "has some behavior" True+ ]+ ]+```++### A new monadic API for custom Formatters++For all the details, have a look at the [docs]+(https://hackage.haskell.org/packages/archive/hspec/latest/doc/html/Test-Hspec-Formatters.html).+++### The total time required to run a spec is now included in the summary++In addition to the used CPU time, the total time required to run a spec is now+include in the summary. This is useful for specs that do non-CPU-intensive+stuff, or fork subprocesses.
LICENSE view
@@ -1,4 +1,4 @@-Copyright (c) 2011-2014 Simon Hengel <sol@typeful.net>+Copyright (c) 2011-2026 Simon Hengel <sol@typeful.net> Copyright (c) 2011-2012 Trystan Spangler <trystan.s@comcast.net> Copyright (c) 2011-2011 Greg Weber <greg@gregweber.info>
− example/Spec.hs
@@ -1,16 +0,0 @@-module Main (main, spec) where--import Test.Hspec-import Test.QuickCheck--main :: IO ()-main = hspec spec--spec :: Spec-spec = do- describe "reverse" $ do- it "reverses a list" $ do- reverse [1 :: Int, 2, 3] `shouldBe` [3, 2, 1]-- it "gives the original list, if applied twice" $ property $- \xs -> (reverse . reverse) xs == (xs :: [Int])
− hspec-discover/src/Config.hs
@@ -1,43 +0,0 @@-module Config (- Config (..)-, defaultConfig-, parseConfig-, usage-) where--import Data.Maybe-import System.Console.GetOpt--data Config = Config {- configNested :: Bool-, configFormatter :: Maybe String-, configNoMain :: Bool-} deriving (Eq, Show)--defaultConfig :: Config-defaultConfig = Config False Nothing False--options :: [OptDescr (Config -> Config)]-options = [- Option [] ["nested"] (NoArg $ \c -> c {configNested = True}) ""- , Option [] ["formatter"] (ReqArg (\s c -> c {configFormatter = Just s}) "FORMATTER") ""- , Option [] ["no-main"] (NoArg $ \c -> c {configNoMain = True}) ""- ]--usage :: String -> String-usage prog = "\nUsage: " ++ prog ++ " SRC CUR DST [--formatter=FORMATTER] [--no-main]\n"--parseConfig :: String -> [String] -> Either String Config-parseConfig prog args = case getOpt Permute options args of- (opts, [], []) -> let- c = (foldl (flip id) defaultConfig opts)- in- if (configNoMain c && isJust (configFormatter c))- then- formatError "option `--formatter=<fmt>' does not make sense with `--no-main'\n"- else- Right c- (_, _, err:_) -> formatError err- (_, arg:_, _) -> formatError ("unexpected argument `" ++ arg ++ "'\n")- where- formatError err = Left (prog ++ ": " ++ err ++ usage prog)
− hspec-discover/src/Main.hs
@@ -1,8 +0,0 @@-module Main (main) where--import System.Environment--import Run (run)--main :: IO ()-main = getArgs >>= run
− hspec-discover/src/Run.hs
@@ -1,132 +0,0 @@-{-# LANGUAGE TypeSynonymInstances, FlexibleInstances, OverloadedStrings #-}-{-# OPTIONS_GHC -fno-warn-orphans #-}--- | A preprocessor that finds and combines specs.-module Run (- run---- exported for testing-, importList-, fileToSpec-, findSpecs-, getFilesRecursive-, driverWithFormatter-, moduleName-) where-import Control.Monad-import Control.Applicative-import Data.List-import Data.Char-import Data.Maybe-import Data.String-import System.Environment-import System.Exit-import System.IO-import System.Directory (doesDirectoryExist, getDirectoryContents, doesFileExist)-import System.FilePath hiding (combine)--import Config--instance IsString ShowS where- fromString = showString--type Spec = String--run :: [String] -> IO ()-run args_ = do- name <- getProgName- case args_ of- src : _ : dst : args -> case parseConfig name args of- Left err -> do- hPutStrLn stderr err- exitFailure- Right c -> do- when (configNested c) (hPutStrLn stderr "hspec-discover: WARNING - The `--nested' flag is deprecated and will be removed in a future release!")- specs <- findSpecs src- writeFile dst (mkSpecModule src c specs)- _ -> do- hPutStrLn stderr (usage name)- exitFailure--mkSpecModule :: FilePath -> Config -> [Spec] -> String-mkSpecModule src c nodes =- ( "{-# LINE 1 " . shows src . " #-}"- . showString ("module " ++ module_ ++" where\n")- . importList nodes- . maybe driver (driverWithFormatter (null nodes)) (configFormatter c)- . formatSpecs nodes- ) "\n"- where- driver =- showString "import Test.Hspec\n"- . case configNoMain c of- False ->- showString "main :: IO ()\n"- . showString "main = hspec $ "- True ->- showString "spec :: Spec\n"- . showString "spec = "- module_ = if configNoMain c then pathToModule src else "Main"- pathToModule f = let- fileName = last $ splitDirectories f- m:ms = takeWhile (/='.') fileName- in- toUpper m:ms---driverWithFormatter :: Bool -> String -> ShowS-driverWithFormatter isEmpty f =- (if isEmpty then id else "import Test.Hspec\n")- . showString "import Test.Hspec.Runner\n"- . showString "import qualified " . showString (moduleName f) . showString "\n"- . showString "main :: IO ()\n"- . showString "main = hspecWithFormatter " . showString f . showString " $ "--moduleName :: String -> String-moduleName = reverse . dropWhile (== '.') . dropWhile (/= '.') . reverse---- | Generate imports for a list of specs.-importList :: [Spec] -> ShowS-importList = foldr (.) "" . map f- where- f :: Spec -> ShowS- f name = "import qualified " . showString name . "Spec\n"---- | Combine a list of strings with (>>).-sequenceS :: [ShowS] -> ShowS-sequenceS = foldr (.) "" . intersperse " >> "---- | Convert a list of specs to code.-formatSpecs :: [Spec] -> ShowS-formatSpecs xs- | null xs = "return ()"- | otherwise = sequenceS (map formatSpec xs)---- | Convert a spec to code.-formatSpec :: Spec -> ShowS-formatSpec name = "describe " . shows name . " " . showString name . "Spec.spec"--findSpecs :: FilePath -> IO [Spec]-findSpecs src = do- let (dir, file) = splitFileName src- mapMaybe fileToSpec . filter (/= file) <$> getFilesRecursive dir--fileToSpec :: FilePath -> Maybe String-fileToSpec f = intercalate "." . reverse <$> case reverse $ splitDirectories f of- x:xs -> case stripSuffix "Spec.hs" x <|> stripSuffix "Spec.lhs" x of- Nothing -> Nothing- Just "" -> Nothing- Just ys -> Just (ys : xs)- _ -> Nothing- where- stripSuffix :: Eq a => [a] -> [a] -> Maybe [a]- stripSuffix suffix str = reverse <$> stripPrefix (reverse suffix) (reverse str)--getFilesRecursive :: FilePath -> IO [FilePath]-getFilesRecursive baseDir = sort <$> go []- where- go :: FilePath -> IO [FilePath]- go dir = do- c <- map (dir </>) . filter (`notElem` [".", ".."]) <$> getDirectoryContents (baseDir </> dir)- dirs <- filterM (doesDirectoryExist . (baseDir </>)) c >>= mapM go- files <- filterM (doesFileExist . (baseDir </>)) c- return (files ++ concat dirs)
− hspec-discover/test-data/empty-dir/Foo/Bar/Baz/.placeholder
− hspec-discover/test-data/nested-spec/Foo/Bar/BazSpec.hs
− hspec-discover/test-data/nested-spec/Foo/BarSpec.hs
− hspec-discover/test-data/nested-spec/FooSpec.hs
− hspec-discover/test/ConfigSpec.hs
@@ -1,47 +0,0 @@-module ConfigSpec (main, spec) where--import Test.Hspec.Meta--import Config--main :: IO ()-main = hspec spec--spec :: Spec-spec = do- describe "parseConfig" $ do- let parse = parseConfig "hspec-discover"-- it "recognizes --nested" $ do- parse ["--nested"] `shouldBe` Right (defaultConfig {configNested = True})-- it "recognizes --formatter" $ do- parse ["--formatter", "someFormatter"] `shouldBe` Right (defaultConfig {configFormatter = Just "someFormatter"})-- it "recognizes --no-main" $ do- parse ["--no-main"] `shouldBe` Right (defaultConfig {configNoMain = True})-- it "returns error message on unrecognized option" $ do- parse ["--foo"] `shouldBe` (Left . unlines) [- "hspec-discover: unrecognized option `--foo'"- , ""- , "Usage: hspec-discover SRC CUR DST [--formatter=FORMATTER] [--no-main]"- ]-- it "returns error message on unexpected argument" $ do- parse ["foo"] `shouldBe` (Left . unlines) [- "hspec-discover: unexpected argument `foo'"- , ""- , "Usage: hspec-discover SRC CUR DST [--formatter=FORMATTER] [--no-main]"- ]-- it "returns error message on --formatter=<fmt> with --no-main" $ do- parse ["--no-main", "--formatter=foo"] `shouldBe` (Left . unlines) [- "hspec-discover: option `--formatter=<fmt>' does not make sense with `--no-main'"- , ""- , "Usage: hspec-discover SRC CUR DST [--formatter=FORMATTER] [--no-main]"- ]-- context "when option is given multiple times" $ do- it "gives the last occurrence precedence" $ do- parse ["--formatter", "foo", "--formatter", "bar"] `shouldBe` Right (defaultConfig {configFormatter = Just "bar"})
− hspec-discover/test/RunSpec.hs
@@ -1,100 +0,0 @@-module RunSpec (main, spec) where--import Test.Hspec.Meta--import Control.Applicative-import System.IO-import System.Directory-import System.FilePath-import Data.List (intercalate, sort)--import Run--main :: IO ()-main = hspec spec--withTempFile :: (FilePath -> IO a) -> IO a-withTempFile action = do- dir <- getTemporaryDirectory- (file, h) <- openTempFile dir ""- hClose h- action file <* removeFile file---spec :: Spec-spec = do- describe "run" $ do- it "generates test driver" $ withTempFile $ \f -> do- run ["hspec-discover/test-data/nested-spec/Spec.hs", "", f]- readFile f `shouldReturn` unlines [- "{-# LINE 1 \"hspec-discover/test-data/nested-spec/Spec.hs\" #-}module Main where"- , "import qualified Foo.Bar.BazSpec"- , "import qualified Foo.BarSpec"- , "import qualified FooSpec"- , "import Test.Hspec"- , "main :: IO ()"- , "main = hspec $ describe \"Foo.Bar.Baz\" Foo.Bar.BazSpec.spec >> describe \"Foo.Bar\" Foo.BarSpec.spec >> describe \"Foo\" FooSpec.spec"- ]-- it "generates test driver for an empty directory" $ withTempFile $ \f -> do- run ["hspec-discover/test-data/empty-dir/Spec.hs", "", f]- readFile f `shouldReturn` unlines [- "{-# LINE 1 \"hspec-discover/test-data/empty-dir/Spec.hs\" #-}module Main where"- , "import Test.Hspec"- , "main :: IO ()"- , "main = hspec $ return ()"- ]-- describe "getFilesRecursive" $ do- it "recursively returns all file entries of a given directory" $ do- getFilesRecursive "hspec-discover/test-data" `shouldReturn` sort [- "empty-dir/Foo/Bar/Baz/.placeholder"- , "nested-spec/Foo/Bar/BazSpec.hs"- , "nested-spec/Foo/BarSpec.hs"- , "nested-spec/FooSpec.hs"- ]-- describe "fileToSpec" $ do- it "converts path to spec name" $ do- fileToSpec "FooSpec.hs" `shouldBe` Just "Foo"-- it "rejects spec with empty name" $ do- fileToSpec "Spec.hs" `shouldBe` Nothing-- it "works for lhs files" $ do- fileToSpec "FooSpec.lhs" `shouldBe` Just "Foo"-- it "returns Nothing for invalid spec name" $ do- fileToSpec "foo" `shouldBe` Nothing-- context "when path has directory component" $ do- it "converts path to spec name" $ do- fileToSpec ("Foo" </> "Bar" </> "BazSpec.hs") `shouldBe` Just "Foo.Bar.Baz"-- it "rejects spec with empty name" $ do- fileToSpec ("Foo" </> "Bar" </> "Spec.hs") `shouldBe` Nothing-- describe "findSpecs" $ do- it "finds specs" $ do- findSpecs "hspec-discover/test-data/nested-spec/Spec.hs" `shouldReturn` ["Foo.Bar.Baz","Foo.Bar","Foo"]-- describe "driverWithFormatter" $ do- it "generates a test driver that uses a custom formatter" $ do- driverWithFormatter False "Some.Module.formatter" "" `shouldBe` intercalate "\n" [- "import Test.Hspec"- , "import Test.Hspec.Runner"- , "import qualified Some.Module"- , "main :: IO ()"- , "main = hspecWithFormatter Some.Module.formatter $ "- ]-- describe "moduleName" $ do- it "returns the module name of an fully qualified identifier" $ do- moduleName "Some.Module.someId" `shouldBe` "Some.Module"-- describe "importList" $ do- it "generates imports for a list of specs" $ do- importList ["Foo", "Bar"] "" `shouldBe` unlines [- "import qualified FooSpec"- , "import qualified BarSpec"- ]
− hspec-discover/test/Spec.hs
@@ -1,1 +0,0 @@-{-# OPTIONS_GHC -F -pgmF hspec-meta-discover #-}
hspec.cabal view
@@ -1,174 +1,62 @@+cabal-version: 1.12++-- This file has been generated from package.yaml by hpack version 0.39.1.+--+-- see: https://github.com/sol/hpack+ name: hspec-version: 1.8.3+version: 2.11.17 license: MIT license-file: LICENSE-copyright: (c) 2011-2014 Simon Hengel,+copyright: (c) 2011-2026 Simon Hengel, (c) 2011-2012 Trystan Spangler, (c) 2011 Greg Weber maintainer: Simon Hengel <sol@typeful.net> build-type: Simple-cabal-version: >= 1.8 category: Testing stability: experimental bug-reports: https://github.com/hspec/hspec/issues-homepage: http://hspec.github.io/-synopsis: Behavior-Driven Development for Haskell-description: Behavior-Driven Development for Haskell+author: Simon Hengel <sol@typeful.net>+homepage: https://hspec.github.io/+synopsis: A Testing Framework for Haskell+description: Hspec is a testing framework for Haskell. Some of Hspec's distinctive+ features are: .- Hspec is roughly based on the Ruby library RSpec. However,- Hspec is just a framework for running HUnit and QuickCheck- tests. Compared to other options, it provides a much nicer- syntax that makes tests very easy to read.+ * a friendly DSL for defining tests .- The Hspec Manual is at <http://hspec.github.io/>.---- find hspec-discover/test-data/ -type f+ * integration with QuickCheck, SmallCheck, and HUnit+ .+ * parallel test execution+ .+ * automatic discovery of test files+ .+ The Hspec Manual is at <https://hspec.github.io/>. extra-source-files:- hspec-discover/test-data/nested-spec/FooSpec.hs- hspec-discover/test-data/nested-spec/Foo/Bar/BazSpec.hs- hspec-discover/test-data/nested-spec/Foo/BarSpec.hs- hspec-discover/test-data/empty-dir/Foo/Bar/Baz/.placeholder+ version.yaml+ CHANGES.markdown source-repository head type: git location: https://github.com/hspec/hspec -Library- ghc-options:- -Wall+library+ ghc-options: -Wall hs-source-dirs: src build-depends:- base == 4.*- , random == 1.0.*- , setenv- , ansi-terminal >= 0.5- , time- , transformers >= 0.2.2.0 && < 0.4.0- , deepseq- , HUnit >= 1.2.5- , QuickCheck >= 2.5.1- , quickcheck-io- , hspec-expectations == 0.5.0.*+ QuickCheck >=2.12+ , base ==4.*+ , hspec-core ==2.11.17+ , hspec-discover ==2.11.17+ , hspec-expectations ==0.8.4.* exposed-modules: Test.Hspec- Test.Hspec.Core- Test.Hspec.Monadic- Test.Hspec.Runner+ Test.Hspec.Discover Test.Hspec.Formatters- Test.Hspec.HUnit Test.Hspec.QuickCheck- other-modules:- Test.Hspec.Util- Test.Hspec.Compat- Test.Hspec.Core.Type- Test.Hspec.Core.QuickCheckUtil- Test.Hspec.Config- Test.Hspec.Options- Test.Hspec.FailureReport- Test.Hspec.Runner.Eval- Test.Hspec.Formatters.Internal- Test.Hspec.Timer--test-suite spec- type:- exitcode-stdio-1.0- hs-source-dirs:- src, test- main-is:- Spec.hs- other-modules:- Mock- Helper- Test.HspecSpec- Test.Hspec.CompatSpec- Test.Hspec.Core.TypeSpec- Test.Hspec.FailureReportSpec- Test.Hspec.FormattersSpec- Test.Hspec.HUnitSpec- Test.Hspec.OptionsSpec- Test.Hspec.QuickCheckSpec- Test.Hspec.RunnerSpec- Test.Hspec.TimerSpec- Test.Hspec.UtilSpec- ghc-options:- -Wall -Werror- build-depends:- base == 4.*- , random == 1.0.*- , setenv- , silently >= 1.2.4- , ansi-terminal- , time- , transformers- , deepseq- , HUnit- , QuickCheck- , quickcheck-io- , hspec-expectations-- , hspec-meta >= 1.8.0- , process- , ghc-paths--test-suite doctests- main-is:- doctests.hs- type:- exitcode-stdio-1.0- ghc-options:- -Wall -Werror -threaded- hs-source-dirs:- test- build-depends:- base == 4.*- , doctest >= 0.9.4.1--test-suite example- type:- exitcode-stdio-1.0- main-is:- Spec.hs- hs-source-dirs:- example- ghc-options:- -Wall -Werror- build-depends:- base == 4.*- , hspec- , QuickCheck---- hspec-discover-executable hspec-discover- ghc-options:- -Wall- hs-source-dirs:- hspec-discover/src- main-is:- Main.hs- other-modules:- Run- Config- build-depends:- base == 4.*- , filepath- , directory--test-suite hspec-discover-spec- type:- exitcode-stdio-1.0- ghc-options:- -Wall -Werror- hs-source-dirs:- hspec-discover/src- , hspec-discover/test- main-is:- Spec.hs+ Test.Hspec.Runner other-modules:- RunSpec- ConfigSpec- build-depends:- base == 4.*- , filepath- , directory- , hspec-meta+ Paths_hspec+ default-language: Haskell2010+ if impl(ghc)+ cpp-options: -DENABLE_SPEC_HOOK_ARGS
src/Test/Hspec.hs view
@@ -1,67 +1,86 @@ -- | -- Stability: stable ----- Hspec is a testing library for Haskell.+-- Hspec is a testing framework for Haskell. -- -- This is the library reference for Hspec.--- The <http://hspec.github.io/ User's Manual> contains more in-depth+-- The <https://hspec.github.io/ User's Manual> contains more in-depth -- documentation. module Test.Hspec ( -- * Types Spec+, SpecWith , Example+, Arg -- * Setting expectations , module Test.Hspec.Expectations -- * Defining a spec+, it+, specify , describe , context-, it , example+, parallel+, sequential+, runIO++-- * Pending spec items+-- |+-- During a test run a /pending/ spec item is:+--+-- 1. not executed+--+-- 1. reported as \"pending\" , pending , pendingWith+, xit+, xspecify+, xdescribe+, xcontext++-- * Focused spec items #focus#+-- |+-- During a test run, when a spec contains /focused/ spec items, all other spec+-- items are ignored.+, focus+, fit+, fspecify+, fdescribe+, fcontext++-- * Hooks+, ActionWith , before+, before_+, beforeWith+, beforeAll+, beforeAll_+, beforeAllWith , after+, after_+, afterAll+, afterAll_ , around-, parallel+, around_+, aroundWith+, aroundAll+, aroundAll_+, aroundAllWith+, mapSubject+, ignoreSubject -- * Running a spec , hspec ) where -import Control.Exception (finally)--import Test.Hspec.Core.Type hiding (describe, it)+import Test.Hspec.Core.Spec+import Test.Hspec.Core.Hooks import Test.Hspec.Runner-import Test.Hspec.HUnit () import Test.Hspec.Expectations-import Test.Hspec.Core (mapSpecItem)-import qualified Test.Hspec.Core as Core --- | Combine a list of specs into a larger spec.-describe :: String -> Spec -> Spec-describe label action = fromSpecList [Core.describe label (runSpecM action)]---- | An alias for `describe`.-context :: String -> Spec -> Spec-context = describe---- | Create a spec item.------ A spec item consists of:------ * a textual description of a desired behavior------ * an example for that behavior------ > describe "absolute" $ do--- > it "returns a positive number when given a negative number" $--- > absolute (-1) == 1-it :: Example a => String -> a -> Spec-it label action = fromSpecList [Core.it label action]---- | This is a type restricted version of `id`. It can be used to get better+-- | @example@ is a type restricted version of `id`. It can be used to get better -- error messages on type mismatches. -- -- Compare e.g.@@ -75,19 +94,3 @@ -- > putStrLn example :: Expectation -> Expectation example = id---- | Run examples of given spec in parallel.-parallel :: Spec -> Spec-parallel = mapSpecItem $ \item -> item {itemIsParallelizable = True}---- | Run a custom action before every spec item.-before :: IO () -> Spec -> Spec-before action = around (action >>)---- | Run a custom action after every spec item.-after :: IO () -> Spec -> Spec-after action = around (`finally` action)---- | Run a custom action before and/or after every spec item.-around :: (IO () -> IO ()) -> Spec -> Spec-around a2 = mapSpecItem $ \item -> item {itemExample = \params a1 -> itemExample item params (a1 . a2)}
− src/Test/Hspec/Compat.hs
@@ -1,79 +0,0 @@-{-# LANGUAGE CPP #-}-module Test.Hspec.Compat (- showType-, showFullType-, readMaybe-, lookupEnv-, module Data.IORef-#if !MIN_VERSION_base(4,6,0)-, modifyIORef'-#endif-) where--import Data.Typeable (Typeable, typeOf, typeRepTyCon)-import Text.Read-import Data.IORef-import System.Environment--#if MIN_VERSION_base(4,4,0)-import Data.Typeable.Internal (tyConModule, tyConName)-#endif--#if !MIN_VERSION_base(4,6,0)-import qualified Text.ParserCombinators.ReadP as P-#endif--#if !MIN_VERSION_base(4,6,0)--- |Strict version of 'modifyIORef'-modifyIORef' :: IORef a -> (a -> a) -> IO ()-modifyIORef' ref f = do- x <- readIORef ref- let x' = f x- x' `seq` writeIORef ref x'---- | Parse a string using the 'Read' instance.--- Succeeds if there is exactly one valid result.--- A 'Left' value indicates a parse error.-readEither :: Read a => String -> Either String a-readEither s =- case [ x | (x,"") <- readPrec_to_S read' minPrec s ] of- [x] -> Right x- [] -> Left "Prelude.read: no parse"- _ -> Left "Prelude.read: ambiguous parse"- where- read' =- do x <- readPrec- lift P.skipSpaces- return x---- | Parse a string using the 'Read' instance.--- Succeeds if there is exactly one valid result.-readMaybe :: Read a => String -> Maybe a-readMaybe s = case readEither s of- Left _ -> Nothing- Right a -> Just a---- | Return the value of the environment variable @var@, or @Nothing@ if--- there is no such value.------ For POSIX users, this is equivalent to 'System.Posix.Env.getEnv'.-lookupEnv :: String -> IO (Maybe String)-lookupEnv k = lookup k `fmap` getEnvironment-#endif--showType :: Typeable a => a -> String-showType a = let t = typeRepTyCon (typeOf a) in-#if MIN_VERSION_base(4,4,0)- show t-#else- (reverse . takeWhile (/= '.') . reverse . show) t-#endif---showFullType :: Typeable a => a -> String-showFullType a = let t = typeRepTyCon (typeOf a) in-#if MIN_VERSION_base(4,4,0)- tyConModule t ++ "." ++ tyConName t-#else- show t-#endif
− src/Test/Hspec/Config.hs
@@ -1,118 +0,0 @@-module Test.Hspec.Config (- Config (..)-, defaultConfig-, getConfig-, configAddFilter-, configSetSeed-) where--import Control.Applicative-import Data.List-import Data.Maybe-import System.IO-import System.Exit-import qualified Test.QuickCheck as QC-import Test.Hspec.Formatters--import Test.Hspec.Util---- for Monad (Either e) when base < 4.3-import Control.Monad.Trans.Error ()--import Test.Hspec.Options-import Test.Hspec.FailureReport--data Config = Config {- configDryRun :: Bool-, configPrintCpuTime :: Bool-, configFastFail :: Bool---- |--- A predicate that is used to filter the spec before it is run. Only examples--- that satisfy the predicate are run.-, configFilterPredicate :: Maybe (Path -> Bool)-, configQuickCheckArgs :: QC.Args-, configSmallCheckDepth :: Int-, configColorMode :: ColorMode-, configFormatter :: Formatter-, configHtmlOutput :: Bool-, configHandle :: Either Handle FilePath-}--defaultConfig :: Config-defaultConfig = Config False False False Nothing QC.stdArgs 5 ColorAuto specdoc False (Left stdout)---- | Add a filter predicate to config. If there is already a filter predicate,--- then combine them with `||`.-configAddFilter :: (Path -> Bool) -> Config -> Config-configAddFilter p1 c = c {- configFilterPredicate = Just p1 `filterOr` configFilterPredicate c- }--filterOr :: Maybe (Path -> Bool) -> Maybe (Path -> Bool) -> Maybe (Path -> Bool)-filterOr p1_ p2_ = case (p1_, p2_) of- (Just p1, Just p2) -> Just $ \path -> p1 path || p2 path- _ -> p1_ <|> p2_--configSetSeed :: Integer -> Config -> Config-configSetSeed n c = c {configQuickCheckArgs = (configQuickCheckArgs c) {QC.replay = Just (stdGenFromInteger n, 0)}}--mkConfig :: Maybe FailureReport -> Options -> Config-mkConfig mFailureReport opts = Config {- configDryRun = optionsDryRun opts- , configPrintCpuTime = optionsPrintCpuTime opts- , configFastFail = optionsFastFail opts- , configFilterPredicate = matchFilter `filterOr` rerunFilter- , configQuickCheckArgs = qcArgs- , configSmallCheckDepth = fromMaybe (configSmallCheckDepth defaultConfig) (optionsDepth opts)- , configColorMode = optionsColorMode opts- , configFormatter = optionsFormatter opts- , configHtmlOutput = optionsHtmlOutput opts- , configHandle = maybe (configHandle defaultConfig) Right (optionsOutputFile opts)- }- where- qcArgs = (- maybe id setSeed mSeed- . maybe id setMaxDiscardRatio mMaxDiscardRatio- . maybe id setMaxSize mMaxSize- . maybe id setMaxSuccess mMaxSuccess) QC.stdArgs-- mSeed = optionsSeed opts <|> (failureReportSeed <$> mFailureReport)- mMaxSuccess = optionsMaxSuccess opts <|> (failureReportMaxSuccess <$> mFailureReport)- mMaxSize = optionsMaxSize opts <|> (failureReportMaxSize <$> mFailureReport)- mMaxDiscardRatio = optionsMaxDiscardRatio opts <|> (failureReportMaxDiscardRatio <$> mFailureReport)-- setMaxSuccess :: Int -> QC.Args -> QC.Args- setMaxSuccess n args = args {QC.maxSuccess = n}-- setMaxSize :: Int -> QC.Args -> QC.Args- setMaxSize n args = args {QC.maxSize = n}-- setMaxDiscardRatio :: Int -> QC.Args -> QC.Args- setMaxDiscardRatio n args = args {QC.maxDiscardRatio = n}-- setSeed :: Integer -> QC.Args -> QC.Args- setSeed n args = args {QC.replay = Just (stdGenFromInteger n, 0)}-- matchFilter = case optionsMatch opts of- [] -> Nothing- xs -> Just $ foldl1' (\p0 p1 path -> p0 path || p1 path) (map filterPredicate xs)-- rerunFilter = flip elem . failureReportPaths <$> mFailureReport--getConfig :: Options -> String -> [String] -> IO Config-getConfig opts_ prog args = do- case parseOptions opts_ prog args of- Left (err, msg) -> exitWithMessage err msg- Right opts -> do- r <- if optionsRerun opts then readFailureReport else return Nothing- return (mkConfig r opts)--exitWithMessage :: ExitCode -> String -> IO a-exitWithMessage err msg = do- hPutStr h msg- exitWith err- where- h = case err of- ExitSuccess -> stdout- _ -> stderr
− src/Test/Hspec/Core.hs
@@ -1,73 +0,0 @@--- |--- Stability: experimental------ This module provides access to Hspec's internals. It is less stable than--- other parts of the API. For most users "Test.Hspec" is more suitable!-module Test.Hspec.Core (---- * A type class for examples- Example (..)-, Params (..)-, Progress-, Result (..)---- * A writer monad for constructing specs-, SpecM-, runSpecM-, fromSpecList---- * Internal representation of a spec tree-, SpecTree (..)-, Item (..)-, mapSpecItem-, modifyParams-, describe-, it---- * Deprecated types and functions-, Specs-, hspecB-, hspecX-, hHspec-, hspec-) where--import Control.Applicative-import System.IO (Handle)--import Test.Hspec.Core.Type-import qualified Test.Hspec.Runner as Runner-import Test.Hspec.Runner (Summary(..), Config(..), defaultConfig)--hspecWith :: Config -> [SpecTree] -> IO Summary-hspecWith c = Runner.hspecWith c . fromSpecList--mapSpecItem :: (Item -> Item) -> Spec -> Spec-mapSpecItem f = fromSpecList . map go . runSpecM- where- go :: SpecTree -> SpecTree- go spec = case spec of- SpecItem item -> SpecItem (f item)- SpecGroup d es -> SpecGroup d (map go es)--modifyParams :: (Params -> Params) -> Spec -> Spec-modifyParams f = mapSpecItem $ \item -> item {itemExample = \p -> (itemExample item) (f p)}--{-# DEPRECATED hspecX "use `Test.Hspec.Runner.hspec` instead" #-} -- since 1.2.0-hspecX :: [SpecTree] -> IO ()-hspecX = hspec--{-# DEPRECATED hspec "use `Test.Hspec.Runner.hspec` instead" #-} -- since 1.4.0-hspec :: [SpecTree] -> IO ()-hspec = Runner.hspec . fromSpecList--{-# DEPRECATED hspecB "use `Test.Hspec.Runner.hspecWith` instead" #-} -- since 1.4.0-hspecB :: [SpecTree] -> IO Bool-hspecB spec = (== 0) . summaryFailures <$> hspecWith defaultConfig spec--{-# DEPRECATED hHspec "use `Test.Hspec.Runner.hspecWith` instead" #-} -- since 1.4.0-hHspec :: Handle -> [SpecTree] -> IO Summary-hHspec h = hspecWith defaultConfig {configHandle = Left h}--{-# DEPRECATED Specs "use `[SpecTree]` instead" #-} -- since 1.4.0-type Specs = [SpecTree]
− src/Test/Hspec/Core/QuickCheckUtil.hs
@@ -1,28 +0,0 @@-{-# LANGUAGE CPP #-}-module Test.Hspec.Core.QuickCheckUtil where--import Data.IORef-import Test.QuickCheck hiding (Result(..))-import Test.QuickCheck as QC-import Test.QuickCheck.Property hiding (Result(..))-import qualified Test.QuickCheck.Property as QCP-import Test.QuickCheck.IO ()-import Control.Applicative--aroundProperty :: (IO () -> IO ()) -> Property -> Property-aroundProperty action p = MkProp . aroundRose action . unProp <$> p--aroundRose :: (IO () -> IO ()) -> Rose QCP.Result -> Rose QCP.Result-aroundRose action r = ioRose $ do- ref <- newIORef (return QCP.succeeded)- action (reduceRose r >>= writeIORef ref)- readIORef ref--isUserInterrupt :: QC.Result -> Bool-isUserInterrupt r = case r of-#if MIN_VERSION_QuickCheck(2,6,0)- QC.Failure {QC.interrupted = x} -> x-#else- QC.Failure {QC.reason = "Exception: 'user interrupt'"} -> True-#endif- _ -> False
− src/Test/Hspec/Core/Type.hs
@@ -1,176 +0,0 @@-{-# LANGUAGE TypeSynonymInstances, FlexibleInstances, GeneralizedNewtypeDeriving, DeriveDataTypeable #-}-module Test.Hspec.Core.Type (- Spec-, SpecM (..)-, runSpecM-, fromSpecList-, SpecTree (..)-, Item (..)-, Example (..)-, Result (..)-, Params (..)-, Progress--, describe-, it-, forceResult--, pending-, pendingWith-) where--import qualified Control.Exception as E-import Control.Applicative-import Control.Monad (when)-import Control.Monad.Trans.Writer (Writer, execWriter, tell)-import Data.Typeable (Typeable)-import Data.List (isPrefixOf)-import Data.Maybe (fromMaybe)--import Test.Hspec.Compat-import Test.Hspec.Util-import Test.Hspec.Expectations-import Test.HUnit.Lang (HUnitFailure(..))-import qualified Test.QuickCheck as QC-import qualified Test.QuickCheck.State as QC-import qualified Test.QuickCheck.Property as QCP-import qualified Test.QuickCheck.IO ()--import Test.Hspec.Core.QuickCheckUtil-import Control.DeepSeq (deepseq)--type Spec = SpecM ()---- | A writer monad for `SpecTree` forests.-newtype SpecM a = SpecM (Writer [SpecTree] a)- deriving (Functor, Applicative, Monad)---- | Convert a `Spec` to a forest of `SpecTree`s.-runSpecM :: Spec -> [SpecTree]-runSpecM (SpecM specs) = execWriter specs---- | Create a `Spec` from a forest of `SpecTree`s.-fromSpecList :: [SpecTree] -> Spec-fromSpecList = SpecM . tell---- | The result of running an example.-data Result = Success | Pending (Maybe String) | Fail String- deriving (Eq, Show, Read, Typeable)--forceResult :: Result -> Result-forceResult r = case r of- Success -> r- Pending m -> r `seq` m `deepseq` r- Fail m -> r `seq` m `deepseq` r--instance E.Exception Result--type Progress = (Int, Int)--data Params = Params {- paramsQuickCheckArgs :: QC.Args-, paramsSmallCheckDepth :: Int-, paramsReportProgress :: Progress -> IO ()-}---- | Internal representation of a spec.-data SpecTree =- SpecGroup String [SpecTree]- | SpecItem Item--data Item = Item {- itemIsParallelizable :: Bool-, itemRequirement :: String-, itemExample :: Params -> (IO () -> IO ()) -> IO Result-}---- | The @describe@ function combines a list of specs into a larger spec.-describe :: String -> [SpecTree] -> SpecTree-describe s = SpecGroup msg- where- msg- | null s = "(no description given)"- | otherwise = s---- | Create a spec item.-it :: Example a => String -> a -> SpecTree-it s e = SpecItem $ Item False msg (evaluateExample e)- where- msg- | null s = "(unspecified behavior)"- | otherwise = s---- | A type class for examples.-class Example a where- evaluateExample :: a -> Params -> (IO () -> IO ()) -> IO Result--instance Example Bool where- evaluateExample b _ _ = if b then return Success else return (Fail "")--instance Example Expectation where- evaluateExample e _ action = (action e >> return Success) `E.catches` [- E.Handler (\(HUnitFailure err) -> return (Fail err))- , E.Handler (return :: Result -> IO Result)- ]--instance Example Result where- evaluateExample r _ _ = return r--instance Example QC.Property where- evaluateExample p c action = do- r <- QC.quickCheckWithResult (paramsQuickCheckArgs c) {QC.chatty = False} (QCP.callback progressCallback $ aroundProperty action p)- when (isUserInterrupt r) $ do- E.throwIO E.UserInterrupt-- return $- case r of- QC.Success {} -> Success- QC.Failure {QC.output = m} -> fromMaybe (Fail $ sanitizeFailureMessage m) (parsePending m)- QC.GaveUp {QC.numTests = n} -> Fail ("Gave up after " ++ pluralize n "test" )- QC.NoExpectedFailure {} -> Fail ("No expected failure")- where- progressCallback = QCP.PostTest QCP.NotCounterexample $- \st _ -> paramsReportProgress c (QC.numSuccessTests st, QC.maxSuccessTests st)-- sanitizeFailureMessage :: String -> String- sanitizeFailureMessage = strip . addFalsifiable . stripFailed-- addFalsifiable :: String -> String- addFalsifiable m- | "(after " `isPrefixOf` m = "Falsifiable " ++ m- | otherwise = m-- stripFailed :: String -> String- stripFailed m- | prefix `isPrefixOf` m = drop n m- | otherwise = m- where- prefix = "*** Failed! "- n = length prefix-- parsePending :: String -> Maybe Result- parsePending m- | prefix `isPrefixOf` m = (readMaybe . takeWhile (/= '\'') . drop n) m- | otherwise = Nothing- where- n = length prefix- prefix = "*** Failed! Exception: '"---- | Specifies a pending example.------ If you want to textually specify a behavior but do not have an example yet,--- use this:------ > describe "fancyFormatter" $ do--- > it "can format text in a way that everyone likes" $--- > pending-pending :: Expectation-pending = E.throwIO (Pending Nothing)---- | Specifies a pending example with a reason for why it's pending.------ > describe "fancyFormatter" $ do--- > it "can format text in a way that everyone likes" $--- > pendingWith "waiting for clarification from the designers"-pendingWith :: String -> Expectation-pendingWith = E.throwIO . Pending . Just
+ src/Test/Hspec/Discover.hs view
@@ -0,0 +1,35 @@+{-# OPTIONS_GHC -fno-warn-deprecations #-}+{-# OPTIONS_HADDOCK hide #-}+{-# LANGUAGE FlexibleInstances #-}+module Test.Hspec.Discover {-# WARNING+ "This module is used by @hspec-discover@. It is not part of the public API and may change at any time."+ #-} (+ Spec+, hspec+, IsFormatter (..)+, hspecWithFormatter+, postProcessSpec+, describe+, module Prelude+) where++import Test.Hspec.Core.Spec+import Test.Hspec.Core.Runner+import Test.Hspec.Core.Formatters.V1++class IsFormatter a where+ toFormatter :: a -> IO Formatter++instance IsFormatter (IO Formatter) where+ toFormatter = id++instance IsFormatter Formatter where+ toFormatter = return++hspecWithFormatter :: IsFormatter a => a -> Spec -> IO ()+hspecWithFormatter formatter spec = do+ f <- toFormatter formatter+ hspecWith defaultConfig {configFormatter = Just f} spec++postProcessSpec :: FilePath -> Spec -> Spec+postProcessSpec _ = id
− src/Test/Hspec/FailureReport.hs
@@ -1,36 +0,0 @@-module Test.Hspec.FailureReport (- FailureReport (..)-, writeFailureReport-, readFailureReport-) where--import System.IO-import System.SetEnv-import Test.Hspec.Compat-import Test.Hspec.Util (Path, safeTry)--data FailureReport = FailureReport {- failureReportSeed :: Integer-, failureReportMaxSuccess :: Int-, failureReportMaxSize :: Int-, failureReportMaxDiscardRatio :: Int-, failureReportPaths :: [Path]-} deriving (Eq, Show, Read)--writeFailureReport :: FailureReport -> IO ()-writeFailureReport x = do- -- on Windows this can throw an exception when the input is too large, hence- -- we use `safeTry` here- safeTry (setEnv "HSPEC_FAILURES" $ show x) >>= either onError return- where- onError err = do- hPutStrLn stderr ("WARNING: Could not write environment variable HSPEC_FAILURES (" ++ show err ++ ")")--readFailureReport :: IO (Maybe FailureReport)-readFailureReport = do- mx <- lookupEnv "HSPEC_FAILURES"- case mx >>= readMaybe of- Nothing -> do- hPutStrLn stderr "WARNING: Could not read environment variable HSPEC_FAILURES; `--rerun' is ignored!"- return Nothing- x -> return x
src/Test/Hspec/Formatters.hs view
@@ -1,234 +1,8 @@-{-# LANGUAGE FlexibleInstances #-}--- |--- Stability: experimental------ This module contains formatters that can be used with--- `Test.Hspec.Runner.hspecWith`.-module Test.Hspec.Formatters (---- * Formatters- silent-, specdoc-, progress-, failed_examples---- * Implementing a custom Formatter--- |--- A formatter is a set of actions. Each action is evaluated when a certain--- situation is encountered during a test run.------ Actions live in the `FormatM` monad. It provides access to the runner state--- and primitives for appending to the generated report.-, Formatter (..)-, FormatM---- ** Accessing the runner state-, getSuccessCount-, getPendingCount-, getFailCount-, getTotalCount--, FailureRecord (..)-, getFailMessages-, usedSeed--, getCPUTime-, getRealTime---- ** Appending to the gerenated report-, write-, writeLine-, newParagraph---- ** Dealing with colors-, withSuccessColor-, withPendingColor-, withFailColor---- ** Helpers-, formatException---- * Using custom formatters with @hspec-discover@+{-# OPTIONS_GHC -fno-warn-deprecations #-} -- |--- Anything that is an instance of `IsFormatter` can be used by--- @hspec-discover@ as the default formatter for a spec. If you have a--- formatter @myFormatter@ in the module @Custom.Formatters@ you can use it--- by passing an additional argument to @hspec-discover@.------ >{-# OPTIONS_GHC -F -pgmF hspec-discover -optF --formatter=Custom.Formatters.myFormatter #-}-, IsFormatter (..)-) where--import Data.Maybe-import Test.Hspec.Util-import Test.Hspec.Compat-import Text.Printf-import Control.Monad (unless, forM_)-import Control.Applicative-import qualified Control.Exception as E-import System.IO (hPutStr, hFlush)---- We use an explicit import list for "Test.Hspec.Formatters.Internal", to make--- sure, that we only use the public API to implement formatters.------ Everything imported here has to be re-exported, so that users can implement--- their own formatters.-import Test.Hspec.Formatters.Internal (- Formatter (..)- , FormatM-- , getSuccessCount- , getPendingCount- , getFailCount- , getTotalCount-- , FailureRecord (..)- , getFailMessages- , usedSeed-- , getCPUTime- , getRealTime-- , write- , writeLine- , newParagraph-- , withSuccessColor- , withPendingColor- , withFailColor- )--class IsFormatter a where- toFormatter :: a -> IO Formatter--instance IsFormatter (IO Formatter) where- toFormatter = id--instance IsFormatter Formatter where- toFormatter = return--silent :: Formatter-silent = Formatter {- headerFormatter = return ()-, exampleGroupStarted = \_ _ _ -> return ()-, exampleGroupDone = return ()-, exampleProgress = \_ _ _ -> return ()-, exampleSucceeded = \_ -> return ()-, exampleFailed = \_ _ -> return ()-, examplePending = \_ _ -> return ()-, failedFormatter = return ()-, footerFormatter = return ()-}---specdoc :: Formatter-specdoc = silent {-- headerFormatter = do- writeLine ""--, exampleGroupStarted = \n nesting name -> do-- -- separate groups with an empty line- unless (n == 0) $ do- newParagraph-- writeLine (indentationFor nesting ++ name)--, exampleGroupDone = do- newParagraph--, exampleProgress = \h _ p -> do- hPutStr h (formatProgress p)- hFlush h--, exampleSucceeded = \(nesting, requirement) -> withSuccessColor $ do- writeLine $ indentationFor nesting ++ "- " ++ requirement--, exampleFailed = \(nesting, requirement) _ -> withFailColor $ do- n <- getFailCount- writeLine $ indentationFor nesting ++ "- " ++ requirement ++ " FAILED [" ++ show n ++ "]"--, examplePending = \(nesting, requirement) reason -> withPendingColor $ do- writeLine $ indentationFor nesting ++ "- " ++ requirement ++ "\n # PENDING: " ++ fromMaybe "No reason given" reason--, failedFormatter = defaultFailedFormatter--, footerFormatter = defaultFooter-} where- indentationFor nesting = replicate (length nesting * 2) ' '- formatProgress (current, total)- | total == 0 = show current ++ "\r"- | otherwise = show current ++ "/" ++ show total ++ "\r"---progress :: Formatter-progress = silent {- exampleSucceeded = \_ -> withSuccessColor $ write "."-, exampleFailed = \_ _ -> withFailColor $ write "F"-, examplePending = \_ _ -> withPendingColor $ write "."-, failedFormatter = defaultFailedFormatter-, footerFormatter = defaultFooter-}---failed_examples :: Formatter-failed_examples = silent {- failedFormatter = defaultFailedFormatter-, footerFormatter = defaultFooter-}--defaultFailedFormatter :: FormatM ()-defaultFailedFormatter = do- newParagraph-- failures <- getFailMessages-- forM_ (zip [1..] failures) $ \x -> do- formatFailure x- writeLine ""- unless (null failures) $ do- write "Randomized with seed " >> usedSeed >>= writeLine . show- writeLine ""- where- formatFailure :: (Int, FailureRecord) -> FormatM ()- formatFailure (n, FailureRecord path reason) = do- write (show n ++ ") ")- writeLine (formatRequirement path)- withFailColor $ do- unless (null err) $ do- writeLine err- where- err = either (("uncaught exception: " ++) . formatException) id reason---- | Convert an exception to a string.------ The type of the exception is included. Here is an example:------ >>> import Control.Applicative--- >>> import Control.Exception--- >>> either formatException show <$> (try . evaluate) (1 `div` 0)--- "ArithException (divide by zero)"-formatException :: E.SomeException -> String-formatException (E.SomeException e) = showType e ++ " (" ++ show e ++ ")"--defaultFooter :: FormatM ()-defaultFooter = do-- writeLine =<< (++)- <$> (printf "Finished in %1.4f seconds"- <$> getRealTime) <*> (maybe "" (printf ", used %1.4f seconds of CPU time") <$> getCPUTime)-- fails <- getFailCount- pending <- getPendingCount- total <- getTotalCount-- let c | fails /= 0 = withFailColor- | pending /= 0 = withPendingColor- | otherwise = withSuccessColor- c $ do- write $ pluralize total "example"- write (", " ++ pluralize fails "failure")- unless (pending == 0) $- write (", " ++ show pending ++ " pending")- writeLine ""+-- Stability: deprecated+module Test.Hspec.Formatters+{-# DEPRECATED "Use [Test.Hspec.Api.Formatters.V1](https://hackage.haskell.org/package/hspec-api/docs/Test-Hspec-Api-Formatters-V1.html) instead." #-}+(module Test.Hspec.Core.Formatters.V1)+where+import Test.Hspec.Core.Formatters.V1
− src/Test/Hspec/Formatters/Internal.hs
@@ -1,263 +0,0 @@-{-# LANGUAGE GeneralizedNewtypeDeriving #-}-module Test.Hspec.Formatters.Internal (---- * Public API- Formatter (..)-, FormatM--, getSuccessCount-, getPendingCount-, getFailCount-, getTotalCount--, FailureRecord (..)-, getFailMessages-, usedSeed--, getCPUTime-, getRealTime--, write-, writeLine-, newParagraph--, withSuccessColor-, withPendingColor-, withFailColor---- * Functions for internal use-, runFormatM-, increaseSuccessCount-, increasePendingCount-, increaseFailCount-, addFailMessage-, finally_-) where--import qualified System.IO as IO-import System.IO (Handle)-import Control.Monad (when, unless)-import Control.Applicative-import Control.Exception (SomeException, AsyncException(..), bracket_, try, throwIO)-import System.Console.ANSI-import Control.Monad.Trans.State hiding (gets, modify)-import Control.Monad.IO.Class-import qualified System.CPUTime as CPUTime-import Data.Time.Clock.POSIX (POSIXTime, getPOSIXTime)--import Test.Hspec.Util (Path)-import Test.Hspec.Compat-import Test.Hspec.Core.Type (Progress)---- | A lifted version of `Control.Monad.Trans.State.gets`-gets :: (FormatterState -> a) -> FormatM a-gets f = FormatM $ do- f <$> (get >>= liftIO . readIORef)---- | A lifted version of `Control.Monad.Trans.State.modify`-modify :: (FormatterState -> FormatterState) -> FormatM ()-modify f = FormatM $ do- get >>= liftIO . (`modifyIORef'` f)--data FormatterState = FormatterState {- stateHandle :: Handle-, stateUseColor :: Bool-, produceHTML :: Bool-, lastIsEmptyLine :: Bool -- True, if last line was empty-, successCount :: Int-, pendingCount :: Int-, failCount :: Int-, failMessages :: [FailureRecord]-, stateUsedSeed :: Integer-, cpuStartTime :: Maybe Integer-, startTime :: POSIXTime-}---- | The random seed that is used for QuickCheck.-usedSeed :: FormatM Integer-usedSeed = gets stateUsedSeed---- | The total number of examples encountered so far.-totalCount :: FormatterState -> Int-totalCount s = successCount s + pendingCount s + failCount s---- NOTE: We use an IORef here, so that the state persists when UserInterrupt is--- thrown.-newtype FormatM a = FormatM (StateT (IORef FormatterState) IO a)- deriving (Functor, Applicative, Monad, MonadIO)--runFormatM :: Bool -> Bool -> Bool -> Integer -> Handle -> FormatM a -> IO a-runFormatM useColor produceHTML_ printCpuTime seed handle (FormatM action) = do- time <- getPOSIXTime- cpuTime <- if printCpuTime then Just <$> CPUTime.getCPUTime else pure Nothing- st <- newIORef (FormatterState handle useColor produceHTML_ False 0 0 0 [] seed cpuTime time)- evalStateT action st---- | Increase the counter for successful examples-increaseSuccessCount :: FormatM ()-increaseSuccessCount = modify $ \s -> s {successCount = succ $ successCount s}---- | Increase the counter for pending examples-increasePendingCount :: FormatM ()-increasePendingCount = modify $ \s -> s {pendingCount = succ $ pendingCount s}---- | Increase the counter for failed examples-increaseFailCount :: FormatM ()-increaseFailCount = modify $ \s -> s {failCount = succ $ failCount s}---- | Get the number of successful examples encountered so far.-getSuccessCount :: FormatM Int-getSuccessCount = gets successCount---- | Get the number of pending examples encountered so far.-getPendingCount :: FormatM Int-getPendingCount = gets pendingCount---- | Get the number of failed examples encountered so far.-getFailCount :: FormatM Int-getFailCount = gets failCount---- | Get the total number of examples encountered so far.-getTotalCount :: FormatM Int-getTotalCount = gets totalCount---- | Append to the list of accumulated failure messages.-addFailMessage :: Path -> Either SomeException String -> FormatM ()-addFailMessage p m = modify $ \s -> s {failMessages = FailureRecord p m : failMessages s}---- | Get the list of accumulated failure messages.-getFailMessages :: FormatM [FailureRecord]-getFailMessages = reverse `fmap` gets failMessages--data FailureRecord = FailureRecord {- failureRecordPath :: Path-, failureRecordMessage :: Either SomeException String-}--data Formatter = Formatter {-- headerFormatter :: FormatM ()---- | evaluated before each test group------ The given number indicates the position within the parent group.-, exampleGroupStarted :: Int -> [String] -> String -> FormatM ()--, exampleGroupDone :: FormatM ()---- | used to notify the progress of the currently evaluated example------ NOTE: This is only called when interactive/color mode.-, exampleProgress :: Handle -> Path -> Progress -> IO ()---- | evaluated after each successful example-, exampleSucceeded :: Path -> FormatM ()---- | evaluated after each failed example-, exampleFailed :: Path -> Either SomeException String -> FormatM ()---- | evaluated after each pending example-, examplePending :: Path -> Maybe String -> FormatM ()---- | evaluated after a test run-, failedFormatter :: FormatM ()---- | evaluated after `failuresFormatter`-, footerFormatter :: FormatM ()-}----- | Append an empty line to the report.------ Calling this multiple times has the same effect as calling it once.-newParagraph :: FormatM ()-newParagraph = do- f <- gets lastIsEmptyLine- unless f $ do- writeLine ""- setLastIsEmptyLine True--setLastIsEmptyLine :: Bool -> FormatM ()-setLastIsEmptyLine f = modify $ \s -> s {lastIsEmptyLine = f}---- | Append some output to the report.-write :: String -> FormatM ()-write s = do- h <- gets stateHandle- liftIO $ IO.hPutStr h s- setLastIsEmptyLine False---- | The same as `write`, but adds a newline character.-writeLine :: String -> FormatM ()-writeLine s = write s >> write "\n"---- | Set output color to red, run given action, and finally restore the default--- color.-withFailColor :: FormatM a -> FormatM a-withFailColor = withColor (SetColor Foreground Dull Red) "hspec-failure"---- | Set output to color green, run given action, and finally restore the--- default color.-withSuccessColor :: FormatM a -> FormatM a-withSuccessColor = withColor (SetColor Foreground Dull Green) "hspec-success"---- | Set output color to yellow, run given action, and finally restore the--- default color.-withPendingColor :: FormatM a -> FormatM a-withPendingColor = withColor (SetColor Foreground Dull Yellow) "hspec-pending"---- | Set a color, run an action, and finally reset colors.-withColor :: SGR -> String -> FormatM a -> FormatM a-withColor color cls action = do- r <- gets produceHTML- (if r then htmlSpan cls else withColor_ color) action--htmlSpan :: String -> FormatM a -> FormatM a-htmlSpan cls action = write ("<span class=\"" ++ cls ++ "\">") *> action <* write "</span>"--withColor_ :: SGR -> FormatM a -> FormatM a-withColor_ color (FormatM action) = do- useColor <- gets stateUseColor- h <- gets stateHandle-- FormatM . StateT $ \st -> do- bracket_-- -- set color- (when useColor $ hSetSGR h [color])-- -- reset colors- (when useColor $ hSetSGR h [Reset])-- -- run action- (runStateT action st)---- |--- @finally_ actionA actionB@ runs @actionA@ and then @actionB@. @actionB@ is--- run even when a `UserInterrupt` occurs during @actionA@.-finally_ :: FormatM () -> FormatM () -> FormatM ()-finally_ (FormatM actionA) (FormatM actionB) = FormatM . StateT $ \st -> do- r <- try (execStateT actionA st)- case r of- Left e -> do- when (e == UserInterrupt) $- runStateT actionB st >> return ()- throwIO e- Right st_ -> do- runStateT actionB st_---- | Get the used CPU time since the test run has been started.-getCPUTime :: FormatM (Maybe Double)-getCPUTime = do- t1 <- liftIO CPUTime.getCPUTime- mt0 <- gets cpuStartTime- return $ toSeconds <$> ((-) <$> pure t1 <*> mt0)- where- toSeconds x = fromIntegral x / (10.0 ^ (12 :: Integer))---- | Get the passed real time since the test run has been started.-getRealTime :: FormatM Double-getRealTime = do- t1 <- liftIO getPOSIXTime- t0 <- gets startTime- return (realToFrac $ t1 - t0)
− src/Test/Hspec/HUnit.hs
@@ -1,39 +0,0 @@-{-# OPTIONS -fno-warn-orphans #-}-module Test.Hspec.HUnit (--- * Interoperability with HUnit- fromHUnitTest-) where--import Data.List (intercalate)-import qualified Test.HUnit as HU-import Test.HUnit (Test (..))--import Test.Hspec.Core.Type---- | This instance is deprecated, use `Test.Hspec.HUnit.fromHUnitTest` instead!-instance Example Test where- evaluateExample test _ _ = do- (counts, fails) <- HU.runTestText HU.putTextToShowS test- let r = if HU.errors counts + HU.failures counts == 0- then Success- else Fail (details $ fails "")- return r- where- details :: String -> String- details = intercalate "\n" . tail . init . lines---- |--- Convert a HUnit test suite to a spec. This can be used to run existing--- HUnit tests with Hspec.-fromHUnitTest :: Test -> Spec-fromHUnitTest t = fromSpecList $ case t of- TestList xs -> map go xs- x -> [go x]- where- go :: Test -> SpecTree- go t_ = case t_ of- TestLabel s (TestCase e) -> it s e- TestLabel s (TestList xs) -> describe s (map go xs)- TestLabel s x -> describe s [go x]- TestList xs -> describe "<unlabeled>" (map go xs)- TestCase e -> it "<unlabeled>" e
− src/Test/Hspec/Monadic.hs
@@ -1,53 +0,0 @@-{-# OPTIONS_HADDOCK not-home #-}-module Test.Hspec.Monadic {-# DEPRECATED "use \"Test.Hspec\", \"Test.Hspec.Runner\" or \"Test.Hspec.Core\" instead" #-} (--- * Types- Spec-, Example---- * Defining a spec-, describe-, context-, it-, pending---- * Running a spec-, hspec-, Summary (..)---- * Interface to the non-monadic API-, runSpecM-, fromSpecList---- * Deprecated types and functions-, Specs-, descriptions-, hspecB-, hspecX-, hHspec-) where--import System.IO-import Control.Applicative--import Test.Hspec.Core (runSpecM, fromSpecList)-import Test.Hspec.Runner-import Test.Hspec--{-# DEPRECATED Specs "use `Spec` instead" #-} -- since 1.2.0-type Specs = Spec--{-# DEPRECATED descriptions "use `sequence_` instead" #-} -- since 1.0.0-descriptions :: [Spec] -> Spec-descriptions = sequence_--{-# DEPRECATED hspecX "use `hspec` instead" #-} -- since 1.2.0-hspecX :: Spec -> IO ()-hspecX = hspec--{-# DEPRECATED hspecB "use `hspecWith` instead" #-} -- since 1.4.0-hspecB :: Spec -> IO Bool-hspecB spec = (== 0) . summaryFailures <$> hspecWith defaultConfig spec--{-# DEPRECATED hHspec "use hspecWith instead" #-} -- since 1.4.0-hHspec :: Handle -> Spec -> IO Summary-hHspec h = hspecWith defaultConfig {configHandle = Left h}
− src/Test/Hspec/Options.hs
@@ -1,157 +0,0 @@-module Test.Hspec.Options (- Options (..)-, ColorMode (..)-, defaultOptions-, parseOptions---- exported to silence warnings-, Arg (..)-) where--import Data.List-import System.Exit-import System.Console.GetOpt-import Test.Hspec.Formatters--import Test.Hspec.Compat-import Test.Hspec.Util---- for Monad (Either e) when base < 4.3-import Control.Monad.Trans.Error ()--data Options = Options {- optionsDryRun :: Bool-, optionsPrintCpuTime :: Bool-, optionsRerun :: Bool-, optionsFastFail :: Bool-, optionsMatch :: [String]-, optionsMaxSuccess :: Maybe Int-, optionsDepth :: Maybe Int-, optionsSeed :: Maybe Integer-, optionsMaxSize :: Maybe Int-, optionsMaxDiscardRatio :: Maybe Int-, optionsColorMode :: ColorMode-, optionsFormatter :: Formatter-, optionsHtmlOutput :: Bool-, optionsOutputFile :: Maybe FilePath-}--addMatch :: String -> Options -> Options-addMatch s c = c {optionsMatch = s : optionsMatch c}--setDepth :: Int -> Options -> Options-setDepth n c = c {optionsDepth = Just n}--setMaxSuccess :: Int -> Options -> Options-setMaxSuccess n c = c {optionsMaxSuccess = Just n}--setMaxSize :: Int -> Options -> Options-setMaxSize n c = c {optionsMaxSize = Just n}--setMaxDiscardRatio :: Int -> Options -> Options-setMaxDiscardRatio n c = c {optionsMaxDiscardRatio = Just n}--setSeed :: Integer -> Options -> Options-setSeed n c = c {optionsSeed = Just n}--data ColorMode = ColorAuto | ColorNever | ColorAlways- deriving (Eq, Show)--defaultOptions :: Options-defaultOptions = Options False False False False [] Nothing Nothing Nothing Nothing Nothing ColorAuto specdoc False Nothing--formatters :: [(String, Formatter)]-formatters = [- ("specdoc", specdoc)- , ("progress", progress)- , ("failed-examples", failed_examples)- , ("silent", silent)- ]--formatHelp :: String-formatHelp = unlines (addLineBreaks "use a custom formatter; this can be one of:" ++ map ((" " ++) . fst) formatters)--type Result = Either NoConfig Options--data NoConfig = Help | InvalidArgument String String--data Arg a = Arg {- argumentName :: String-, argumentParser :: String -> Maybe a-, argumentSetter :: a -> Options -> Options-}--mkOption :: [Char] -> String -> Arg a -> String -> OptDescr (Result -> Result)-mkOption shortcut name (Arg argName parser setter) help = Option shortcut [name] (ReqArg arg argName) help- where- arg :: String -> Result -> Result- arg input x = x >>= \c -> case parser input of- Just n -> Right (setter n c)- Nothing -> Left (InvalidArgument name input)--addLineBreaks :: String -> [String]-addLineBreaks = lineBreaksAt 44--options :: [OptDescr (Result -> Result)]-options = [- Option [] ["help"] (NoArg (const $ Left Help)) (h "display this help and exit")- , mkOption "m" "match" (Arg "PATTERN" return addMatch) (h "only run examples that match given PATTERN")- , Option [] ["color"] (NoArg setColor) (h "colorize the output")- , Option [] ["no-color"] (NoArg setNoColor) (h "do not colorize the output")- , mkOption "f" "format" (Arg "FORMATTER" readFormatter setFormatter) formatHelp- , mkOption "o" "out" (Arg "FILE" return setOutputFile) (h "write output to a file instead of STDOUT")- , mkOption [] "depth" (Arg "N" readMaybe setDepth) (h "maximum depth of generated test values for SmallCheck properties")- , mkOption "a" "qc-max-success" (Arg "N" readMaybe setMaxSuccess) (h "maximum number of successful tests before a QuickCheck property succeeds")- , mkOption "" "qc-max-size" (Arg "N" readMaybe setMaxSize) (h "size to use for the biggest test cases")- , mkOption "" "qc-max-discard" (Arg "N" readMaybe setMaxDiscardRatio) (h "maximum number of discarded tests per successful test before giving up")- , mkOption [] "seed" (Arg "N" readMaybe setSeed) (h "used seed for QuickCheck properties")- , Option [] ["print-cpu-time"] (NoArg setPrintCpuTime) (h "include used CPU time in summary")- , Option [] ["dry-run"] (NoArg setDryRun) (h "pretend that everything passed; don't verify anything")- , Option [] ["fail-fast"] (NoArg setFastFail) (h "abort on first failure")- , Option "r" ["rerun"] (NoArg setRerun) (h "rerun all examples that failed in the previously test run (only works in GHCi)")- ]- where- h = unlines . addLineBreaks-- readFormatter :: String -> Maybe Formatter- readFormatter = (`lookup` formatters)-- setFormatter :: Formatter -> Options -> Options- setFormatter f c = c {optionsFormatter = f}-- setOutputFile :: String -> Options -> Options- setOutputFile file c = c {optionsOutputFile = Just file}-- setPrintCpuTime x = x >>= \c -> return c {optionsPrintCpuTime = True}- setDryRun x = x >>= \c -> return c {optionsDryRun = True}- setFastFail x = x >>= \c -> return c {optionsFastFail = True}- setRerun x = x >>= \c -> return c {optionsRerun = True}- setNoColor x = x >>= \c -> return c {optionsColorMode = ColorNever}- setColor x = x >>= \c -> return c {optionsColorMode = ColorAlways}--undocumentedOptions :: [OptDescr (Result -> Result)]-undocumentedOptions = [- -- for compatibility with test-framework- mkOption [] "maximum-generated-tests" (Arg "NUMBER" readMaybe setMaxSuccess) "how many automated tests something like QuickCheck should try, by default"-- -- undocumented for now, as we probably want to change this to produce a- -- standalone HTML report in the future- , Option [] ["html"] (NoArg setHtml) "produce HTML output"-- -- now a noop- , Option "v" ["verbose"] (NoArg id) "do not suppress output to stdout when evaluating examples"- ]- where- setHtml :: Result -> Result- setHtml x = x >>= \c -> return c {optionsHtmlOutput = True}--parseOptions :: Options -> String -> [String] -> Either (ExitCode, String) Options-parseOptions c prog args = case getOpt Permute (options ++ undocumentedOptions) args of- (opts, [], []) -> case foldl' (flip id) (Right c) opts of- Left Help -> Left (ExitSuccess, usageInfo ("Usage: " ++ prog ++ " [OPTION]...\n\nOPTIONS") options)- Left (InvalidArgument flag value) -> tryHelp ("invalid argument `" ++ value ++ "' for `--" ++ flag ++ "'\n")- Right x -> Right x- (_, _, err:_) -> tryHelp err- (_, arg:_, _) -> tryHelp ("unexpected argument `" ++ arg ++ "'\n")- where- tryHelp msg = Left (ExitFailure 1, prog ++ ": " ++ msg ++ "Try `" ++ prog ++ " --help' for more information.\n")
src/Test/Hspec/QuickCheck.hs view
@@ -1,24 +1,22 @@--- |--- Stability: provisional+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE ConstraintKinds #-} module Test.Hspec.QuickCheck ( -- * Params- modifyMaxSuccess+ modifyArgs+, modifyMaxSuccess , modifyMaxDiscardRatio , modifyMaxSize--- * Re-exports from QuickCheck--- |--- Previous versions of Hspec provided a distinct `property` combinator, but--- it's now possible to use QuickCheck's `property` instead. For backward--- compatibility we now re-export QuickCheck's `property`, but it is advisable--- to import it from "Test.QuickCheck" instead.-, property+, modifyMaxShrinks+ -- * Shortcuts , prop+, xprop+, fprop ) where -import Test.QuickCheck import Test.Hspec-import Test.Hspec.Core (Params(..), modifyParams)+import Test.QuickCheck+import Test.Hspec.Core.QuickCheck -- | -- > prop ".." $@@ -26,34 +24,37 @@ -- -- is a shortcut for ----- > it ".." $ property $--- > ..-prop :: Testable prop => String -> prop -> Spec+-- @+-- `it` ".." $ `property` $+-- ..+-- @+prop :: (HasCallStack, Testable prop) => String -> prop -> Spec prop s = it s . property --- | Use a modified `maxSuccess` for given spec.-modifyMaxSuccess :: (Int -> Int) -> Spec -> Spec-modifyMaxSuccess = modifyArgs . modify- where- modify :: (Int -> Int) -> Args -> Args- modify f args = args {maxSuccess = f (maxSuccess args)} --- | Use a modified `maxDiscardRatio` for given spec.-modifyMaxDiscardRatio :: (Int -> Int) -> Spec -> Spec-modifyMaxDiscardRatio = modifyArgs . modify- where- modify :: (Int -> Int) -> Args -> Args- modify f args = args {maxDiscardRatio = f (maxDiscardRatio args)}+-- |+-- > xprop ".." $+-- > ..+--+-- is a shortcut for+--+-- @+-- `xit` ".." $ `property` $+-- ..+-- @+xprop :: (HasCallStack, Testable prop) => String -> prop -> Spec+xprop s = xit s . property --- | Use a modified `maxSize` for given spec.-modifyMaxSize :: (Int -> Int) -> Spec -> Spec-modifyMaxSize = modifyArgs . modify- where- modify :: (Int -> Int) -> Args -> Args- modify f args = args {maxSize = f (maxSize args)} -modifyArgs :: (Args -> Args) -> Spec -> Spec-modifyArgs = modifyParams . modify- where- modify :: (Args -> Args) -> Params -> Params- modify f p = p {paramsQuickCheckArgs = f (paramsQuickCheckArgs p)}+-- |+-- > fprop ".." $+-- > ..+--+-- is a shortcut for+--+-- @+-- `fit` ".." $ `property` $+-- ..+-- @+fprop :: (HasCallStack, Testable prop) => String -> prop -> Spec+fprop s = fit s . property
src/Test/Hspec/Runner.hs view
@@ -1,163 +1,2 @@--- |--- Stability: provisional-module Test.Hspec.Runner (--- * Running a spec- hspec-, hspecResult-, hspecWith---- * Types-, Summary (..)-, Config (..)-, ColorMode (..)-, Path-, defaultConfig-, configAddFilter---- * Internals-, hspecWithFormatter-) where--import Control.Monad-import Control.Applicative-import Data.Monoid-import Data.Maybe-import System.IO-import System.Environment (getProgName, getArgs, withArgs)-import System.Exit-import qualified Control.Exception as E--import System.Console.ANSI (hHideCursor, hShowCursor)-import qualified Test.QuickCheck as QC-import System.Random (newStdGen)-import Control.Monad.IO.Class (liftIO)--import Test.Hspec.Compat (lookupEnv)-import Test.Hspec.Util (Path, stdGenToInteger)-import Test.Hspec.Core.Type-import Test.Hspec.Config-import Test.Hspec.Formatters-import Test.Hspec.Formatters.Internal-import Test.Hspec.FailureReport--import Test.Hspec.Options (Options(..), ColorMode(..), defaultOptions)-import Test.Hspec.Runner.Eval---- | Filter specs by given predicate.------ The predicate takes a list of "describe" labels and a "requirement".-filterSpecs :: (Path -> Bool) -> [SpecTree] -> [SpecTree]-filterSpecs p = goSpecs []- where- goSpecs :: [String] -> [SpecTree] -> [SpecTree]- goSpecs groups = mapMaybe (goSpec groups)-- goSpec :: [String] -> SpecTree -> Maybe SpecTree- goSpec groups spec = case spec of- SpecItem item -> guard (p (groups, itemRequirement item)) >> return spec- SpecGroup group specs -> case goSpecs (groups ++ [group]) specs of- [] -> Nothing- xs -> Just (SpecGroup group xs)---- | Run given spec and write a report to `stdout`.--- Exit with `exitFailure` if at least one spec item fails.-hspec :: Spec -> IO ()-hspec = hspecWithOptions defaultOptions---- | This function is used by @hspec-discover@. It is not part of the public--- API and may change at any time.-hspecWithFormatter :: IsFormatter a => a -> Spec -> IO ()-hspecWithFormatter formatter spec = do- f <- toFormatter formatter- hspecWithOptions defaultOptions {optionsFormatter = f} spec---- Add a StdGen to configQuickCheckArgs if there is none. That way the same--- seed is used for all properties. This helps with --seed and --rerun.-ensureStdGen :: Config -> IO Config-ensureStdGen c = case QC.replay qcArgs of- Nothing -> do- stdGen <- newStdGen- return c {configQuickCheckArgs = qcArgs {QC.replay = Just (stdGen, 0)}}- _ -> return c- where- qcArgs = configQuickCheckArgs c---- | Run given spec with custom options.--- This is similar to `hspec`, but more flexible.-hspecWithOptions :: Options -> Spec -> IO ()-hspecWithOptions opts spec = do- prog <- getProgName- args <- getArgs- c <- getConfig opts prog args- withArgs [] {- do not leak command-line arguments to examples -} $ do- r <- hspecWith c spec- unless (summaryFailures r == 0) exitFailure---- | Run given spec and returns a summary of the test run.------ /Note/: `hspecResult` does not exit with `exitFailure` on failing spec--- items. If you need this, you have to check the `Summary` yourself and act--- accordingly.-hspecResult :: Spec -> IO Summary-hspecResult = hspecWith defaultConfig---- | Run given spec with custom options and returns a summary of the test run.------ /Note/: `hspecWith` does not exit with `exitFailure` on failing spec--- items. If you need this, you have to check the `Summary` yourself and act--- accordingly.-hspecWith :: Config -> Spec -> IO Summary-hspecWith c_ spec = withHandle c_ $ \h -> do- c <- ensureStdGen c_- let formatter = configFormatter c- seed = (stdGenToInteger . fst . fromJust . QC.replay . configQuickCheckArgs) c-- useColor <- doesUseColor h c-- withHiddenCursor useColor h $- runFormatM useColor (configHtmlOutput c) (configPrintCpuTime c) seed h $ do- runFormatter useColor h c formatter (maybe id filterSpecs (configFilterPredicate c) $ runSpecM spec) `finally_` do- failedFormatter formatter-- footerFormatter formatter-- -- dump failure report- xs <- map failureRecordPath <$> getFailMessages- liftIO $ writeFailureReport FailureReport {- failureReportSeed = seed- , failureReportMaxSuccess = QC.maxSuccess (configQuickCheckArgs c)- , failureReportMaxSize = QC.maxSize (configQuickCheckArgs c)- , failureReportMaxDiscardRatio = QC.maxDiscardRatio (configQuickCheckArgs c)- , failureReportPaths = xs- }-- Summary <$> getTotalCount <*> getFailCount- where- withHiddenCursor :: Bool -> Handle -> IO a -> IO a- withHiddenCursor useColor h- | useColor = E.bracket_ (hHideCursor h) (hShowCursor h)- | otherwise = id-- doesUseColor :: Handle -> Config -> IO Bool- doesUseColor h c = case configColorMode c of- ColorAuto -> (&&) <$> hIsTerminalDevice h <*> (not <$> isDumb)- ColorNever -> return False- ColorAlways -> return True-- withHandle :: Config -> (Handle -> IO a) -> IO a- withHandle c action = case configHandle c of- Left h -> action h- Right path -> withFile path WriteMode action--isDumb :: IO Bool-isDumb = maybe False (== "dumb") <$> lookupEnv "TERM"---- | Summary of a test run.-data Summary = Summary {- summaryExamples :: Int-, summaryFailures :: Int-} deriving (Eq, Show)--instance Monoid Summary where- mempty = Summary 0 0- (Summary x1 x2) `mappend` (Summary y1 y2) = Summary (x1 + y1) (x2 + y2)+module Test.Hspec.Runner (module Test.Hspec.Core.Runner) where+import Test.Hspec.Core.Runner
− src/Test/Hspec/Runner/Eval.hs
@@ -1,125 +0,0 @@-module Test.Hspec.Runner.Eval (runFormatter) where--import Control.Monad-import qualified Control.Exception as E-import Control.Concurrent-import System.IO (Handle)--import Control.Monad.IO.Class (liftIO)--import Test.Hspec.Util-import Test.Hspec.Core.Type-import Test.Hspec.Config-import Test.Hspec.Formatters-import Test.Hspec.Formatters.Internal-import Test.Hspec.Timer-import Data.Time.Clock.POSIX---- | Evaluate all examples of a given spec and produce a report.-runFormatter :: Bool -> Handle -> Config -> Formatter -> [SpecTree] -> FormatM ()-runFormatter useColor h c formatter specs = do- headerFormatter formatter- chan <- liftIO newChan- run chan useColor h c formatter specs--data Message = Done | Run (FormatM ())--data Report = ReportProgress Progress | ReportResult (Either E.SomeException Result)--run :: Chan Message -> Bool -> Handle -> Config -> Formatter -> [SpecTree] -> FormatM ()-run chan useColor h c formatter specs = do- liftIO $ do- forM_ (zip [0..] specs) (queueSpec [])- writeChan chan Done- processChan chan (configFastFail c)- where- defer = writeChan chan . Run-- queueSpec :: [String] -> (Int, SpecTree) -> IO ()- queueSpec rGroups (n, SpecGroup group xs) = do- defer (exampleGroupStarted formatter n (reverse rGroups) group)- forM_ (zip [0..] xs) (queueSpec (group : rGroups))- defer (exampleGroupDone formatter)- queueSpec rGroups (_, SpecItem (Item isParallelizable requirement e)) =- queueExample isParallelizable (reverse rGroups, requirement) (`e` id)-- queueExample :: Bool -> Path -> (Params -> IO Result) -> IO ()- queueExample isParallelizable path e- | isParallelizable = runParallel- | otherwise = defer runSequentially- where- runSequentially :: FormatM ()- runSequentially = do- progressHandler <- liftIO (mkProgressHandler reportProgress)- result <- liftIO (evalExample e progressHandler)- formatResult formatter path result-- runParallel = do- mvar <- newEmptyMVar- _ <- forkIO $ do- progressHandler <- mkProgressHandler (replaceMVar mvar . ReportProgress)- result <- evalExample e progressHandler- replaceMVar mvar (ReportResult result)- defer (evalReport mvar)- where- evalReport :: MVar Report -> FormatM ()- evalReport mvar = do- r <- liftIO (takeMVar mvar)- case r of- ReportProgress p -> do- liftIO $ reportProgress p- evalReport mvar- ReportResult result -> formatResult formatter path result-- reportProgress :: (Int, Int) -> IO ()- reportProgress = exampleProgress formatter h path-- mkProgressHandler :: (a -> IO ()) -> IO (a -> IO ())- mkProgressHandler report- | useColor = every 0.05 report- | otherwise = return . const $ return ()-- evalExample :: (Params -> IO Result) -> (Progress -> IO ()) -> IO (Either E.SomeException Result)- evalExample e progressHandler- | configDryRun c = return (Right Success)- | otherwise = (safeTry . fmap forceResult) (e $ Params (configQuickCheckArgs c) (configSmallCheckDepth c) progressHandler)--replaceMVar :: MVar a -> a -> IO ()-replaceMVar mvar p = tryTakeMVar mvar >> putMVar mvar p--processChan :: Chan Message -> Bool -> FormatM ()-processChan chan fastFail = go- where- go = do- m <- liftIO (readChan chan)- case m of- Run action -> do- action- fails <- getFailCount- unless (fastFail && fails /= 0) go- Done -> return ()--formatResult :: Formatter -> ([String], String) -> Either E.SomeException Result -> FormatM ()-formatResult formatter path result = do- case result of- Right Success -> do- increaseSuccessCount- exampleSucceeded formatter path- Right (Pending reason) -> do- increasePendingCount- examplePending formatter path reason- Right (Fail err) -> failed (Right err)- Left e -> failed (Left e)- where- failed err = do- increaseFailCount- addFailMessage path err- exampleFailed formatter path err---- | Execute given action at most every specified number of seconds.-every :: POSIXTime -> (a -> IO ()) -> IO (a -> IO ())-every seconds action = do- timer <- newTimer seconds- return $ \a -> do- r <- timer- when r (action a)
− src/Test/Hspec/Timer.hs
@@ -1,14 +0,0 @@-module Test.Hspec.Timer where--import Data.IORef-import Data.Time.Clock.POSIX--newTimer :: POSIXTime -> IO (IO Bool)-newTimer delay = do- ref <- getPOSIXTime >>= newIORef- return $ do- t0 <- readIORef ref- t1 <- getPOSIXTime- if delay < t1 - t0- then writeIORef ref t1 >> return True- else return False
− src/Test/Hspec/Util.hs
@@ -1,106 +0,0 @@-module Test.Hspec.Util (- pluralize-, lineBreaksAt-, safeTry-, Path-, filterPredicate-, formatRequirement-, strip-, stdGenToInteger-, stdGenFromInteger-) where--import Data.Int (Int32)-import Data.List-import Data.Char (isSpace)-import Control.Applicative-import qualified Control.Exception as E-import System.Random (StdGen)---- | Create a more readable display of a quantity of something.------ Examples:------ >>> pluralize 0 "example"--- "0 examples"------ >>> pluralize 1 "example"--- "1 example"------ >>> pluralize 2 "example"--- "2 examples"-pluralize :: Int -> String -> String-pluralize 1 s = "1 " ++ s-pluralize n s = show n ++ " " ++ s ++ "s"--safeTry :: IO a -> IO (Either E.SomeException a)-safeTry action = (Right <$> (action >>= E.evaluate)) `E.catches` [- -- Re-throw AsyncException, otherwise execution will not terminate on SIGINT- -- (ctrl-c). All AsyncExceptions are re-thrown (not just UserInterrupt)- -- because all of them indicate severe conditions and should not occur during- -- normal operation.- E.Handler $ \e -> E.throwIO (e :: E.AsyncException)-- , E.Handler $ \e -> (return . Left) (e :: E.SomeException)- ]---- |--- A tuple that represents the location of an example within a spec.------ It consists of a list of group descriptions and a requirement description.-type Path = ([String], String)---- | A predicate that can be used to filter specs.-filterPredicate :: String -> Path -> Bool-filterPredicate pattern path@(groups, requirement) =- pattern `isInfixOf` plain- || pattern `isInfixOf` formatted- where- plain = intercalate "/" (groups ++ [requirement])- formatted = formatRequirement path---- |--- Try to create a proper English sentence from a path by applying some--- heuristics.-formatRequirement :: Path -> String-formatRequirement (groups, requirement) = groups_ ++ requirement- where- groups_ = case break (any isSpace) groups of- ([], ys) -> join ys- (xs, ys) -> join (intercalate "." xs : ys)-- join xs = case xs of- [x] -> x ++ " "- ys -> concatMap (++ ", ") ys---- ensure that lines are not longer then given `n`, insert line breaks at word--- boundaries-lineBreaksAt :: Int -> String -> [String]-lineBreaksAt n input = case words input of- [] -> []- x:xs -> go (x, xs)- where- go :: (String, [String]) -> [String]- go c = case c of- (s, []) -> [s]- (s, y:ys) -> let r = s ++ " " ++ y in- if length r <= n- then go (r, ys)- else s : go (y, ys)--strip :: String -> String-strip = dropWhile isSpace . reverse . dropWhile isSpace . reverse---- | Converts a 'StdGen' into an 'Integer'. Assumes--- StdGens to be encoded as two positive 'Int32's and--- $show (StdGen a b) = show a ++ " " ++ show b$.-stdGenToInteger :: StdGen -> Integer-stdGenToInteger stdGen =- let [a, b] = map read . words $ show stdGen- in b * fromIntegral (maxBound :: Int32) + a---- | Inverse of 'stdGenToInteger'.-stdGenFromInteger :: Integer -> StdGen-stdGenFromInteger n =- let (a, b) = quotRem n (fromIntegral (maxBound :: Int32))- in read (show b ++ " " ++ show a)
− test/Helper.hs
@@ -1,81 +0,0 @@-module Helper (- module Test.Hspec.Meta-, module Test.QuickCheck-, module Control.Applicative-, module System.IO.Silently-, sleep-, timeout-, defaultParams-, captureLines-, normalizeSummary--, ignoreExitCode-, ignoreUserInterrupt--, shouldStartWith-, shouldEndWith--, shouldUseArgs-) where--import Data.List-import Data.Char-import Data.IORef-import Control.Monad-import Control.Applicative-import System.Environment (withArgs)-import System.Exit-import Control.Concurrent-import qualified Control.Exception as E-import qualified System.Timeout as System-import Data.Time.Clock.POSIX-import System.IO.Silently--import Test.Hspec.Meta-import Test.QuickCheck hiding (Result(..))--import qualified Test.Hspec as H-import qualified Test.Hspec.Core as H (Params(..), Item(..), mapSpecItem)-import qualified Test.Hspec.Runner as H--ignoreExitCode :: IO () -> IO ()-ignoreExitCode action = action `E.catch` \e -> let _ = e :: ExitCode in return ()--ignoreUserInterrupt :: IO () -> IO ()-ignoreUserInterrupt action = action `E.catch` \e -> unless (e == E.UserInterrupt) (E.throwIO e)--captureLines :: IO a -> IO [String]-captureLines = fmap lines . capture_--shouldStartWith :: (Eq a, Show a) => [a] -> [a] -> Expectation-x `shouldStartWith` y = x `shouldSatisfy` isPrefixOf y--shouldEndWith :: (Eq a, Show a) => [a] -> [a] -> Expectation-x `shouldEndWith` y = x `shouldSatisfy` isSuffixOf y---- replace times in summary with zeroes-normalizeSummary :: [String] -> [String]-normalizeSummary xs = map f xs- where- f x | "Finished in " `isPrefixOf` x = map g x- | otherwise = x- g x | isNumber x = '0'- | otherwise = x--defaultParams :: H.Params-defaultParams = H.Params (H.configQuickCheckArgs H.defaultConfig) (H.configSmallCheckDepth H.defaultConfig) (const $ return ())--sleep :: POSIXTime -> IO ()-sleep = threadDelay . floor . (* 1000000)--timeout :: POSIXTime -> IO a -> IO (Maybe a)-timeout = System.timeout . floor . (* 1000000)--shouldUseArgs :: [String] -> (Args -> Bool) -> Expectation-shouldUseArgs args p = do- spy <- newIORef (H.paramsQuickCheckArgs defaultParams)- let interceptArgs item = item {H.itemExample = \params action -> writeIORef spy (H.paramsQuickCheckArgs params) >> H.itemExample item params action}- spec = H.mapSpecItem interceptArgs $- H.it "foo" False- (silence . ignoreExitCode . withArgs args . H.hspec) spec- readIORef spy >>= (`shouldSatisfy` p)
− test/Mock.hs
@@ -1,15 +0,0 @@-module Mock where--import Control.Applicative-import Data.IORef--newtype Mock = Mock (IORef Int)--newMock :: IO Mock-newMock = Mock <$> newIORef 0--mockAction :: Mock -> IO ()-mockAction (Mock ref) = modifyIORef ref succ--mockCounter :: Mock -> IO Int-mockCounter (Mock ref) = readIORef ref
− test/Spec.hs
@@ -1,1 +0,0 @@-{-# OPTIONS_GHC -F -pgmF hspec-meta-discover #-}
− test/Test/Hspec/CompatSpec.hs
@@ -1,33 +0,0 @@-{-# LANGUAGE DeriveDataTypeable #-}-module Test.Hspec.CompatSpec (main, spec) where--import Helper-import System.SetEnv--import Test.Hspec.Compat-import Data.Typeable--data SomeType = SomeType- deriving Typeable--main :: IO ()-main = hspec spec--spec :: Spec-spec = do- describe "showType" $ do- it "shows unqualified name of type" $ do- showType SomeType `shouldBe` "SomeType"-- describe "showFullType (currently unused)" $ do- it "shows fully qualified name of type" $ do- showFullType SomeType `shouldBe` "Test.Hspec.CompatSpec.SomeType"-- describe "lookupEnv" $ do- it "returns value of specified environment variable" $ do- setEnv "FOO" "bar"- lookupEnv "FOO" `shouldReturn` Just "bar"-- it "returns Nothing if specified environment variable is not set" $ do- unsetEnv "FOO"- lookupEnv "FOO" `shouldReturn` Nothing
− test/Test/Hspec/Core/TypeSpec.hs
@@ -1,133 +0,0 @@-module Test.Hspec.Core.TypeSpec (main, spec) where--import Helper-import Mock-import Data.List-import Data.IORef-import Control.Exception (AsyncException(..), throwIO)--import qualified Test.Hspec.Core.Type as H hiding (describe, it)-import qualified Test.Hspec as H-import qualified Test.Hspec.Runner as H--main :: IO ()-main = hspec spec--evaluateExample :: H.Example e => e -> IO H.Result-evaluateExample e = H.evaluateExample e (defaultParams {H.paramsQuickCheckArgs = (H.paramsQuickCheckArgs defaultParams) {replay = Just (read "", 0)}}) id--evaluateExampleWith :: H.Example e => (IO () -> IO ()) -> e -> IO H.Result-evaluateExampleWith action e = H.evaluateExample e (defaultParams {H.paramsQuickCheckArgs = (H.paramsQuickCheckArgs defaultParams) {replay = Just (read "", 0)}}) action--spec :: Spec-spec = do- describe "evaluateExample" $ do- context "for Bool" $ do- it "returns Success on True" $ do- evaluateExample True `shouldReturn` H.Success-- it "returns Fail on False" $ do- evaluateExample False `shouldReturn` H.Fail ""-- it "propagates exceptions" $ do- evaluateExample (error "foobar" :: Bool) `shouldThrow` errorCall "foobar"-- context "for Expectation" $ do- it "returns Success if all expectations hold" $ do- evaluateExample (23 `shouldBe` (23 :: Int)) `shouldReturn` H.Success-- it "returns Fail if an expectation does not hold" $ do- evaluateExample (23 `shouldBe` (42 :: Int)) `shouldReturn` H.Fail "expected: 42\n but got: 23"-- it "propagates exceptions" $ do- evaluateExample (error "foobar" :: Expectation) `shouldThrow` errorCall "foobar"-- it "runs provided action around expectation" $ do- ref <- newIORef (0 :: Int)- let action :: IO () -> IO ()- action e = do- n <- readIORef ref- e- readIORef ref `shouldReturn` succ n- modifyIORef ref succ- evaluateExampleWith action (modifyIORef ref succ) `shouldReturn` H.Success- readIORef ref `shouldReturn` 2-- context "when used with `pending`" $ do- it "returns Pending" $ do- evaluateExample (H.pending) `shouldReturn` H.Pending Nothing-- context "when used with `pendingWith`" $ do- it "includes the optional reason" $ do- evaluateExample (H.pendingWith "foo") `shouldReturn` H.Pending (Just "foo")-- context "for Property" $ do- it "returns Success if property holds" $ do- evaluateExample (property $ \n -> n == (n :: Int)) `shouldReturn` H.Success-- it "returns Fail if property does not hold" $ do- H.Fail _ <- evaluateExample $ property $ \n -> n /= (n :: Int)- return ()-- it "shows what falsified it" $ do- H.Fail r <- evaluateExample $ property $ \x y -> x + y == (x * y :: Int)- r `shouldBe` intercalate "\n" [- "Falsifiable (after 1 test and 2 shrinks): "- , "0"- , "1"- ]-- it "runs provided action around each single check of the property" $ do- ref <- newIORef (0 :: Int)- let action :: IO () -> IO ()- action e = do- n <- readIORef ref- e- readIORef ref `shouldReturn` succ n- modifyIORef ref succ- H.Success <- evaluateExampleWith action (property $ modifyIORef ref succ)- readIORef ref `shouldReturn` 200-- context "when used with shouldBe" $ do- it "shows what falsified it" $ do- H.Fail r <- evaluateExample $ property $ \x y -> x + y `shouldBe` (x * y :: Int)- r `shouldBe` intercalate "\n" [- "Falsifiable (after 1 test and 2 shrinks): "- , "expected: 0"- , " but got: 1"- , "0"- , "1"- ]-- it "propagates UserInterrupt" $ do- let p = property (throwIO UserInterrupt :: Expectation)- evaluateExample p `shouldThrow` (== UserInterrupt)-- it "propagates exceptions" $ do- pendingWith "this probably needs a patch to QuickCheck"- -- evaluateExample (property $ (error "foobar" :: Int -> Bool)) `shouldThrow` errorCall "foobar"-- context "when used with `pending`" $ do- it "returns Pending" $ do- evaluateExample (property H.pending) `shouldReturn` H.Pending Nothing-- context "when used with `pendingWith`" $ do- it "includes the optional reason" $ do- evaluateExample (property $ H.pendingWith "foo") `shouldReturn` H.Pending (Just "foo")-- describe "Expectation" $ do- context "as a QuickCheck property" $ do- it "can be quantified" $ do- e <- newMock- silence . H.hspec $ do- H.it "some behavior" $ property $ \xs -> do- mockAction e- (reverse . reverse) xs `shouldBe` (xs :: [Int])- mockCounter e `shouldReturn` 100-- it "can be used with expectations/HUnit assertions" $ do- silence . H.hspecResult $ do- H.describe "readIO" $ do- H.it "is inverse to show" $ property $ \x -> do- (readIO . show) x `shouldReturn` (x :: Int)- `shouldReturn` H.Summary 1 0
− test/Test/Hspec/FailureReportSpec.hs
@@ -1,39 +0,0 @@-module Test.Hspec.FailureReportSpec (main, spec) where--import Helper--import System.IO-import Test.Hspec.FailureReport-import GHC.Paths (ghc)-import System.Process-import System.Exit--main :: IO ()-main = hspec spec--spec :: Spec-spec = do- describe "writeFailureReport" $ do- it "prints a warning on unexpected exceptions" $ do- r <- hCapture_ [stderr] $ writeFailureReport (error "some error")- r `shouldBe` "WARNING: Could not write environment variable HSPEC_FAILURES (some error)\n"-- -- GHCi needs to keep the environment on :reload, so that we can store- -- failures there. Otherwise --rerun would not be very useful. So we add a- -- test for that.- describe "GHCi" $ do- it "keeps environment variables on :reload" $ do- let flags = ["-v0", "--interactive", "-ignore-dot-ghci"]- (Just hIn, Just hOut, Nothing, processHandle) <- createProcess $ (proc ghc flags) {- std_in = CreatePipe- , std_out = CreatePipe- }- hPutStrLn hIn "import System.SetEnv"- hPutStrLn hIn "setEnv \"FOO\" \"bar\""- hPutStrLn hIn ":reload"- hPutStrLn hIn "import System.Environment"- hPutStrLn hIn "getEnv \"FOO\""- hClose hIn- r <- hGetContents hOut- length r `seq` r `shouldBe` "\"bar\"\n"- waitForProcess processHandle `shouldReturn` ExitSuccess
− test/Test/Hspec/FormattersSpec.hs
@@ -1,220 +0,0 @@-{-# LANGUAGE CPP #-}-module Test.Hspec.FormattersSpec (main, spec) where--import Helper--import qualified Test.Hspec as H-import qualified Test.Hspec.Core as H (Result(..))-import qualified Test.Hspec.Runner as H-import qualified Test.Hspec.Formatters as H--#ifndef mingw32_HOST_OS-import System.Console.ANSI-#endif--main :: IO ()-main = hspec spec--testSpec :: H.Spec-testSpec = do- H.describe "Example" $ do- H.it "success" (H.Success)- H.it "fail 1" (H.Fail "fail message")- H.it "pending" (H.pendingWith "pending message")- H.it "fail 2" (H.Fail "")- H.it "exceptions" (undefined :: H.Result)- H.it "fail 3" (H.Fail "")--spec :: Spec-spec = do- describe "silent" $ do- let runSpec = fmap fst . capture . H.hspecWith H.defaultConfig {H.configFormatter = H.silent}- it "produces no output" $ do- runSpec testSpec `shouldReturn` ""-- describe "failed_examples" $ do- failed_examplesSpec H.failed_examples-- describe "progress" $ do- let runSpec = captureLines . H.hspecWith H.defaultConfig {H.configFormatter = H.progress}-- it "produces '..F...FF.F' style output" $ do- r <- runSpec testSpec- head r `shouldBe` ".F.FFF"-- context "same as failed_examples" $ do- failed_examplesSpec H.progress-- describe "specdoc" $ do- let runSpec = captureLines . H.hspecWith H.defaultConfig {H.configFormatter = H.specdoc}-- it "displays a header for each thing being described" $ do- _:x:_ <- runSpec testSpec- x `shouldBe` "Example"-- it "displays one row for each behavior" $ do- r <- runSpec $ do- H.describe "List as a Monoid" $ do- H.describe "mappend" $ do- H.it "is associative" True- H.describe "mempty" $ do- H.it "is a left identity" True- H.it "is a right identity" True- H.describe "Maybe as a Monoid" $ do- H.describe "mappend" $ do- H.it "is associative" True- H.describe "mempty" $ do- H.it "is a left identity" True- H.it "is a right identity" True- normalizeSummary r `shouldBe` [- ""- , "List as a Monoid"- , " mappend"- , " - is associative"- , ""- , " mempty"- , " - is a left identity"- , " - is a right identity"- , ""- , "Maybe as a Monoid"- , " mappend"- , " - is associative"- , ""- , " mempty"- , " - is a left identity"- , " - is a right identity"- , ""- , "Finished in 0.0000 seconds"- , "6 examples, 0 failures"- ]-- it "prints an empty line before each group" $ do- r <- runSpec $ do- H.describe "foo" $ do- H.it "example 1" True- H.it "example 2" True- H.describe "bar" $ do- H.it "example 3" True- H.it "example 4" True- normalizeSummary r `shouldBe` [- ""- , "foo"- , " - example 1"- , " - example 2"- , ""- , " bar"- , " - example 3"- , " - example 4"- , ""- , "Finished in 0.0000 seconds"- , "4 examples, 0 failures"- ]-- it "prints an empty line after each group" $ do- r <- runSpec $ do- H.describe "foo" $ do- H.describe "bar" $ do- H.it "example 1" True- H.it "example 2" True- H.it "example 3" True- H.it "example 4" True- normalizeSummary r `shouldBe` [- ""- , "foo"- , " bar"- , " - example 1"- , " - example 2"- , ""- , " - example 3"- , " - example 4"- , ""- , "Finished in 0.0000 seconds"- , "4 examples, 0 failures"- ]-- it "outputs an empty line at the beginning (even for non-nested specs)" $ do- r <- runSpec $ do- H.it "example 1" True- H.it "example 2" True- normalizeSummary r `shouldBe` [- ""- , "- example 1"- , "- example 2"- , ""- , "Finished in 0.0000 seconds"- , "2 examples, 0 failures"- ]-- it "displays a row for each successfull, failed, or pending example" $ do- r <- runSpec testSpec- r `shouldSatisfy` any (== " - fail 1 FAILED [1]")- r `shouldSatisfy` any (== " - success")-- it "displays a '#' with an additional message for pending examples" $ do- r <- runSpec testSpec- r `shouldSatisfy` any (== " # PENDING: pending message")-- context "same as failed_examples" $ do- failed_examplesSpec H.progress--failed_examplesSpec :: H.Formatter -> Spec-failed_examplesSpec formatter = do- let runSpec = captureLines . H.hspecWith H.defaultConfig {H.configFormatter = formatter}-- it "summarizes the time it takes to finish" $ do- r <- runSpec (return ())- normalizeSummary r `shouldSatisfy` any (== "Finished in 0.0000 seconds")-- context "displays a detailed list of failures" $ do- it "prints all requirements that are not met" $ do- r <- runSpec testSpec- r `shouldSatisfy` any (== "1) Example fail 1")-- it "prints the exception type for requirements that fail due to an uncaught exception" $ do- r <- runSpec $ do- H.it "foobar" (undefined :: Bool)- r `shouldContain` [- "1) foobar"- , "uncaught exception: ErrorCall (Prelude.undefined)"- ]-- it "prints all descriptions when a nested requirement fails" $ do- r <- runSpec $- H.describe "foo" $ do- H.describe "bar" $ do- H.it "baz" False- r `shouldSatisfy` any (== "1) foo.bar baz")-- it "summarizes the number of examples and failures" $ do- r <- runSpec testSpec- r `shouldSatisfy` any (== "6 examples, 4 failures, 1 pending")-- -- Windows has no support for ANSI escape codes. The Console API is used for- -- colorized output, hence the following tests do not work on Windows.-#ifndef mingw32_HOST_OS- it "shows summary in green if there are no failures" $ do- r <- captureLines $ H.hspecWith H.defaultConfig {H.configColorMode = H.ColorAlways} $ do- H.it "foobar" True- r `shouldSatisfy` any (== (green ++ "1 example, 0 failures" ++ reset))-- it "shows summary in yellow if there are pending examples" $ do- r <- captureLines $ H.hspecWith H.defaultConfig {H.configColorMode = H.ColorAlways} $ do- H.it "foobar" H.pending- r `shouldSatisfy` any (== (yellow ++ "1 example, 0 failures, 1 pending" ++ reset))-- it "shows summary in red if there are failures" $ do- r <- captureLines $ H.hspecWith H.defaultConfig {H.configColorMode = H.ColorAlways} $ do- H.it "foobar" False- r `shouldSatisfy` any (== (red ++ "1 example, 1 failure" ++ reset))-- it "shows summary in red if there are both failures and pending examples" $ do- r <- captureLines $ H.hspecWith H.defaultConfig {H.configColorMode = H.ColorAlways} $ do- H.it "foo" False- H.it "bar" H.pending- r `shouldSatisfy` any (== (red ++ "2 examples, 1 failure, 1 pending" ++ reset))- where- green = setSGRCode [SetColor Foreground Dull Green]- yellow = setSGRCode [SetColor Foreground Dull Yellow]- red = setSGRCode [SetColor Foreground Dull Red]- reset = setSGRCode [Reset]-#endif
− test/Test/Hspec/HUnitSpec.hs
@@ -1,79 +0,0 @@-module Test.Hspec.HUnitSpec (main, spec) where--import Helper--import qualified Test.Hspec as H-import qualified Test.Hspec.Runner as H-import Test.Hspec.Core.Type (SpecTree(..), Item(..), runSpecM)-import Test.Hspec.HUnit-import Test.HUnit--main :: IO ()-main = hspec spec---- SpecTree does not have an Eq nor a Show instance, hence we map it to `Tree`.-data Tree = Group String [Tree] | Example String- deriving (Eq, Show)--shouldYield :: Test -> [Tree] -> Expectation-a `shouldYield` b = (convert . runSpecM . fromHUnitTest) a `shouldBe` b- where- convert :: [SpecTree] -> [Tree]- convert = map go- where- go :: SpecTree -> Tree- go x = case x of- SpecGroup s xs -> Group s (map go xs)- SpecItem item -> Example (itemRequirement item)--spec :: Spec-spec = do- describe "fromHUnitTest" $ do- let e = TestCase $ pure ()-- it "works for a TestCase" $ do- e `shouldYield` [Example "<unlabeled>"]-- it "works for a labeled TestCase" $ do- TestLabel "foo" e- `shouldYield` [Example "foo"]-- it "works for a TestCase with nested labels" $ do- (TestLabel "foo" . TestLabel "bar") e- `shouldYield` [Group "foo" [Example "bar"]]-- it "works for a flat TestList" $ do- TestList [e, e, e]- `shouldYield` [Example "<unlabeled>", Example "<unlabeled>", Example "<unlabeled>"]-- it "works for a nested TestList" $ do- (TestLabel "foo" . TestLabel "bar" . TestList) [TestLabel "one" e, TestLabel "two" e, TestLabel "three" e]- `shouldYield` [Group "foo" [Group "bar" [Example "one", Example "two", Example "three"]]]-- describe "HUnit TestCase as an example (deprecated!)" $ do- it "is specified with the HUnit `TestCase` data constructor" $ TestCase $ do- silence . H.hspecResult $ do- H.it "some behavior" (TestCase $ "foo" @?= "bar")- H.it "some behavior" (TestCase $ "foo" @?= "foo")- `shouldReturn` H.Summary 2 1-- it "is the assumed example for IO() actions" $ do- silence . H.hspecResult $ do- H.it "some behavior" ("foo" @?= "bar")- H.it "some behavior" ("foo" @?= "foo")- `shouldReturn` H.Summary 2 1-- it "will show the failed assertion text if available (e.g. assertBool)" $ do- let assertionText = "some assertion text"- r <- captureLines . H.hspecResult $ do- H.describe "foo" $ do- H.it "bar" (assertFailure assertionText)- r `shouldSatisfy` any (== assertionText)-- it "will show the failed assertion expected and actual values if available (e.g. assertEqual)" $ do- r <- captureLines . H.hspecResult $ do- H.describe "foo" $ do- H.it "bar" (assertEqual "trivial" (1::Int) 2)- assertBool "should find assertion text" $ any (=="trivial") r- assertBool "should find 'expected: 1'" $ any (=="expected: 1") r- assertBool "should find ' but got: 2'" $ any (==" but got: 2") r
− test/Test/Hspec/OptionsSpec.hs
@@ -1,44 +0,0 @@-module Test.Hspec.OptionsSpec (main, spec) where--import Helper-import System.Exit--import Test.Hspec.Options hiding (parseOptions)-import qualified Test.Hspec.Options as Options--main :: IO ()-main = hspec spec--fromLeft :: Either a b -> a-fromLeft (Left a) = a-fromLeft _ = error "fromLeft: No left value!"--spec :: Spec-spec = do- describe "parseOptions" $ do-- let parseOptions = Options.parseOptions defaultOptions "my-spec"-- it "sets optionsColorMode to ColorAuto" $ do- optionsColorMode <$> parseOptions [] `shouldBe` Right ColorAuto-- context "with --no-color" $ do- it "sets optionsColorMode to ColorNever" $ do- optionsColorMode <$> parseOptions ["--no-color"] `shouldBe` Right ColorNever-- context "with --color" $ do- it "sets optionsColorMode to ColorAlways" $ do- optionsColorMode <$> parseOptions ["--color"] `shouldBe` Right ColorAlways-- context "with --out" $ do- it "sets optionsOutputFile" $ do- optionsOutputFile <$> parseOptions ["--out", "foo"] `shouldBe` Right (Just "foo")-- context "with --qc-max-success" $ do- context "when given an invalid argument" $ do- it "returns an error message" $ do- fromLeft (parseOptions ["--qc-max-success", "foo"]) `shouldBe` (ExitFailure 1, "my-spec: invalid argument `foo' for `--qc-max-success'\nTry `my-spec --help' for more information.\n")-- context "with --depth" $ do- it "sets depth parameter for SmallCheck" $ do- optionsDepth <$> parseOptions ["--depth", "23"] `shouldBe` Right (Just 23)
− test/Test/Hspec/QuickCheckSpec.hs
@@ -1,19 +0,0 @@-module Test.Hspec.QuickCheckSpec (main, spec) where--import Helper--import qualified Test.Hspec as H-import qualified Test.Hspec.Runner as H-import qualified Test.Hspec.QuickCheck as H--main :: IO ()-main = hspec spec--spec :: Spec-spec = do- describe "prop" $ do- it "is a shortcut to use properties as examples" $ do- silence . H.hspecResult $ do- H.describe "read" $ do- H.prop "is inverse to show" $ \x -> (read . show) x == (x :: Int)- `shouldReturn` H.Summary 1 0
− test/Test/Hspec/RunnerSpec.hs
@@ -1,393 +0,0 @@-module Test.Hspec.RunnerSpec (main, spec) where--import Helper-import System.IO (stderr)-import Control.Monad-import System.Environment (withArgs, withProgName, getArgs)-import System.Exit-import qualified Control.Exception as E-import Mock-import System.SetEnv-import Test.Hspec.Compat--import Test.Hspec.FailureReport (FailureReport(..))-import qualified Test.Hspec as H-import qualified Test.Hspec.Runner as H-import qualified Test.Hspec.Core as H (Result(..))-import qualified Test.Hspec.Formatters as H (silent)--import qualified Test.QuickCheck as QC--main :: IO ()-main = hspec spec--quickCheckOptions :: [([Char], Args -> Int)]-quickCheckOptions = [("--qc-max-success", QC.maxSuccess), ("--qc-max-size", QC.maxSize), ("--qc-max-discard", QC.maxDiscardRatio)]--spec :: Spec-spec = do- describe "hspec" $ do- it "runs a spec" $ do- silence . H.hspec $ do- H.it "foobar" True- `shouldReturn` ()-- it "exits with exitFailure if not all examples pass" $ do- silence . H.hspec $ do- H.it "foobar" False- `shouldThrow` (== ExitFailure 1)-- it "allows output to stdout" $ do- r <- captureLines . H.hspec $ do- H.it "foobar" $ do- putStrLn "baz"- r `shouldSatisfy` elem "baz"-- it "prints an error message on unrecognized command-line options" $ do- withProgName "myspec" . withArgs ["--foo"] $ do- hSilence [stderr] (H.hspec $ pure ()) `shouldThrow` (== ExitFailure 1)- fst `fmap` hCapture [stderr] (ignoreExitCode (H.hspec $ pure ())) `shouldReturn` unlines [- "myspec: unrecognized option `--foo'"- , "Try `myspec --help' for more information."- ]-- it "stores a failure report in the environment" $ do- silence . ignoreExitCode . withArgs ["--seed", "23"] . H.hspec $ do- H.describe "foo" $ do- H.describe "bar" $ do- H.it "example 1" True- H.it "example 2" False- H.describe "baz" $ do- H.it "example 3" False- lookupEnv "HSPEC_FAILURES" `shouldReturn` (Just . show) FailureReport {- failureReportSeed = 23- , failureReportMaxSuccess = 100- , failureReportMaxSize = 100- , failureReportMaxDiscardRatio = 10- , failureReportPaths = [- (["foo", "bar"], "example 2")- , (["baz"], "example 3")- ]- }-- describe "with --rerun" $ do- let runSpec = (captureLines . ignoreExitCode . H.hspec) $ do- H.it "example 1" True- H.it "example 2" False- H.it "example 3" False- H.it "example 4" True- H.it "example 5" False-- it "reruns examples that previously failed" $ do- r0 <- runSpec- r0 `shouldSatisfy` elem "5 examples, 3 failures"-- r1 <- withArgs ["--rerun"] runSpec- r1 `shouldSatisfy` elem "3 examples, 3 failures"-- it "reuses the same seed" $ do- let runSpec_ = (captureLines . ignoreExitCode . H.hspec) $ do- H.it "foo" $ property $ (/= (26 :: Integer))-- r0 <- withArgs ["--seed", "2413421499272008081"] runSpec_- r0 `shouldContain` [- "Falsifiable (after 66 tests): "- , "26"- ]-- r1 <- withArgs ["-r"] runSpec_- r1 `shouldContain` [- "Falsifiable (after 66 tests): "- , "26"- ]-- forM_ quickCheckOptions $ \(flag, accessor) -> do- it ("reuses same " ++ flag) $ do- [flag, "23"] `shouldUseArgs` ((== 23) . accessor)- ["--rerun"] `shouldUseArgs` ((== 23) . accessor)-- context "when there is no failure report in the environment" $ do- it "runs everything" $ do- unsetEnv "HSPEC_FAILURES"- r <- hSilence [stderr] $ withArgs ["-r"] runSpec- r `shouldSatisfy` elem "5 examples, 3 failures"-- it "prints a warning to stderr" $ do- unsetEnv "HSPEC_FAILURES"- r <- hCapture_ [stderr] $ withArgs ["-r"] runSpec- r `shouldBe` "WARNING: Could not read environment variable HSPEC_FAILURES; `--rerun' is ignored!\n"-- context "when parsing of failure report fails" $ do- it "runs everything" $ do- setEnv "HSPEC_FAILURES" "some invalid report"- r <- hSilence [stderr] $ withArgs ["-r"] runSpec- r `shouldSatisfy` elem "5 examples, 3 failures"-- it "prints a warning to stderr" $ do- setEnv "HSPEC_FAILURES" "some invalid report"- r <- hCapture_ [stderr] $ withArgs ["-r"] runSpec- r `shouldBe` "WARNING: Could not read environment variable HSPEC_FAILURES; `--rerun' is ignored!\n"--- it "does not leak command-line flags to examples" $ do- silence . withArgs ["--verbose"] $ do- H.hspec $ do- H.it "foobar" $ do- getArgs `shouldReturn` []- `shouldReturn` ()-- context "when interrupted with ctrl-c" $ do- it "prints summary immediately" $ do- r <- captureLines . ignoreUserInterrupt . withArgs ["--seed", "23"] . H.hspec $ do- H.it "foo" False- H.it "bar" $ do- E.throwIO E.UserInterrupt :: IO ()- H.it "baz" True- normalizeSummary r `shouldBe` [- ""- , "- foo FAILED [1]"- , ""- , "1) foo"- , ""- , "Randomized with seed 23"- , ""- ]-- it "throws UserInterrupt" $ do- silence . H.hspec $ do- H.it "foo" $ do- E.throwIO E.UserInterrupt :: IO ()- `shouldThrow` (== E.UserInterrupt)-- context "with --help" $ do- let printHelp = withProgName "spec" . withArgs ["--help"] . H.hspec $ pure ()- it "prints help" $ do- r <- (captureLines . ignoreExitCode) printHelp- r `shouldStartWith` ["Usage: spec [OPTION]..."]- silence printHelp `shouldThrow` (== ExitSuccess)-- it "constrains lines to 80 characters" $ do- r <- (captureLines . ignoreExitCode) printHelp- r `shouldSatisfy` all ((<= 80) . length)- r `shouldSatisfy` any ((78 <=) . length)-- context "with --dry-run" $ do- it "produces a report" $ do- r <- captureLines . withArgs ["--dry-run"] . H.hspec $ do- H.it "foo" True- H.it "bar" True- normalizeSummary r `shouldBe` [- ""- , "- foo"- , "- bar"- , ""- , "Finished in 0.0000 seconds"- , "2 examples, 0 failures"- ]-- it "does not verify anything" $ do- e <- newMock- _ <- captureLines . withArgs ["--dry-run"] . H.hspec $ do- H.it "foo" (mockAction e)- H.it "bar" False- mockCounter e `shouldReturn` 0-- context "with --fail-fast" $ do- it "stops after first failure" $ do- r <- captureLines . ignoreExitCode . withArgs ["--fail-fast", "--seed", "23"] . H.hspec $ do- H.it "foo" True- H.it "bar" False- H.it "baz" False- normalizeSummary r `shouldBe` [- ""- , "- foo"- , "- bar FAILED [1]"- , ""- , "1) bar"- , ""- , "Randomized with seed 23"- , ""- , "Finished in 0.0000 seconds"- , "2 examples, 1 failure"- ]-- it "works for nested specs" $ do- r <- captureLines . ignoreExitCode . withArgs ["--fail-fast", "--seed", "23"] . H.hspec $ do- H.describe "foo" $ do- H.it "bar" False- H.it "baz" True- normalizeSummary r `shouldBe` [- ""- , "foo"- , " - bar FAILED [1]"- , ""- , "1) foo bar"- , ""- , "Randomized with seed 23"- , ""- , "Finished in 0.0000 seconds"- , "1 example, 1 failure"- ]-- context "with --match" $ do- it "only runs examples that match a given pattern" $ do- e1 <- newMock- e2 <- newMock- e3 <- newMock- silence . withArgs ["-m", "/bar/example"] . H.hspec $ do- H.describe "foo" $ do- H.describe "bar" $ do- H.it "example 1" $ mockAction e1- H.it "example 2" $ mockAction e2- H.describe "baz" $ do- H.it "example 3" $ mockAction e3- (,,) <$> mockCounter e1 <*> mockCounter e2 <*> mockCounter e3 `shouldReturn` (1, 1, 0)-- it "can be given multiple times" $ do- e1 <- newMock- e2 <- newMock- e3 <- newMock- silence . withArgs ["-m", "foo", "-m", "baz"] . H.hspec $ do- H.describe "foo" $ do- H.it "example 1" $ mockAction e1- H.describe "bar" $ do- H.it "example 2" $ mockAction e2- H.describe "baz" $ do- H.it "example 3" $ mockAction e3- (,,) <$> mockCounter e1 <*> mockCounter e2 <*> mockCounter e3 `shouldReturn` (1, 0, 1)-- context "with --format" $ do- it "uses specified formatter" $ do- r <- capture_ . ignoreExitCode . withArgs ["--format", "progress"] . H.hspec $ do- H.it "foo" True- H.it "bar" True- H.it "baz" False- H.it "qux" True- r `shouldContain` "..F."-- context "when given an invalid argument" $ do- it "prints an error message to stderr" $ do- r <- hCapture_ [stderr] . ignoreExitCode . withArgs ["--format", "foo"] . H.hspec $ do- H.it "foo" True- r `shouldContain` "invalid argument `foo' for `--format'"-- context "with --qc-max-success" $ do- it "tries QuickCheck properties specified number of times" $ do- m <- newMock- silence . withArgs ["--qc-max-success", "23"] . H.hspec $ do- H.it "foo" $ property $ do- mockAction m- mockCounter m `shouldReturn` 23-- context "when run with --rerun" $ do- it "takes precedence" $ do- ["--qc-max-success", "23"] `shouldUseArgs` ((== 23) . QC.maxSuccess)- ["--rerun", "--qc-max-success", "42"] `shouldUseArgs` ((== 42) . QC.maxSuccess)-- context "with --qc-max-size" $ do- it "passes specified size to QuickCheck properties" $ do- ["--qc-max-size", "23"] `shouldUseArgs` ((== 23) . QC.maxSize)-- context "with --qc-max-discard" $ do- it "uses specified discard ratio to QuickCheck properties" $ do- ["--qc-max-discard", "23"] `shouldUseArgs` ((== 23) . QC.maxDiscardRatio)-- context "with --seed" $ do- it "uses specified seed" $ do- r <- captureLines . ignoreExitCode . withArgs ["--seed", "2413421499272008081"] . H.hspec $ do- H.it "foo" $- property (/= (26 :: Integer))- r `shouldContain` [- "Falsifiable (after 66 tests): "- , "26"- ]-- context "when run with --rerun" $ do- it "takes precedence" $ do- let runSpec args = capture_ . ignoreExitCode . withArgs args . H.hspec $ do- H.it "foo" $- property $ \n -> ((17 + 31 * n) `mod` 50) /= (23 :: Integer)- r0 <- runSpec ["--seed", "23"]- r0 `shouldContain` "(after 88 tests)"-- r1 <- runSpec ["--seed", "42"]- r1 `shouldContain` "(after 48 tests)"-- r2 <- runSpec ["--rerun", "--seed", "23"]- r2 `shouldContain` "(after 88 tests)"-- context "when given an invalid argument" $ do- let run = withArgs ["--seed", "foo"] . H.hspec $ do- H.it "foo" True- it "prints an error message to stderr" $ do- r <- hCapture_ [stderr] (ignoreExitCode run)- r `shouldContain` "invalid argument `foo' for `--seed'"-- it "exits with exitFailure" $ do- hSilence [stderr] run `shouldThrow` (== ExitFailure 1)-- context "with --print-cpu-time" $ do- it "includes used CPU time in summary" $ do- r <- capture_ $ withArgs ["--print-cpu-time"] (H.hspec $ pure ())- (normalizeSummary . lines) r `shouldContain` ["Finished in 0.0000 seconds, used 0.0000 seconds of CPU time"]-- context "with --html" $ do- it "produces HTML output" $ do- r <- capture_ . withArgs ["--html"] . H.hspec $ do- H.it "foo" True- r `shouldContain` "</span>"-- it "marks successful examples with CSS class hspec-success" $ do- r <- capture_ . withArgs ["--html"] . H.hspec $ do- H.it "foo" True- r `shouldContain` "<span class=\"hspec-success\">- foo\n</span>"-- it "marks pending examples with CSS class hspec-pending" $ do- r <- capture_ . withArgs ["--html"] . H.hspec $ do- H.it "foo" H.pending- r `shouldContain` "<span class=\"hspec-pending\">- foo"-- it "marks failed examples with CSS class hspec-failure" $ do- r <- capture_ . ignoreExitCode . withArgs ["--html"] . H.hspec $ do- H.it "foo" False- r `shouldContain` "<span class=\"hspec-failure\">- foo"-- describe "hspecResult" $ do- it "returns a summary of the test run" $ do- silence . H.hspecResult $ do- H.it "foo" True- H.it "foo" False- H.it "foo" False- H.it "foo" True- H.it "foo" True- `shouldReturn` H.Summary 5 2-- it "treats uncaught exceptions as failure" $ do- silence . H.hspecResult $ do- H.it "foobar" (E.throwIO (E.ErrorCall "foobar") >> pure ())- `shouldReturn` H.Summary 1 1-- it "uses the specdoc formatter by default" $ do- _:r:_ <- captureLines . H.hspecResult $ do- H.describe "Foo.Bar" $ do- H.it "some example" True- r `shouldBe` "Foo.Bar"-- it "can use a custom formatter" $ do- r <- capture_ . H.hspecWith H.defaultConfig {H.configFormatter = H.silent} $ do- H.describe "Foo.Bar" $ do- H.it "some example" True- r `shouldBe` ""-- it "does not let escape error thunks from failure messages" $ do- r <- silence . H.hspecResult $ do- H.it "some example" (H.Fail $ "foobar" ++ undefined)- r `shouldBe` H.Summary 1 1-- it "runs specs in parallel" $ do- let n = 10- t = 0.01- dt = t * (fromIntegral n / 2)- r <- timeout dt . silence . H.hspecResult . H.parallel $ do- replicateM_ n (H.it "foo" $ sleep t)- r `shouldBe` Just (H.Summary n 0)
− test/Test/Hspec/TimerSpec.hs
@@ -1,29 +0,0 @@-module Test.Hspec.TimerSpec (main, spec) where--import Helper--import Test.Hspec.Timer--main :: IO ()-main = hspec spec--spec :: Spec-spec = do- describe "timer action returned by newTimer" $ do-- let dt = 0.01-- it "returns False" $ do- timer <- newTimer dt- timer `shouldReturn` False-- context "after specified time" $ do- it "returns True" $ do- timer <- newTimer dt- sleep dt- timer `shouldReturn` True- timer `shouldReturn` False- sleep dt- sleep dt- timer `shouldReturn` True- timer `shouldReturn` False
− test/Test/Hspec/UtilSpec.hs
@@ -1,108 +0,0 @@-{-# OPTIONS_GHC -fno-warn-orphans #-}-module Test.Hspec.UtilSpec (main, spec) where--import Helper-import Data.Int (Int32)-import System.Random (StdGen)-import qualified Control.Exception as E--import Test.Hspec.Util--main :: IO ()-main = hspec spec--spec :: Spec-spec = do- describe "pluralize" $ do- it "returns an amount and a word given an amount and word" $ do- pluralize 1 "thing" `shouldBe` "1 thing"-- it "returns a singular word given the number 1" $ do- pluralize 1 "thing" `shouldBe` "1 thing"-- it "returns a plural word given a number greater than 1" $ do- pluralize 2 "thing" `shouldBe` "2 things"-- it "returns a plural word given the number 0" $ do- pluralize 0 "thing" `shouldBe` "0 things"-- describe "lineBreaksAt" $ do- it "inserts line breaks at word boundaries" $ do- lineBreaksAt 20 "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod"- `shouldBe` [- "Lorem ipsum dolor"- , "sit amet,"- , "consectetur"- , "adipisicing elit,"- , "sed do eiusmod"- ]-- describe "safeTry" $ do- it "returns Right on success" $ do- Right e <- safeTry (return 23 :: IO Int)- e `shouldBe` 23-- it "returns Left on exception" $ do- Left e <- safeTry (E.throwIO E.DivideByZero :: IO Int)- show e `shouldBe` "divide by zero"-- it "evaluates result to weak head normal form" $ do- Left e <- safeTry (return undefined)- show e `shouldBe` "Prelude.undefined"-- it "re-throws AsyncException" $ do- safeTry (E.throwIO E.UserInterrupt :: IO Int) `shouldThrow` (== E.UserInterrupt)-- describe "filterPredicate" $ do- it "tries to match a pattern against a path" $ do- let p = filterPredicate "foo/bar/example 1"- p (["foo", "bar"], "example 1") `shouldBe` True- p (["foo", "bar"], "example 2") `shouldBe` False-- it "is ambiguous" $ do- let p = filterPredicate "foo/bar/baz"- p (["foo", "bar"], "baz") `shouldBe` True- p (["foo"], "bar/baz") `shouldBe` True-- it "succeeds on a partial match" $ do- let p = filterPredicate "bar/baz"- p (["foo", "bar", "baz"], "example 1") `shouldBe` True-- it "succeeds with a pattern that matches the message give in the failure list" $ do- let p = filterPredicate "ModuleA.ModuleB.foo does something"- p (["ModuleA", "ModuleB", "foo"], "does something") `shouldBe` True-- describe "formatRequirement" $ do- it "creates a sentence from a subject and a requirement" $ do- formatRequirement (["reverse"], "reverses a list") `shouldBe` "reverse reverses a list"-- it "creates a sentence from a subject and a requirement when the subject consits of multiple words" $ do- formatRequirement (["The reverse function"], "reverses a list") `shouldBe` "The reverse function reverses a list"-- it "returns the requirement if no subject is given" $ do- formatRequirement ([], "reverses a list") `shouldBe` "reverses a list"-- it "inserts context separated by commas" $ do- formatRequirement (["reverse", "when applied twice"], "reverses a list") `shouldBe` "reverse, when applied twice, reverses a list"-- it "joins components of a subject with a dot" $ do- formatRequirement (["Data", "List", "reverse"], "reverses a list") `shouldBe` "Data.List.reverse reverses a list"-- it "properly handles context after a subject that consists of several components" $ do- formatRequirement (["Data", "List", "reverse", "when applied twice"], "reverses a list") `shouldBe` "Data.List.reverse, when applied twice, reverses a list"-- describe "stdGenToInteger" $ do- it "is inverse to stdGenFromInteger" $ property $- \(NonNegative i) -> (stdGenToInteger . stdGenFromInteger) i `shouldBe` i-- describe "stdGenFromInteger" $ do- it "is inverse to stdGenToInteger" $ property $- \stdGen -> (stdGenFromInteger . stdGenToInteger) stdGen `shouldBe` stdGen--instance Eq StdGen where- a == b = show a == show b--instance Arbitrary StdGen where- arbitrary = do- (Positive a, Positive b) <- arbitrary- return $ read (show (a :: Int32) ++ " " ++ show (b :: Int32))
− test/Test/HspecSpec.hs
@@ -1,146 +0,0 @@-module Test.HspecSpec (main, spec) where--import Helper-import Mock-import Data.IORef-import Data.List (isPrefixOf)--import Test.Hspec.Core (SpecTree(..), Item(..), Result(..), runSpecM)-import qualified Test.Hspec as H-import qualified Test.Hspec.Runner as H (hspecResult)--main :: IO ()-main = hspec spec--spec :: Spec-spec = do- describe "pending" $ do- it "specifies a pending example" $ do- r <- runSpec $ do- H.it "foo" H.pending- r `shouldSatisfy` any (== " # PENDING: No reason given")-- describe "pendingWith" $ do- it "specifies a pending example with a reason for why it's pending" $ do- r <- runSpec $ do- H.it "foo" $ do- H.pendingWith "for some reason"- r `shouldSatisfy` any (== " # PENDING: for some reason")-- describe "describe" $ do- let testSpec = do- H.describe "some subject" $ do- H.it "foo" True- H.it "bar" True- H.it "baz" True- it "takes a description of what the behavior is for" $ do- r <- runSpec testSpec- r `shouldSatisfy` any (== "some subject")-- it "groups behaviors for what's being described" $ do- r <- filter (isPrefixOf " - ") `fmap` runSpec testSpec- length r `shouldBe` 3-- it "can be nested" $ do- let [SpecGroup foo [SpecGroup bar [SpecItem Item {itemRequirement = baz}]]] = runSpecM $ do- H.describe "foo" $ do- H.describe "bar" $ do- H.it "baz" True- (foo, bar, baz) `shouldBe` ("foo", "bar", "baz")-- context "when no description is given" $ do- it "uses a default description" $ do- let [SpecGroup d _] = runSpecM (H.describe "" (pure ()))- d `shouldBe` "(no description given)"-- describe "it" $ do- it "takes a description of a desired behavior" $ do- let [SpecItem item] = runSpecM (H.it "whatever" True)- itemRequirement item `shouldBe` "whatever"-- it "takes an example of that behavior" $ do- let [SpecItem item] = runSpecM (H.it "whatever" True)- itemExample item defaultParams id `shouldReturn` Success-- context "when no description is given" $ do- it "uses a default description" $ do- let [SpecItem item] = runSpecM (H.it "" True)- itemRequirement item `shouldBe` "(unspecified behavior)"-- describe "example" $ do- it "fixes the type of an expectation" $ do- r <- runSpec $ do- H.it "foo" $ H.example $ do- pure ()- r `shouldSatisfy` any (== "1 example, 0 failures")-- describe "parallel" $ do- it "marks examples for parallel execution" $ do- let [SpecItem item] = runSpecM . H.parallel $ H.it "whatever" True- itemIsParallelizable item `shouldBe` True-- it "is applied recursively" $ do- let [SpecGroup _ [SpecGroup _ [SpecItem item]]] = runSpecM . H.parallel $ do- H.describe "foo" $ do- H.describe "bar" $ do- H.it "baz" True- itemIsParallelizable item `shouldBe` True-- describe "before" $ do- it "runs an action before each spec item" $ do- mock <- newMock- silence $ H.hspec $ H.before (mockAction mock) $ do- H.it "foo" $ do- mockCounter mock `shouldReturn` 1- H.it "bar" $ do- mockCounter mock `shouldReturn` 2- mockCounter mock `shouldReturn` 2-- context "when used multiple times" $ do- it "is evaluated outside in" $ do- ref <- newIORef (0 :: Int)- let action1 = do- readIORef ref `shouldReturn` 0- modifyIORef ref succ- action2 = do- readIORef ref `shouldReturn` 1- modifyIORef ref succ- silence $ H.hspec $ H.before action1 $ H.before action2 $ do- H.it "foo" $ do- readIORef ref `shouldReturn` 2-- describe "after" $ do- it "runs an action after each spec item" $ do- mock <- newMock- silence $ H.hspec $ H.after (mockAction mock) $ do- H.it "foo" $ do- mockCounter mock `shouldReturn` 0- H.it "bar" $ do- mockCounter mock `shouldReturn` 1- mockCounter mock `shouldReturn` 2-- it "guarantees that action is run" $ do- mock <- newMock- silence . ignoreExitCode $ H.hspec $ H.after (mockAction mock) $ do- H.it "foo" $ do- ioError $ userError "foo" :: IO ()- mockCounter mock `shouldReturn` 1-- describe "around" $ do- it "wraps each spec item with an action" $ do- ref <- newIORef (0 :: Int)- let action :: IO () -> IO ()- action e = do- readIORef ref `shouldReturn` 0- writeIORef ref 1- e- readIORef ref `shouldReturn` 2- writeIORef ref 3- silence $ H.hspec $ H.around action $ do- H.it "foo" $ do- readIORef ref `shouldReturn` 1- writeIORef ref 2- readIORef ref `shouldReturn` 3- where- runSpec :: H.Spec -> IO [String]- runSpec = captureLines . H.hspecResult
− test/doctests.hs
@@ -1,6 +0,0 @@-module Main where--import Test.DocTest--main :: IO ()-main = doctest ["-isrc", "-optP-include", "-optPdist/build/autogen/cabal_macros.h", "src/Test/Hspec/Util.hs", "src/Test/Hspec/Formatters.hs"]
+ version.yaml view
@@ -0,0 +1,7 @@+version: &version 2.11.17+synopsis: A Testing Framework for Haskell+author: Simon Hengel <sol@typeful.net>+maintainer: Simon Hengel <sol@typeful.net>+category: Testing+stability: experimental+homepage: https://hspec.github.io/