hspec 1.4.5 → 2.11.17
raw patch · 56 files changed
Files
- CHANGES.markdown +812/−0
- LICENSE +18/−7
- example/Spec.hs +0/−16
- hspec-discover/example/Spec.hs +0/−1
- hspec-discover/integration-test/empty/Spec.hs +0/−1
- hspec-discover/src/Main.hs +0/−8
- hspec-discover/src/Run.hs +0/−173
- hspec-discover/test-data/empty-dir/Foo/Bar/Baz/.placeholder +0/−0
- hspec-discover/test-data/lhs-spec/FooSpec.lhs +0/−0
- hspec-discover/test-data/lhs-spec/Spec.hs +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-data/no-intermediate-specs/Foo/Bar/BazSpec.hs +0/−0
- hspec-discover/test-data/prefix-name/Foo/BazSpec.hs +0/−0
- hspec-discover/test-data/prefix-name/FooBar/BazSpec.hs +0/−0
- hspec-discover/test-data/prefix-name/FooBarSpec.hs +0/−0
- hspec-discover/test-data/prefix-name/FooSpec.hs +0/−0
- hspec-discover/test-data/several-specs/BarSpec.hs +0/−0
- hspec-discover/test-data/several-specs/BazSpec.hs +0/−0
- hspec-discover/test-data/several-specs/FooSpec.hs +0/−0
- hspec-discover/test-data/single-spec-nested/Foo/BarSpec.hs +0/−0
- hspec-discover/test-data/single-spec/FooSpec.hs +0/−0
- hspec-discover/test-data/single-spec/Spec.hs +0/−0
- hspec-discover/test/RunSpec.hs +0/−93
- hspec-discover/test/Spec.hs +0/−1
- hspec.cabal +39/−179
- src/Test/Hspec.hs +68/−100
- src/Test/Hspec/Compat.hs +0/−25
- src/Test/Hspec/Config.hs +0/−157
- src/Test/Hspec/Core.hs +0/−72
- src/Test/Hspec/Core/Type.hs +0/−95
- src/Test/Hspec/Discover.hs +35/−0
- src/Test/Hspec/FailureReport.hs +0/−26
- src/Test/Hspec/Formatters.hs +7/−203
- src/Test/Hspec/Formatters/Internal.hs +0/−260
- src/Test/Hspec/HUnit.hs +0/−39
- src/Test/Hspec/Monadic.hs +0/−54
- src/Test/Hspec/Pending.hs +0/−34
- src/Test/Hspec/QuickCheck.hs +46/−13
- src/Test/Hspec/Runner.hs +2/−152
- src/Test/Hspec/Util.hs +0/−96
- test/Mock.hs +0/−15
- test/Spec.hs +0/−1
- test/Test/Hspec/CompatSpec.hs +0/−23
- test/Test/Hspec/Core/TypeSpec.hs +0/−65
- test/Test/Hspec/FailureReportSpec.hs +0/−40
- test/Test/Hspec/FormattersSpec.hs +0/−225
- test/Test/Hspec/HUnitSpec.hs +0/−83
- test/Test/Hspec/QuickCheckSpec.hs +0/−19
- test/Test/Hspec/RunnerSpec.hs +0/−293
- test/Test/Hspec/UtilSpec.hs +0/−100
- test/Test/HspecSpec.hs +0/−64
- test/Util.hs +0/−27
- 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,10 +1,21 @@--Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:-+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> -Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.-Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.-The name of the author may not be used to endorse or promote products derived from this software without specific prior written permission.+Permission is hereby granted, free of charge, to any person obtaining a copy+of this software and associated documentation files (the "Software"), to deal+in the Software without restriction, including without limitation the rights+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell+copies of the Software, and to permit persons to whom the Software is+furnished to do so, subject to the following conditions: -THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.+The above copyright notice and this permission notice shall be included in+all copies or substantial portions of the Software. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN+THE SOFTWARE.
− 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/example/Spec.hs
@@ -1,1 +0,0 @@-{-# OPTIONS_GHC -F -pgmF hspec-discover #-}
− hspec-discover/integration-test/empty/Spec.hs
@@ -1,1 +0,0 @@-{-# OPTIONS_GHC -F -pgmF hspec-discover #-}
− 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,173 +0,0 @@-{-# LANGUAGE TypeSynonymInstances, FlexibleInstances, OverloadedStrings #-}-{-# OPTIONS_GHC -fno-warn-orphans #-}--- | A preprocessor that finds and combines specs.-module Run where-import Control.Monad-import Control.Applicative-import Data.List-import Data.Maybe-import Data.String-import Data.Function-import System.Environment-import System.Exit-import System.IO-import System.Directory-import System.FilePath hiding (combine)--instance IsString ShowS where- fromString = showString--run :: [String] -> IO ()-run args_ = case args_ of- src : _ : dst : args -> do- nested <- case args of- [] -> return False- ["--nested"] -> return True- _ -> exit- specs <- findSpecs src- writeFile dst (mkSpecModule src nested specs)- _ -> exit- where- exit = do- name <- getProgName- hPutStrLn stderr ("usage: " ++ name ++ " SRC CUR DST [--nested]")- exitFailure--mkSpecModule :: FilePath -> Bool -> [SpecNode] -> String-mkSpecModule src nested nodes =- ( "{-# LINE 1 " . shows src . " #-}"- . showString "module Main where\n"- . showString "import Test.Hspec\n"- . importList nodes- . showString "main :: IO ()\n"- . showString "main = hspec $ "- . format nodes- ) "\n"- where- format- | nested = formatSpecsNested- | otherwise = formatSpecs---- | Generate imports for a list of specs.-importList :: [SpecNode] -> ShowS-importList = go ""- where- go :: ShowS -> [SpecNode] -> ShowS- go current = foldr (.) "" . map (f current)- f current (SpecNode name inhabited children) = this . go (current . showString name . ".") children- where- this- | inhabited = "import qualified " . current . showString name . "Spec\n"- | otherwise = id---- | Combine a list of strings with (>>).-sequenceS :: [ShowS] -> ShowS-sequenceS = foldr (.) "" . intersperse " >> "---- | Convert a list of specs to code.-formatSpecs :: [SpecNode] -> ShowS-formatSpecs xs- | null xs = "return ()"- | otherwise = sequenceS (map formatSpec xs)---- | Convert a spec to code.-formatSpec :: SpecNode -> ShowS-formatSpec = sequenceS . go ""- where- go :: String -> SpecNode -> [ShowS]- go current (SpecNode name inhabited children) = addThis $ concatMap (go (current ++ name ++ ".")) children- where- addThis :: [ShowS] -> [ShowS]- addThis- | inhabited = ("describe " . shows (current ++ name) . " " . showString (current ++ name ++ "Spec.spec") :)- | otherwise = id---- | Convert a list of specs to code.------ Hierarchical modules are mapped to nested specs.-formatSpecsNested :: [SpecNode] -> ShowS-formatSpecsNested xs- | null xs = "return ()"- | otherwise = sequenceS (map formatSpecNested xs)---- | Convert a spec to code.------ Hierarchical modules are mapped to nested specs.-formatSpecNested :: SpecNode -> ShowS-formatSpecNested = go ""- where- go current (SpecNode name inhabited children) = "describe " . shows name . " (" . specs . ")"- where- specs :: ShowS- specs = (sequenceS . addThis . map (go (current . showString name . "."))) children- addThis- | inhabited = ((current . showString name . "Spec.spec") :)- | otherwise = id--data SpecNode = SpecNode String Bool [SpecNode]- deriving (Eq, Show)--specNodeName :: SpecNode -> String-specNodeName (SpecNode name _ _) = name--specNodeInhabited :: SpecNode -> Bool-specNodeInhabited (SpecNode _ inhabited _) = inhabited--specNodeChildren :: SpecNode -> [SpecNode]-specNodeChildren (SpecNode _ _ children) = children--getFilesAndDirectories :: FilePath -> IO ([FilePath], [FilePath])-getFilesAndDirectories dir = do- c <- filter (`notElem` ["..", "."]) <$> getDirectoryContents dir- dirs <- filterM (doesDirectoryExist . (dir </>)) c- files <- filterM (doesFileExist . (dir </>)) c- return (dirs, files)---- | Find specs relative to given source file.------ The source file itself is not considered.-findSpecs :: FilePath -> IO [SpecNode]-findSpecs src = do- let (dir, file) = splitFileName src- (dirs, files) <- getFilesAndDirectories dir- go dir (dirs, filter (/= file) files)- where- go :: FilePath -> ([FilePath], [FilePath]) -> IO [SpecNode]- go base (dirs, files) = do- nestedSpecs <- forM dirs $ \d -> do- let dir = base </> d- SpecNode d False <$> (getFilesAndDirectories dir >>= go dir)- (return . filterSpecs . combineSpecs) (specsFromFiles files ++ nestedSpecs)- where- specsFromFiles = catMaybes . map specFromFile- where- suffixes :: [String]- suffixes = ["Spec.hs","Spec.lhs"]-- specFromFile :: FilePath -> Maybe SpecNode- specFromFile file = msum $ map (specFromFile_ file) suffixes-- specFromFile_ :: FilePath -> String -> Maybe SpecNode- specFromFile_ file suffix- | suffix `isSuffixOf` file = Just $ SpecNode (dropEnd (length suffix) file) True []- | otherwise = Nothing-- dropEnd :: Int -> [a] -> [a]- dropEnd n = reverse . drop n . reverse-- -- remove empty leafs- filterSpecs :: [SpecNode] -> [SpecNode]- filterSpecs = filter (\x -> specNodeInhabited x || (not . null . specNodeChildren) x)-- -- sort specs, and merge nodes with the same name- combineSpecs :: [SpecNode] -> [SpecNode]- combineSpecs = foldr f [] . sortBy (compare `on` specNodeName)- where- f x@(SpecNode n1 _ _) (y@(SpecNode n2 _ _):acc) | n1 == n2 = x `combine` y : acc- f x acc = x : acc-- x `combine` y = SpecNode name inhabited children- where- name = specNodeName x- inhabited = specNodeInhabited x || specNodeInhabited y- children = specNodeChildren x ++ specNodeChildren y
− hspec-discover/test-data/empty-dir/Foo/Bar/Baz/.placeholder
− hspec-discover/test-data/lhs-spec/FooSpec.lhs
− hspec-discover/test-data/lhs-spec/Spec.hs
− 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-data/no-intermediate-specs/Foo/Bar/BazSpec.hs
− hspec-discover/test-data/prefix-name/Foo/BazSpec.hs
− hspec-discover/test-data/prefix-name/FooBar/BazSpec.hs
− hspec-discover/test-data/prefix-name/FooBarSpec.hs
− hspec-discover/test-data/prefix-name/FooSpec.hs
− hspec-discover/test-data/several-specs/BarSpec.hs
− hspec-discover/test-data/several-specs/BazSpec.hs
− hspec-discover/test-data/several-specs/FooSpec.hs
− hspec-discover/test-data/single-spec-nested/Foo/BarSpec.hs
− hspec-discover/test-data/single-spec/FooSpec.hs
− hspec-discover/test-data/single-spec/Spec.hs
− hspec-discover/test/RunSpec.hs
@@ -1,93 +0,0 @@-{-# LANGUAGE OverloadedStrings #-}-module RunSpec (main, spec) where--import Test.Hspec.Meta--import Run--main :: IO ()-main = hspec spec--spec :: Spec-spec = do- describe "findSpecs" $ do- context "when specs are not nested" $ do- it "finds a single spec" $ do- findSpecs "hspec-discover/test-data/single-spec/Spec.hs" `shouldReturn` [SpecNode "Foo" True []]-- it "finds several specs" $ do- findSpecs "hspec-discover/test-data/several-specs/Spec.hs" `shouldReturn` [SpecNode "Bar" True [], SpecNode "Baz" True [], SpecNode "Foo" True []]-- it "discovers .lhs files" $ do- findSpecs "hspec-discover/test-data/lhs-spec/Spec.hs" `shouldReturn` [SpecNode "Foo" True []]-- context "when specs are nested" $ do- it "finds a single spec" $ do- findSpecs "hspec-discover/test-data/single-spec-nested/Spec.hs" `shouldReturn` [SpecNode "Foo" False [SpecNode "Bar" True []]]-- it "properly groups nested specs" $ do- findSpecs "hspec-discover/test-data/nested-spec/Spec.hs" `shouldReturn` [SpecNode "Foo" True [SpecNode "Bar" True [SpecNode "Baz" True []]]]-- context "given a nested spec, without specs at the intermediate nodes" $ do- it "finds a single spec" $ do- findSpecs "hspec-discover/test-data/no-intermediate-specs/Spec.hs" `shouldReturn` [SpecNode "Foo" False [SpecNode "Bar" False [SpecNode "Baz" True []]]]-- context "given a nested specs, with specs at the intermediate nodes" $ do- context "with two top-level specs, where one spec name is a prefix of the other" $ do- it "properly sorts specs" $ do- findSpecs "hspec-discover/test-data/prefix-name/Spec.hs" `shouldReturn`- [SpecNode "Foo" True [SpecNode "Baz" True []], SpecNode "FooBar" True [SpecNode "Baz" True []]]-- context "when there are no specs" $ do- it "returns an empty list" $ do- findSpecs "hspec-discover/test-data/empty-dir/Spec.hs" `shouldReturn` []-- describe "formatSpec" $ do- it "generates code for a spec" $- formatSpec (SpecNode "Foo" True []) "" `shouldBe` "describe \"Foo\" FooSpec.spec"-- it "generates code for a nested spec" $- formatSpec (SpecNode "Foo" True [SpecNode "Bar" True [SpecNode "Baz" True []]]) "" `shouldBe`- "describe \"Foo\" FooSpec.spec >> describe \"Foo.Bar\" Foo.BarSpec.spec >> describe \"Foo.Bar.Baz\" Foo.Bar.BazSpec.spec"-- describe "formatSpecs" $ do- it "generates code for a list of specs" $ do- formatSpecs [SpecNode "Bar" True [], SpecNode "Baz" True [], SpecNode "Foo" True []] "" `shouldBe`- "describe \"Bar\" BarSpec.spec >> describe \"Baz\" BazSpec.spec >> describe \"Foo\" FooSpec.spec"-- it "generates code for an empty list" $ do- formatSpecs [] "" `shouldBe`- "return ()"-- describe "formatSpecNested" $ do- it "generates code for a spec" $- formatSpecNested (SpecNode "Foo" True []) "" `shouldBe` "describe \"Foo\" (FooSpec.spec)"-- it "generates code for a nested spec" $- formatSpecNested (SpecNode "Foo" True [SpecNode "Bar" True [SpecNode "Baz" True []]]) "" `shouldBe`- "describe \"Foo\" (FooSpec.spec >> describe \"Bar\" (Foo.BarSpec.spec >> describe \"Baz\" (Foo.Bar.BazSpec.spec)))"-- describe "formatSpecsNested" $ do- it "generates code for a list of specs" $ do- formatSpecsNested [SpecNode "Bar" True [], SpecNode "Baz" True [], SpecNode "Foo" True []] "" `shouldBe`- "describe \"Bar\" (BarSpec.spec) >> describe \"Baz\" (BazSpec.spec) >> describe \"Foo\" (FooSpec.spec)"-- it "generates code for an empty list" $ do- formatSpecsNested [] "" `shouldBe`- "return ()"-- describe "importList" $ do- it "generates imports for a spec" $ do- importList [SpecNode "Foo" True []] "" `shouldBe` "import qualified FooSpec\n"-- it "generates imports for a nested spec" $- importList [SpecNode "Foo" True [SpecNode "Bar" True [SpecNode "Baz" True []]]] "" `shouldBe`- "import qualified FooSpec\nimport qualified Foo.BarSpec\nimport qualified Foo.Bar.BazSpec\n"-- it "generates imports for a list of specs" $ do- importList [SpecNode "Bar" True [], SpecNode "Baz" True [], SpecNode "Foo" True []] "" `shouldBe`- "import qualified BarSpec\nimport qualified BazSpec\nimport qualified FooSpec\n"-- it "generates imports for a nested spec that has no specs at the intermediate nodes" $ do- importList [SpecNode "Foo" False [SpecNode "Bar" False [SpecNode "Baz" True []]]] "" `shouldBe`- "import qualified Foo.Bar.BazSpec\n"
− hspec-discover/test/Spec.hs
@@ -1,1 +0,0 @@-{-# OPTIONS_GHC -F -pgmF hspec-meta-discover #-}
hspec.cabal view
@@ -1,202 +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.4.5-license: BSD3+version: 2.11.17+license: MIT license-file: LICENSE-copyright: (c) 2011-2012 Trystan Spangler, (c) 2011-2012 Simon Hengel, (c) 2011 Greg Weber+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.com/-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.com/>.---- 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/single-spec/FooSpec.hs- hspec-discover/test-data/single-spec/Spec.hs- hspec-discover/test-data/single-spec-nested/Foo/BarSpec.hs- 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/lhs-spec/FooSpec.lhs- hspec-discover/test-data/lhs-spec/Spec.hs- hspec-discover/test-data/several-specs/BarSpec.hs- hspec-discover/test-data/several-specs/FooSpec.hs- hspec-discover/test-data/several-specs/BazSpec.hs- hspec-discover/test-data/empty-dir/Foo/Bar/Baz/.placeholder- hspec-discover/test-data/prefix-name/FooSpec.hs- hspec-discover/test-data/prefix-name/Foo/BazSpec.hs- hspec-discover/test-data/prefix-name/FooBarSpec.hs- hspec-discover/test-data/prefix-name/FooBar/BazSpec.hs- hspec-discover/test-data/no-intermediate-specs/Foo/Bar/BazSpec.hs+ 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.*- , setenv- , silently >= 1.1.1- , ansi-terminal >= 0.5- , time- , transformers >= 0.2.2.0 && < 0.4.0- , HUnit >= 1.2.5- , QuickCheck >= 2.4.0.1- , hspec-expectations == 0.3.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.Pending- Test.Hspec.Core.Type- Test.Hspec.Config- Test.Hspec.FailureReport- Test.Hspec.Formatters.Internal--test-suite spec- type:- exitcode-stdio-1.0- hs-source-dirs:- src, test- main-is:- Spec.hs- other-modules:- Mock- Util- Test.HspecSpec- Test.Hspec.CompatSpec- Test.Hspec.Core.TypeSpec- Test.Hspec.FailureReportSpec- Test.Hspec.FormattersSpec- Test.Hspec.HUnitSpec- Test.Hspec.QuickCheckSpec- Test.Hspec.RunnerSpec- Test.Hspec.UtilSpec- ghc-options:- -Wall -Werror- build-depends:- base == 4.*- , setenv- , silently >= 1.2.4- , ansi-terminal- , time- , transformers- , HUnit- , QuickCheck- , hspec-expectations-- , hspec-meta- , 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- 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- build-depends:- base == 4.*- , filepath- , directory- , hspec-meta--test-suite hspec-discover-example- buildable: False- type:- exitcode-stdio-1.0- ghc-options:- -Wall -Werror- hs-source-dirs:- hspec-discover/example- main-is:- Spec.hs- build-depends:- base == 4.*- , hspec- , QuickCheck--test-suite hspec-discover-integration-test-empty- buildable: False- type:- exitcode-stdio-1.0- ghc-options:- -Wall -Werror- hs-source-dirs:- hspec-discover/integration-test/empty- main-is:- Spec.hs- build-depends:- base == 4.*- , hspec+ Paths_hspec+ default-language: Haskell2010+ if impl(ghc)+ cpp-options: -DENABLE_SPEC_HOOK_ARGS
src/Test/Hspec.hs view
@@ -1,128 +1,96 @@ -- | -- Stability: stable ----- Hspec is a framework for /Behavior-Driven Development (BDD)/ in Haskell. BDD--- is an approach to software development that combines Test-Driven--- Development, Domain-Driven Design, and Acceptance Test-Driven Planning.--- Hspec helps you do the TDD part of that equation, focusing on the--- documentation and design aspects of TDD.+-- Hspec is a testing framework for Haskell. ----- Hspec (and the preceding intro) are based on the Ruby library RSpec. Much of--- what applies to RSpec also applies to Hspec. Hspec ties together--- /textual descriptions/ of behavior and /examples/ for that behavior. The--- examples serve as test cases for the specified behavior. Hspec's mechanism--- for examples is extensible. Support for QuickCheck properties and HUnit--- tests is included in the core package.+-- This is the library reference for Hspec.+-- The <https://hspec.github.io/ User's Manual> contains more in-depth+-- documentation. module Test.Hspec (---- * Introduction--- $intro- -- * Types Spec+, SpecWith , Example-, Pending+, 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+, around_+, aroundWith+, aroundAll+, aroundAll_+, aroundAllWith+, mapSubject+, ignoreSubject+ -- * Running a spec , hspec ) where -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.Pending-import qualified Test.Hspec.Core as Core --- $intro------ The three functions you'll use the most are 'hspec', 'describe', and 'it'.--- Here is an example of functions that format and unformat phone numbers and--- the specs for them.------ > import Test.Hspec--- > import Test.QuickCheck--- > import Test.HUnit--- >--- > main :: IO ()--- > main = hspec spec------ Since the specs are often used to tell you what to implement, it's best to--- start with undefined functions. Once we have some specs, then you can--- implement each behavior one at a time, ensuring that each behavior is met--- and there is no undocumented behavior.------ > unformatPhoneNumber :: String -> String--- > unformatPhoneNumber = undefined--- >--- > formatPhoneNumber :: String -> String--- > formatPhoneNumber = undefined------ The 'describe' function takes a list of behaviors and examples bound--- together with the 'it' function------ > spec :: Spec--- > spec = do--- > describe "unformatPhoneNumber" $ do------ A `Bool` can be used as an example.------ > it "removes dashes, spaces, and parenthesies" $--- > unformatPhoneNumber "(555) 555-1234" == "5555551234"--------- The 'pending' function marks a behavior as pending an example. The example--- doesn't count as failing.------ > it "handles non-US phone numbers" $--- > pending "need to look up how other cultures format phone numbers"------ An HUnit 'Test.HUnit.Lang.Assertion' can be used as an example.------ > it "converts letters to numbers" $ do--- > let expected = "6862377"--- > actual = unformatPhoneNumber "NUMBERS"--- > actual @?= expected--------- A QuickCheck 'Test.QuickCheck.Property' can be used as an example.------ > it "can add and remove formatting without changing the number" $ property $--- > forAll phoneNumber $ \n -> unformatPhoneNumber (formatPhoneNumber n) == n--- >--- > phoneNumber :: Gen String--- > phoneNumber = do--- > n <- elements [7,10,11,12,13,14,15]--- > vectorOf n (elements "0123456789")----- | 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.+-- | @example@ is a type restricted version of `id`. It can be used to get better+-- error messages on type mismatches. ----- A spec item consists of:+-- Compare e.g. ----- * a textual description of a desired behavior+-- > it "exposes some behavior" $ example $ do+-- > putStrLn ----- * an example for that behavior+-- with ----- > describe "absolute" $ do--- > it "returns a positive number when given a negative number" $--- > absolute (-1) == 1-it :: Example v => String -> v -> Spec-it label action = fromSpecList [Core.it label action]+-- > it "exposes some behavior" $ do+-- > putStrLn+example :: Expectation -> Expectation+example = id
− src/Test/Hspec/Compat.hs
@@ -1,25 +0,0 @@-{-# LANGUAGE CPP #-}-module Test.Hspec.Compat where--import Data.Typeable (Typeable, typeOf, typeRepTyCon)--#if MIN_VERSION_base(4,4,0)-import Data.Typeable.Internal (tyConModule, tyConName)-#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,157 +0,0 @@-module Test.Hspec.Config (- Config (..)-, ColorMode (..)-, defaultConfig-, getConfig-, configAddFilter-) where--import Control.Monad (unless)-import Control.Applicative-import System.IO-import System.Exit-import System.Environment-import System.Console.GetOpt-import qualified Test.QuickCheck as QC-import Test.Hspec.Formatters--import Test.Hspec.Util-import Test.Hspec.Core.Type (Params (..), defaultParams)---- for Monad (Either e) when base < 4.3-import Control.Monad.Trans.Error ()--data Config = Config {- configVerbose :: Bool-, configDryRun :: Bool-, configPrintCpuTime :: Bool-, configReRun :: 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)-, configParams :: Params-, configColorMode :: ColorMode-, configFormatter :: Formatter-, configHtmlOutput :: Bool-, configHandle :: Handle-}--data ColorMode = ColorAuto | ColorNever | ColorAlway--defaultConfig :: Config-defaultConfig = Config False False False False False Nothing defaultParams ColorAuto specdoc False stdout--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 Config--data NoConfig = Help | InvalidArgument String String---- | 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 p}- where- -- if there is already a predicate, we combine them with ||- p = maybe p1 (\p0 path -> p0 path || p1 path) mp- mp = configFilterPredicate c--setQC_MaxSuccess :: String -> Result -> Result-setQC_MaxSuccess n x = (mapParams $ \p -> p {paramsQuickCheckArgs = (paramsQuickCheckArgs p) {QC.maxSuccess = read n}}) <$> x- where- mapParams :: (Params -> Params) -> Config -> Config- mapParams f c = c {configParams = f (configParams c)}--addLineBreaks :: String -> [String]-addLineBreaks = lineBreaksAt 44--options :: [OptDescr (Result -> Result)]-options = [- Option [] ["help"] (NoArg (const $ Left Help)) (h "display this help and exit")- , Option "v" ["verbose"] (NoArg setVerbose) (h "do not suppress output to stdout when evaluating examples")- , Option "m" ["match"] (ReqArg setFilter "PATTERN") (h "only run examples that match given PATTERN")- , Option [] ["color"] (OptArg setColor "WHEN") (h "colorize the output; WHEN defaults to `always' or can be `never' or `auto'")- , Option "f" ["format"] (ReqArg setFormatter "FORMATTER") formatHelp- , Option "a" ["qc-max-success"] (ReqArg setQC_MaxSuccess "N") (h "maximum number of successful tests before a QuickCheck property succeeds")- , 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 [] ["fast-fail"] (NoArg setFastFail) (h "stop after first failure")- ]- where- h = unlines . addLineBreaks-- setFilter :: String -> Result -> Result- setFilter pattern x = configAddFilter (filterPredicate pattern) <$> x-- setVerbose x = x >>= \c -> return c {configVerbose = True}- setPrintCpuTime x = x >>= \c -> return c {configPrintCpuTime = True}- setDryRun x = x >>= \c -> return c {configDryRun = True}- setFastFail x = x >>= \c -> return c {configFastFail = True}-- setFormatter name x = x >>= \c -> case lookup name formatters of- Nothing -> Left (InvalidArgument "format" name)- Just f -> return c {configFormatter = f}-- setColor mValue x = x >>= \c -> parseColor mValue >>= \v -> return c {configColorMode = v}- where- parseColor s = case s of- Nothing -> return ColorAlway- Just "auto" -> return ColorAuto- Just "never" -> return ColorNever- Just "always" -> return ColorAlway- Just v -> Left (InvalidArgument "color" v)--undocumentedOptions :: [OptDescr (Result -> Result)]-undocumentedOptions = [- Option "r" ["re-run"] (NoArg setReRun) "only re-run examples that previously failed"-- -- for compatibility with test-framework- , Option "" ["maximum-generated-tests"] (ReqArg setQC_MaxSuccess "NUMBER") "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"- ]- where- setReRun :: Result -> Result- setReRun x = x >>= \c -> return c {configReRun = True}-- setHtml :: Result -> Result- setHtml x = x >>= \c -> return c {configHtmlOutput = True}--getConfig :: IO Config-getConfig = do- (opts, args, errors) <- getOpt Permute (options ++ undocumentedOptions) <$> getArgs-- unless (null errors)- (tryHelp $ head errors)-- unless (null args)- (tryHelp $ "unexpected argument `" ++ head args ++ "'\n")-- case foldl (flip id) (Right defaultConfig) opts of- Left Help -> do- name <- getProgName- putStr $ usageInfo ("Usage: " ++ name ++ " [OPTION]...\n\nOPTIONS") options- exitSuccess- Left (InvalidArgument flag value) -> do- tryHelp $ "invalid argument `" ++ value ++ "' for `--" ++ flag ++ "'\n"- Right config -> do- return config- where- tryHelp message = do- name <- getProgName- hPutStr stderr $ name ++ ": " ++ message ++ "Try `" ++ name ++ " --help' for more information.\n"- exitFailure
− src/Test/Hspec/Core.hs
@@ -1,72 +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 (..)-, Result (..)---- * A writer monad for constructing specs-, SpecM-, runSpecM-, fromSpecList---- * Internal representation of a spec tree-, SpecTree (..)-, describe-, it---- * Deprecated types and functions-, Spec-, Specs-, hspecB-, hspecX-, hHspec-, hspec-, Pending-, pending-) where--import Control.Applicative-import System.IO (Handle)--import Test.Hspec.Core.Type hiding (Spec)-import qualified Test.Hspec.Pending as Pending-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--{-# 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 = h}--{-# DEPRECATED Spec "use `SpecTree` instead" #-} -- since 1.4.0-type Spec = SpecTree--{-# DEPRECATED Specs "use `[SpecTree]` instead" #-} -- since 1.4.0-type Specs = [SpecTree]--{-# DEPRECATED pending "use `Test.Hspec.pending` instead" #-} -- since 1.4.0-pending :: String -> Pending-pending = Pending.pending--{-# DEPRECATED Pending "use `Test.Hspec.Pending` instead" #-} -- since 1.4.0-type Pending = Pending.Pending
− src/Test/Hspec/Core/Type.hs
@@ -1,95 +0,0 @@-{-# LANGUAGE TypeSynonymInstances, FlexibleInstances, GeneralizedNewtypeDeriving #-}-module Test.Hspec.Core.Type (- Spec-, SpecM (..)-, runSpecM-, fromSpecList-, SpecTree (..)-, Example (..)-, Result (..)--, Params (..)-, defaultParams--, describe-, it-) where--import qualified Control.Exception as E-import Control.Applicative-import Control.Monad (when)-import Control.Monad.Trans.Writer (Writer, execWriter, tell)--import Test.Hspec.Util-import Test.Hspec.Expectations-import Test.HUnit.Lang (HUnitFailure(..))-import qualified Test.QuickCheck as QC--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)--data Params = Params {- paramsQuickCheckArgs :: QC.Args-}--defaultParams :: Params-defaultParams = Params QC.stdArgs---- | Internal representation of a spec.-data SpecTree =- SpecGroup String [SpecTree]- | SpecItem String (Params -> IO Result)---- | The @describe@ function combines a list of specs into a larger spec.-describe :: String -> [SpecTree] -> SpecTree-describe = SpecGroup---- | Create a spec item.-it :: Example a => String -> a -> SpecTree-it s e = SpecItem s (`evaluateExample` e)---- | A type class for examples.-class Example a where- evaluateExample :: Params -> a -> IO Result--instance Example Bool where- evaluateExample _ b = if b then return Success else return (Fail "")--instance Example Expectation where- evaluateExample _ action = (action >> return Success) `E.catch` \(HUnitFailure err) -> return (Fail err)--instance Example Result where- evaluateExample _ r = return r--instance Example QC.Property where- evaluateExample c p = do- r <- QC.quickCheckWithResult (paramsQuickCheckArgs c) p- when (isUserInterrupt r) $ do- E.throwIO E.UserInterrupt-- return $- case r of- QC.Success {} -> Success- f@(QC.Failure {}) -> Fail (QC.output f)- QC.GaveUp {QC.numTests = n} -> Fail ("Gave up after " ++ quantify n "test" )- QC.NoExpectedFailure {} -> Fail ("No expected failure")- where- isUserInterrupt :: QC.Result -> Bool- isUserInterrupt r = case r of- QC.Failure {QC.reason = "Exception: 'user interrupt'"} -> True- _ -> False
+ 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,26 +0,0 @@-module Test.Hspec.FailureReport where--import System.IO-import System.SetEnv-import Test.Hspec.Config-import Test.Hspec.Util (safeEvaluate, readMaybe, getEnv)--writeFailureReport :: String -> IO ()-writeFailureReport x = do- -- on Windows this can throw an exception when the input is too large, hence- -- we use `safeEvaluate` here- r <- safeEvaluate (setEnv "HSPEC_FAILURES" x)- either onError return r- where- onError err = do- hPutStrLn stderr ("WARNING: Could not write environment variable HSPEC_FAILURES (" ++ show err ++ ")")--readFailureReport :: Config -> IO Config-readFailureReport c = do- mx <- getEnv "HSPEC_FAILURES"- case mx >>= readMaybe of- Nothing -> do- hPutStrLn stderr "WARNING: Could not read environment variable HSPEC_FAILURES; `--re-run' is ignored!"- return c- Just xs -> do- return $ configAddFilter (`elem` xs) c
src/Test/Hspec/Formatters.hs view
@@ -1,204 +1,8 @@--- |--- 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+{-# OPTIONS_GHC -fno-warn-deprecations #-} -- |--- 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--, getCPUTime-, getRealTime---- ** Appending to the gerenated report-, write-, writeLine-, newParagraph---- ** Dealing with colors-, withSuccessColor-, withPendingColor-, withFailColor---- ** Helpers-, formatException-) 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---- 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-- , getCPUTime- , getRealTime-- , write- , writeLine- , newParagraph-- , withSuccessColor- , withPendingColor- , withFailColor- )---silent :: Formatter-silent = Formatter {- headerFormatter = return ()-, exampleGroupStarted = \_ _ _ -> return ()-, exampleGroupDone = 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--, 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) ' '---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 ""- where- formatFailure :: (Int, FailureRecord) -> FormatM ()- formatFailure (n, FailureRecord path reason) = do- write (show n ++ ") ")- withFailColor $ do- write (formatRequirement path ++ " FAILED")- write $ case reason of- Right _ -> "\n"- Left _ -> " (uncaught exception)\n"- unless (null err) $ do- writeLine err- where- err = either 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 $ quantify total "example"- write (", " ++ quantify 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,260 +0,0 @@-{-# LANGUAGE GeneralizedNewtypeDeriving #-}-module Test.Hspec.Formatters.Internal (---- * Public API- Formatter (..)-, FormatM--, getSuccessCount-, getPendingCount-, getFailCount-, getTotalCount--, FailureRecord (..)-, getFailMessages--, getCPUTime-, getRealTime--, write-, writeLine-, newParagraph--, withSuccessColor-, withPendingColor-, withFailColor---- * Functions for internal use-, runFormatM-, liftIO-, 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 qualified Control.Monad.IO.Class as IOClass-import qualified System.CPUTime as CPUTime-import Data.IORef-import Data.Time.Clock.POSIX (POSIXTime, getPOSIXTime)--import Test.Hspec.Util (Path)---- | A lifted version of `Control.Monad.Trans.State.gets`-gets :: (FormatterState -> a) -> FormatM a-gets f = FormatM $ do- f <$> (get >>= IOClass.liftIO . readIORef)---- | A lifted version of `Control.Monad.Trans.State.modify`-modify :: (FormatterState -> FormatterState) -> FormatM ()-modify f = FormatM $ do- get >>= IOClass.liftIO . (`modifyIORef` f)---- | A lifted version of `IOClass.liftIO`------ This is meant for internal use only, and not part of the public API. This--- is also the reason why we do not make FormatM an instance MonadIO, so we--- have narrow control over the visibilty of this function.-liftIO :: IO a -> FormatM a-liftIO action = FormatM (IOClass.liftIO action)--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]-, cpuStartTime :: Maybe Integer-, startTime :: POSIXTime-}---- | 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)--runFormatM :: Bool -> Bool -> Bool -> Handle -> FormatM a -> IO a-runFormatM useColor produceHTML_ printCpuTime 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 [] 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 ()---- | 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 (intersperse)-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 = concat . intersperse "\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,54 +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-, Pending---- * 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 = h}
− src/Test/Hspec/Pending.hs
@@ -1,34 +0,0 @@-{-# LANGUAGE FlexibleInstances #-}-module Test.Hspec.Pending where--import qualified Test.Hspec.Core.Type as Core-import Test.Hspec.Core.Type (Example(..))---- NOTE: This is defined in a separate packages, because it clashes with--- Result.Pending.---- | A pending example.-newtype Pending = Pending (Maybe String)--instance Example Pending where- evaluateExample c (Pending reason) = evaluateExample c (Core.Pending reason)--instance Example (String -> Pending) where- evaluateExample c _ = evaluateExample c (Pending Nothing)---- | 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------ You can give an optional reason for why it's pending:------ > describe "fancyFormatter" $ do--- > it "can format text in a way that everyone likes" $--- > pending "waiting for clarification from the designers"-pending :: String -> Pending-pending = Pending . Just
src/Test/Hspec/QuickCheck.hs view
@@ -1,19 +1,22 @@--- |--- Stability: provisional+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE ConstraintKinds #-} module Test.Hspec.QuickCheck (--- * 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+-- * Params+ modifyArgs+, modifyMaxSuccess+, modifyMaxDiscardRatio+, modifyMaxSize+, modifyMaxShrinks+ -- * Shortcuts , prop+, xprop+, fprop ) where -import Test.QuickCheck import Test.Hspec+import Test.QuickCheck+import Test.Hspec.Core.QuickCheck -- | -- > prop ".." $@@ -21,7 +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+++-- |+-- > xprop ".." $+-- > ..+--+-- is a shortcut for+--+-- @+-- `xit` ".." $ `property` $+-- ..+-- @+xprop :: (HasCallStack, Testable prop) => String -> prop -> Spec+xprop s = xit s . property+++-- |+-- > 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,152 +1,2 @@--- |--- Stability: provisional-module Test.Hspec.Runner (--- * Running a spec- hspec-, hspecWith---- * Types-, Summary (..)-, Config (..)-, ColorMode (..)-, Path-, defaultConfig-, configAddFilter-) where--import Control.Monad-import Control.Applicative-import Data.Monoid-import Data.Maybe-import System.IO-import System.Environment-import System.Exit-import System.IO.Silently (silence)--import Test.Hspec.Util (Path, safeEvaluate)-import Test.Hspec.Core.Type-import Test.Hspec.Config-import Test.Hspec.Formatters-import Test.Hspec.Formatters.Internal-import Test.Hspec.FailureReport---- | 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 = catMaybes . map (goSpec groups)-- goSpec :: [String] -> SpecTree -> Maybe SpecTree- goSpec groups spec = case spec of- SpecItem requirement _ -> guard (p (groups, requirement)) >> return spec- SpecGroup group specs -> case goSpecs (groups ++ [group]) specs of- [] -> Nothing- xs -> Just (SpecGroup group xs)---- | Evaluate all examples of a given spec and produce a report.-runFormatter :: Config -> Formatter -> [SpecTree] -> FormatM ()-runFormatter c formatter specs = headerFormatter formatter >> zip [0..] specs `each` go []- where- -- like forM_, but respects --fast-fail- each :: [a] -> (a -> FormatM ()) -> FormatM ()- each [] _ = pure ()- each (x:xs) f = do- f x- fails <- getFailCount- unless (configFastFail c && fails /= 0) $ do- xs `each` f-- silence_- | configVerbose c = id- | otherwise = silence-- eval- | configDryRun c = \_ -> return (Right Success)- | otherwise = liftIO . safeEvaluate . silence_-- go :: [String] -> (Int, SpecTree) -> FormatM ()- go rGroups (n, SpecGroup group xs) = do- exampleGroupStarted formatter n (reverse rGroups) group- zip [0..] xs `each` go (group : rGroups)- exampleGroupDone formatter- go rGroups (_, SpecItem requirement example) = do- result <- eval (example $ configParams c)- 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- path = (groups, requirement)- groups = reverse rGroups- failed err = do- increaseFailCount- addFailMessage path err- exampleFailed formatter path err----- | Run given spec and write a report to `stdout`.--- Exit with `exitFailure` if at least one spec item fails.------ (see also `hspecWith`)-hspec :: Spec -> IO ()-hspec spec = do- c <- getConfig- withArgs [] {- do not leak command-line arguments to examples -} $ do- r <- hspecWith c spec- unless (summaryFailures r == 0) exitFailure---- | Run given spec with custom options.--- This is similar to `hspec`, but more flexible.------ /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 = do- -- read failure report on --re-run- c <- if configReRun c_- then do- readFailureReport c_- else do- return c_-- let formatter = configFormatter c- h = configHandle c-- useColor <- doesUseColor h c- runFormatM useColor (configHtmlOutput c) (configPrintCpuTime c) h $ do- runFormatter c formatter (maybe id filterSpecs (configFilterPredicate c) $ runSpecM spec) `finally_`- failedFormatter formatter-- footerFormatter formatter-- -- dump failure report- xs <- map failureRecordPath <$> getFailMessages- liftIO $ writeFailureReport (show xs)-- Summary <$> getTotalCount <*> getFailCount- where- doesUseColor :: Handle -> Config -> IO Bool- doesUseColor h c = case configColorMode c of- ColorAuto -> hIsTerminalDevice h- ColorNever -> return False- ColorAlway -> return True---- | 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/Util.hs
@@ -1,96 +0,0 @@-module Test.Hspec.Util (- quantify-, lineBreaksAt-, safeEvaluate-, Path-, filterPredicate-, formatRequirement-, readMaybe-, getEnv-) where--import Data.List-import Data.Maybe-import Data.Char (isSpace)-import Control.Applicative-import qualified Control.Exception as E-import qualified System.Environment as Environment---- | Create a more readable display of a quantity of something.------ Examples:------ >>> quantify 0 "example"--- "0 examples"------ >>> quantify 1 "example"--- "1 example"------ >>> quantify 2 "example"--- "2 examples"-quantify :: Int -> String -> String-quantify 1 s = "1 " ++ s-quantify n s = show n ++ " " ++ s ++ "s"--safeEvaluate :: IO a -> IO (Either E.SomeException a)-safeEvaluate 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.throw (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---- NOTE: base-4.6.0.0 provides a function with that name and type. For--- compatibility with earlier versions, we define our own version here.-readMaybe :: Read a => String -> Maybe a-readMaybe = fmap fst . listToMaybe . reads--getEnv :: String -> IO (Maybe String)-getEnv key = either (const Nothing) Just <$> safeEvaluate (Environment.getEnv key)---- ensure that lines are not longer then given `n`, insert line beraks 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)
− 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,23 +0,0 @@-{-# LANGUAGE DeriveDataTypeable #-}-module Test.Hspec.CompatSpec (main, spec) where--import Test.Hspec.Meta--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"
− test/Test/Hspec/Core/TypeSpec.hs
@@ -1,65 +0,0 @@-module Test.Hspec.Core.TypeSpec (main, spec) where--import Test.Hspec.Meta-import Test.QuickCheck--import Test.QuickCheck.Property (morallyDubiousIOProperty)-import Control.Exception (AsyncException(..), throwIO)-import qualified Test.Hspec.Core.Type as H-import qualified Test.Hspec.Pending as H (pending)--main :: IO ()-main = hspec spec--evaluateExample :: H.Example e => e -> IO H.Result-evaluateExample = H.evaluateExample H.defaultParams--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"-- 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 $ \ n -> n == (n + 1 :: Int)- lines r `shouldSatisfy` any (== "0")-- it "propagates UserInterrupt" $ do- let p = morallyDubiousIOProperty (throwIO UserInterrupt >> return True)- evaluateExample p `shouldThrow` (== UserInterrupt)-- it "propagates exceptions" $ do- pending "this probaly needs a patch to QuickCheck"- -- evaluateExample (property $ (error "foobar" :: Int -> Bool)) `shouldThrow` errorCall "foobar"-- context "for pending" $ do- it "returns Pending" $ do- evaluateExample (H.pending) `shouldReturn` H.Pending Nothing-- it "includes the optional reason" $ do- evaluateExample (H.pending "foo") `shouldReturn` H.Pending (Just "foo")
− test/Test/Hspec/FailureReportSpec.hs
@@ -1,40 +0,0 @@-module Test.Hspec.FailureReportSpec (main, spec) where--import Test.Hspec.Meta--import System.IO-import System.IO.Silently-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 --re-run 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,225 +0,0 @@-{-# LANGUAGE CPP #-}-module Test.Hspec.FormattersSpec (main, spec) where--import Test.Hspec.Meta--import Util-import System.IO.Silently (capture)-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.pending "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")-- it "outputs failed examples in red, pending in yellow, and successful in green" $ do- pending-- 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 FAILED")-- 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 FAILED (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 FAILED")-- 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.ColorAlway} $ 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.ColorAlway} $ 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.ColorAlway} $ 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.ColorAlway} $ 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,83 +0,0 @@-module Test.Hspec.HUnitSpec (main, spec) where--import Test.Hspec.Meta-import Util (captureLines)-import Control.Applicative--import qualified Test.Hspec as H-import qualified Test.Hspec.Runner as H-import Test.Hspec.Core.Type (SpecTree(..), 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 s _ -> Example s--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- runSpec $ 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- runSpec $ 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 . runSpec $ 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 . runSpec $ 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- where- runSpec = H.hspecWith H.defaultConfig
− test/Test/Hspec/QuickCheckSpec.hs
@@ -1,19 +0,0 @@-module Test.Hspec.QuickCheckSpec (main, spec) where--import Test.Hspec.Meta--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- H.hspecWith H.defaultConfig $ 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,293 +0,0 @@-module Test.Hspec.RunnerSpec (main, spec) where--import Test.Hspec.Meta-import System.IO.Silently-import System.IO (stderr)-import Control.Applicative-import Control.Monad (unless)-import System.Environment (withArgs, withProgName, getArgs)-import System.Exit-import qualified Control.Exception as E-import Util-import Mock-import System.SetEnv-import Test.Hspec.Util (getEnv)-import Test.QuickCheck.Property (morallyDubiousIOProperty)--import qualified Test.Hspec.Runner as H-import qualified Test.Hspec as H (describe, it, pending)-import qualified Test.Hspec.Formatters as H (silent)--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)--main :: IO ()-main = hspec spec--spec :: Spec-spec = do-- describe "hspec" $ do- it "runs a spec" $ do- H.hspec $ do- H.it "foobar" True- `shouldReturn` ()-- it "exits with exitFailure if not all examples pass" $ do- H.hspec $ do- H.it "foobar" False- `shouldThrow` (== ExitFailure 1)-- it "suppresses output to stdout when evaluating examples" $ do- r <- captureLines . H.hspec $ do- H.it "foobar" $ do- putStrLn "baz"- r `shouldSatisfy` notElem "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 "does not leak command-line flags to examples" $ do- 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 . 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 FAILED"- , ""- ]-- it "throws UserInterrupt" $ do- 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]..."]- 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 --verbose" $ do- it "does not suppress output to stdout" $ do- r <- captureLines . withArgs ["--verbose"] . H.hspec $ do- H.it "foobar" $ do- putStrLn "baz"- r `shouldSatisfy` elem "baz"-- 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 --fast-fail" $ do- it "stops after first failure" $ do- r <- captureLines . ignoreExitCode . withArgs ["--fast-fail"] . H.hspec $ do- H.it "foo" True- H.it "bar" False- H.it "baz" False- normalizeSummary r `shouldBe` [- ""- , "- foo"- , "- bar FAILED [1]"- , ""- , "1) bar FAILED"- , ""- , "Finished in 0.0000 seconds"- , "2 examples, 1 failure"- ]-- it "works for nested specs" $ do- r <- captureLines . ignoreExitCode . withArgs ["--fast-fail"] . 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 FAILED"- , ""- , "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- 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- 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 --maximum-generated-tests=n" $ do- it "tries QuickCheck properties n times" $ do- m <- newMock- withArgs ["--maximum-generated-tests=23"] . H.hspec $ do- H.it "foo" $ do- morallyDubiousIOProperty (mockAction m >> pure True)- mockCounter m `shouldReturn` 23-- 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 "hspec (experimental features)" $ do- it "stores a failure report in environment HSPEC_FAILURES" $ do- ignoreExitCode . 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- getEnv "HSPEC_FAILURES" `shouldReturn` Just "[([\"foo\",\"bar\"],\"example 2\"),([\"baz\"],\"example 3\")]"-- describe "with --re-run" $ 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 "re-runs examples that previously failed" $ do- r0 <- runSpec- r0 `shouldSatisfy` elem "5 examples, 3 failures"-- r1 <- withArgs ["-r"] runSpec- r1 `shouldSatisfy` elem "3 examples, 3 failures"-- 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- fst r `shouldBe` "WARNING: Could not read environment variable HSPEC_FAILURES; `--re-run' 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- fst r `shouldBe` "WARNING: Could not read environment variable HSPEC_FAILURES; `--re-run' is ignored!\n"-- describe "hspecWith" $ do- it "returns a summary of the test run" $ do- H.hspecWith H.defaultConfig $ 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- H.hspecWith H.defaultConfig $ 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.hspecWith H.defaultConfig $ 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` ""
− test/Test/Hspec/UtilSpec.hs
@@ -1,100 +0,0 @@-module Test.Hspec.UtilSpec (main, spec) where--import Test.Hspec.Meta--import qualified Control.Exception as E-import Test.Hspec.Util--import System.SetEnv--main :: IO ()-main = hspec spec--spec :: Spec-spec = do- describe "quantify" $ do- it "returns an amount and a word given an amount and word" $ do- quantify 1 "thing" `shouldBe` "1 thing"-- it "returns a singular word given the number 1" $ do- quantify 1 "thing" `shouldBe` "1 thing"-- it "returns a plural word given a number greater than 1" $ do- quantify 2 "thing" `shouldBe` "2 things"-- it "returns a plural word given the number 0" $ do- quantify 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 "safeEvaluate" $ do- it "returns Right on success" $ do- Right e <- safeEvaluate (return 23 :: IO Int)- e `shouldBe` 23-- it "returns Left on exception" $ do- Left e <- safeEvaluate (E.throwIO E.DivideByZero :: IO Int)- show e `shouldBe` "divide by zero"-- it "evaluates result to weak head normal form" $ do- Left e <- safeEvaluate (return undefined)- show e `shouldBe` "Prelude.undefined"-- it "re-throws AsyncException" $ do- safeEvaluate (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 "getEnv" $ do- it "returns value of specified environment variable" $ do- setEnv "FOO" "bar"- getEnv "FOO" `shouldReturn` Just "bar"-- it "returns Nothing if specified environment variable is not set" $ do- unsetEnv "FOO"- getEnv "FOO" `shouldReturn` Nothing
− test/Test/HspecSpec.hs
@@ -1,64 +0,0 @@-module Test.HspecSpec (main, spec) where--import Test.Hspec.Meta-import Util (captureLines)-import Data.List (isPrefixOf)--import qualified Test.Hspec.Core.Type as H (defaultParams)-import Test.Hspec.Core (SpecTree(..), Result(..), runSpecM)-import qualified Test.Hspec as H-import qualified Test.Hspec.Runner as H (hspecWith)-import Test.Hspec.Runner (defaultConfig)--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")-- it "accepts an optional message, which is included in the report" $ do- r <- runSpec $ do- H.it "foo" $ do- H.pending "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 baz _]]] = runSpecM $ do- H.describe "foo" $ do- H.describe "bar" $ do- H.it "baz" True- (foo, bar, baz) `shouldBe` ("foo", "bar", "baz")-- describe "it" $ do- it "takes a description of a desired behavior" $ do- let [SpecItem d _] = runSpecM (H.it "whatever" True)- d `shouldBe` "whatever"-- it "takes an example of that behavior" $ do- let [SpecItem _ e] = runSpecM (H.it "whatever" True)- e H.defaultParams `shouldReturn` Success-- it "can use a Bool, HUnit Test, QuickCheck property, or `pending` as an example"- pending- where- runSpec :: H.Spec -> IO [String]- runSpec = captureLines . H.hspecWith defaultConfig
− test/Util.hs
@@ -1,27 +0,0 @@-module Util where--import Data.List-import Data.Char-import Test.Hspec.Meta-import System.IO.Silently--captureLines :: IO a -> IO [String]-captureLines = fmap lines . capture_--shouldContain :: (Eq a, Show a) => [a] -> [a] -> Expectation-x `shouldContain` y = x `shouldSatisfy` isInfixOf y--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
− 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/