1 cabal-testsuite is a suite of integration tests for Cabal-based
7 1. Build `cabal-testsuite` (`cabal build cabal-testsuite:cabal-tests`)
8 2. Run the `cabal-tests` executable. It will scan for all tests
9 in your current directory and subdirectories and run them.
10 To run a specific set of tests, use `cabal-tests --with-cabal=CABALBIN PATH ...`.
11 (e.g. `cabal run cabal-testsuite:cabal-tests -- --with-cabal=cabal cabal-testsuite/PackageTests/TestOptions/setup.test.hs`)
12 You can control parallelism using the `-j` flag.
14 There are a few useful flags:
16 * `--with-cabal PATH` can be used to specify the path of a
17 `cabal-install` executable. IF YOU DO NOT SPECIFY THIS FLAG,
18 CABAL INSTALL TESTS WILL NOT RUN.
20 * `--with-ghc PATH` can be used to specify an alternate version of
21 GHC to ask the tests to compile with.
23 * `--builddir DIR` can be used to manually specify the dist directory
24 that was used to build `cabal-tests`; this can be used if
25 the autodetection doesn't work correctly (which may be the
26 case for old versions of GHC.)
28 * `--keep-tmp-files` can be used to keep the temporary directories that tests
31 ## Which Cabal library version do cabal-install tests use?
33 By default the `cabal-install` tests will use the `Cabal` library which comes with
34 the boot compiler when it needs to build a custom `Setup.hs`.
36 This can be very confusing if you are modifying the Cabal library, writing a test
37 which relies on a custom setup script and you are wondering why the test is not
38 responding at all to your changes.
40 There are some flags which allow you to instruct `cabal-install` to use a different
41 `Cabal` library version.
43 1. `--boot-cabal-lib` specifies to use the Cabal library bundled with the
44 test compiler, this is the default.
45 2. `--intree-cabal-lib=<root_dir>` specifies to use Cabal and Cabal-syntax
46 from a specific directory, and `--test-tmp` indicates where to put
47 the package database they are built into.
48 3. `--specific-cabal-lib=<VERSION>` specifies to use a specific Cabal
49 version from hackage (ie 3.10.2.0) and installs the package database
50 into `--test-tmp=<DIR>`
52 The CI scripts use the `--intree-cabal-lib` option for the most part but in
53 the future there should be a variety of jobs which test `cabal-install` built
54 against newer `Cabal` versions but forced to interact with older `Cabal` versions.
56 ### How to run the doctests
58 You need to install the `doctest` tool. Make sure it's compiled with your current
59 GHC, and don't forget to reinstall it every time you switch GHC version:
62 cabal install doctest --overwrite-policy=always --ignore-project
65 After that you can run doctests for a component of your choice via the following command:
68 cabal repl --with-ghc=doctest --build-depends=QuickCheck --build-depends=template-haskell --repl-options="-w" --project-file="cabal.validate.project" Cabal-syntax
71 In this example we have run doctests in `Cabal-syntax`. Notice, that some
72 components have broken doctests
73 ([#8734](https://github.com/haskell/cabal/issues/8734));
74 our CI currently checks that `Cabal-syntax` and `Cabal` doctests pass via
75 `make doctest-install && make doctest` (you can use this `make`-based workflow too).
80 If you learn better by example, just look at the tests that live
81 in `cabal-testsuite/PackageTests`; if you `git log -p`, you can
82 see the full contents of various commits which added a test for
83 various functionality. See if you can find an existing test that
84 is similar to what you want to test.
86 Tests are all run in temporary system directories. At the start of a test
87 all the files which are in the same folder as the test script are copied into
88 a system temporary directory and then the rest of the script operates in this
91 **NOTE:** only files which are known to git are copied, so you have to
92 `git add` any files which are part of a test before running the test.
93 You can use the `--keep-tmp-files` flag to keep the temporary directories in
94 order to inspect the result of running a test.
96 Otherwise, here is a walkthrough:
98 1. Create the package(s) that you need for your test in a
100 (Currently (2021-10-06), tests are stored in `PackageTests`,
101 with the exception of one test stored in `tests`.)
103 2. Create one or more `.test.hs` scripts in your directory, using
106 import Test.Cabal.Prelude
107 main = setupAndCabalTest $ do
108 -- your test code here
111 `setupAndCabal` test indicates that invocations of `setup`
112 should work both for a raw `Setup` script, as well as
113 `cabal-install` (if your test works only for one or the
114 other, use `setupTest` or `cabalTest`).
116 Code runs in the `TestM` monad, which manages some administrative
117 environment (e.g., the test that is running, etc.).
118 `Test.Cabal.Prelude` contains a number of useful functions
119 for testing implemented in this monad, including the functions `cabal`
120 and `setup` which let you invoke those respective programs. You should
121 read through that file to get a sense for what capabilities
122 are possible (grep for use-sites of functions to see how they
123 are used). If you don't see something anywhere, that's probably
124 because it isn't implemented. Implement it!
126 To include parts that are supposed to fail (in the sense that a
127 non-zero exit code is returned), there is the `fails` combinator,
130 main = cabalTest $ do
131 fails $ cabal "bad-command" [ "bad", "args" ]
132 cabal "good-command" [ "good", "args" ]
133 fails $ cabal "another-bad-one" [ ... ]
137 The dependencies which your test is allowed to use are listed in the
138 cabal file under the `test-runtime-deps` executable. At compile-time there is
139 a custom Setup.hs script which inspects this list and records the versions of
140 each package in a generated file. These are then used when `cabal-tests` runs
141 when it invokes `runghc` to run each test.
142 We ensure they are built and available by listing `test-runtime-deps` in the
143 build-tool-depends section of the cabal-tests executable.
146 3. Run your tests using `cabal-tests` (no need to rebuild when
147 you add or modify a test; it is automatically picked up).
148 The first time you run a test, assuming everything else is
149 in order, it will complain that the actual output doesn't match
150 the expected output. Use the `--accept` flag to accept the
151 output if it makes sense!
153 We also support a `.multitest.hs` prefix; eventually this will
154 allow multiple tests to be defined in one file but run in parallel;
155 at the moment, these just indicate long running tests that should
156 be run early (to avoid straggling).
158 Frequently asked questions
159 --------------------------
161 For all of these answers, to see examples of the functions in
162 question, grep the test suite.
164 **Why isn't some output I added to Cabal showing up in the recorded
165 test output?** Only "marked" output is picked up by Cabal; currently,
166 only `notice`, `warn` and `die` produce marked output. Use those
167 combinators for your output.
169 **How can I add a dependency on a package from Hackage in a test?**
170 By default, the test suite is completely independent of the contents
171 of Hackage, to ensure that it keeps working across all GHC versions.
172 If possible, define the package locally. If the package needs
173 to be from Hackage (e.g., you are testing the global store code
174 in new-build), use `withRepo "repo"` to initialize a "fake" Hackage with
175 the packages placed in the `repo` directory.
177 **How do I run an executable that my test built?** The specific
178 function you should use depends on how you built the executable:
180 * If you built it using `Setup build`, use `runExe`
181 * If you installed it using `Setup install` or `cabal install`, use
183 * If you built it with `cabal build`, use `runPlanExe`; note
184 that you will need to run this inside of a `withPlan` that is
185 placed *after* you have invoked `build`. (Grep for an example!)
187 **How do I turn off accept tests? My test output wobbles too much.**
188 Use `recordMode DoNotRecord`. This should be a last resort; consider
189 modifying Cabal so that the output is stable. If you must do this, make
190 sure you add extra, manual tests to ensure the output looks like what
193 **How can I manually test for a string in output?** Use the primed
194 variants of a command (e.g., `cabal'` rather than `cabal`) and use
195 `assertOutputContains`. Note that this will search over BOTH stdout
198 **How do I skip running a test in some environments?** Use the
199 `skipIf` and `skipUnless` combinators. Useful parameters to test
200 these with include `hasSharedLibraries`, `hasProfiledLibraries`,
201 `hasCabalShared`, `isGhcVersion`, `isWindows`, `isLinux`, `isOSX`.
203 **I programmatically modified a file in my test suite, but Cabal/GHC
204 doesn't seem to be picking it up.** You need to sleep sufficiently
205 long before editing a file, in order for file system timestamp
206 resolution to pick it up. Use `withDelay` and `delay` prior to
207 making a modification.
209 **How do I mark a test as broken?** Use `expectBroken`, which takes
210 the ticket number as its first argument. Note that this does NOT
211 handle accept-test brokenness, so you will have to add a manual
212 string output test, if that is how your test is "failing."
217 Tests are run in a fresh temporary system directory. This attempts to isolate the
218 tests from anything specific to do with your directory structure. In particular
220 * You must be running the test inside a valid Git checkout of the test
221 suite (`withSourceCopy` uses Git to determine which files should be copied.)
223 * You must `git add` all files which are relevant to the test, otherwise
224 they will not be copied.
229 This is the second rewrite of the integration testing framework. The
230 primary goal was to use Haskell as the test language (letting us take
231 advantage of a real programming language, and use utilities provided to
232 us by the Cabal library itself), while at the same time compensating for
233 two perceived problems of pure-Haskell test suites:
235 * Haskell test suites are generally compiled before they run
236 (for example, this is the modus operandi of `cabal test`).
237 In practice, this results in a long edit-recompile cycle
238 when working on tests. This hurts a lot when you would
239 like to experimentally edit a test when debugging an issue.
241 * Haskell's metaprogramming facilities (e.g., Template Haskell)
242 can't handle dynamically loading modules from the file system;
243 thus, there ends up being a considerable amount of boilerplate
244 needed to "wire" up test cases to the central test runner.
246 Our approach to address these issues is to maintain Haskell test scripts
247 as self-contained programs which are run by the GHCi interpreter.
248 This is not altogether trivial, and so there are a few important
249 technical innovations to make this work:
251 * Unlike a traditional test program which can be built by the Cabal
252 build system, these test scripts must be interpretable at
253 runtime (outside of the build system.) Our approach to handle
254 this is to link against the same version of Cabal that was
255 used to build the top-level test program (by way of a Custom
256 setup linked against the Cabal library under test) and then
257 use this library to compute the necessary GHC flags to pass
260 * The startup latency of `runghc` can be quite high, which adds up
261 when you have many tests. To solve this, our `Test.Cabal.Server`
262 GHCi server implementation can reuse
263 a GHCi instance as we are running test scripts. It took some
264 technical ingenuity to implement this, but the result is that
265 running scripts is essentially free.
267 Here is the general outline of how the `cabal-tests` program operates:
269 1. It first loads the cached `LocalBuildInfo` associated with the
270 host build system (which was responsible for building `cabal-tests`
271 in the first place.) This information lets us compute the
272 flags that we will use to subsequently invoke GHC.
274 2. We then recursively scan the current working directory, looking
275 for files suffixed `.test.hs`; these are the test scripts we
278 3. For every thread specified via the `-j`, we spawn a GHCi
279 server, and then use these to run the test scripts until all
280 test scripts have been run.
282 The new `cabal-tests` runner doesn't use Tasty because I couldn't
283 figure out how to get out the threading setting, and then spawn
284 that many GHCi servers to service the running threads. Improvements
290 An expect test (aka _golden test_)
291 is a test where we read out the output of the test
292 and compare it directly against a saved copy of the test output.
293 When test output changes, you can ask the test suite to "accept"
294 the new output, which automatically overwrites the old expected
295 test output with the new.
297 Supporting expect tests with Cabal is challenging, because Cabal
298 interacts with multiple versions of external components (most
299 prominently GHC) with different variants of their output, and no
300 one wants to rerun a test on four different versions of GHC to make
301 sure we've picked up the correct output in all cases.
303 Still, we'd like to take advantage of expect tests for Cabal's error
304 reporting. So here's our strategy:
306 1. We have a new verbosity flag `+markoutput` which lets you toggle the emission
307 of `-----BEGIN CABAL OUTPUT-----` and `-----END CABAL OUTPUT-----`
310 2. When someone requests an expect test, we ONLY consider output between
313 The expectation is that Cabal will only enclose output it controls
314 between these stanzas. In practice, this just means we wrap `die`,
315 `warn` and `notice` with these markers.
317 An added benefit of this strategy is that we can continue operating
318 at high verbosity by default (which is very helpful for having useful
319 diagnostic information immediately, e.g. in CI.)
321 We also need to deal with nondeterminism in test output in some
322 situations. Here are the most common ones:
324 * Dependency solving output on failure is still non-deterministic, due to
325 its dependence on the global package database. We're tracking this
326 in https://github.com/haskell/cabal/issues/4332 but for now, we're
327 not running expect tests on this output.
329 * Tests against Custom setup will build against the Cabal that shipped with
330 GHC, so you need to be careful NOT to record this output (since we
331 don't control that output.)
333 * We have some munging on the output, to remove common sources of
334 non-determinism: paths, GHC versions, boot package versions, etc.
335 Check `normalizeOutput` to see what we do. Note that we save
336 *normalized* output, so if you modify the normalizer you will
337 need to rerun the test suite accepting everything.
339 * The Setup interface gets a `--enable-deterministic` flag which we
340 pass by default. The intent is to make Cabal more deterministic;
341 for example, with this flag we no longer compute a hash when
342 computing IPIDs, but just use the tag `-inplace`. You can manually
343 disable this using `--disable-deterministic` (as is the case with
348 * It's good style to put `default-language` in all your stanzas, so
349 Cabal doesn't complain about it (that warning is marked!). Ditto
350 with `cabal-version` at the top of your Cabal file.
352 * If you can't get the output of a test to be deterministic, no
353 problem: just exclude it from recording and do a manual test
354 on the output for the string you're looking for. Try to be
355 deterministic, but sometimes it's not (easily) possible.
360 Here are some things we do not currently plan on supporting:
362 * A file format for specifying multiple packages and source files.
363 While in principle there is nothing wrong with making it easier
364 to write tests, tests stored in this manner are more difficult
365 to debug with, as they must first be "decompressed" into a full
366 folder hierarchy before they can be interacted with. (But some
367 of our tests need substantial setup; for example, tests that
368 have to setup a package repository. In this case, because there
369 already is a setup necessary, we might consider making things easier here.)