I know I can just wrap the whole test-suite with testWithApplication (in main) but I'd prefer if the API was started only for the TestTree that requires it.
Right, so there are two different ways to achieve this.
One way is what the linked tutorial does with Hspec's around
: start and stop your app for each individual test.
Tasty doesn't provide a separate utility for this use case because it's fairly trivial to do it yourself: simply call testWithApplication
inside each testCase
(or you could define an alias for a composition of testCase
and testWithApplication
to save you some typing). But if you have multiple tests for the same application, you might think it's a bit wasteful to start and stop it for each individual test.
That's where tasty's withResource
(or HSpec's aroundAll
) comes in. When you use it, the app is started right before the first test that needs it and stopped right after the last such test.
But that relies crucially on the dynamic scope of resources — i.e. we don't know in advance in what order the resources will be allocated or de-allocated. (This may seem surprising if you think of executing the test suite as traversing the test tree and running all tests in order. But the reality is more complicated due to parallel test execution and dependencies between tests, so the actual execution order can be arbitrary.)
And that dynamic scope is incompatible with the "with"-style functions, which normally only create nested, stack-like scopes.
So your options are:
- Start an app at the top level and have it running for the whole duration of the test suite (what you describe in your question).
- Start and stop the app at the bottom level (i.e. within each
testCase
), which is what the linked tutorial does with Hspec.
- Don't use
testWithApplication
, but instead write separate functions to start and stop the app. The appeal of testWithApplication
compared to separate acquire/release functions is that it handles exceptions for you and ensures the the release action will run, but tasty already takes care of that.
- Finally, there's a trick I describe in Decompose ContT that uses threads to achieve dynamic scope with "with"-style functions (which are equivalent to ContT values). This could be the most practical solution if decomposing
testWithApplication
into separate acquire/release actions is too much of a hassle. HSpec's aroundAll also seems to be using something similar and threads-based.