668db763

Report a description or a failure that cannot be rendered

Stacked on #155, which is where exceptions thrown *by* a test are decided.
This is about the two places outside a test body where an exception still took
the suite down.

## Hole 1: a description

A description is user code: `describe (nameFor x)` throws whatever `nameFor`
throws. Nothing forced one until the output did, in the thread that collects
results, where the exception took the suite down along with the results of
every test that had already run. Worse, the terse output never forces a
description at all, so the same suite passed piped into a file and died in a
terminal.

`reportUnrenderableDescriptions` walks the forest once in `runTestDefM`, after
filtering and randomisation, and replaces a node whose description throws with
a test that fails carrying that exception. Every runner gets its forest from
`runTestDefM`, so one walk covers all of them and the two output formats agree
by construction rather than by assertion.

A `describe` takes its subtree with it: a group that cannot say what it is
cannot sensibly report what is under it. The stand-in keeps the call stack of
the `it` it replaces, so the failure points at the test whose name threw, and
it is not retried, because the same description throws the same way every time.

## Hole 2: a failure

Rendering a failure runs user code too: the `displayException` of whatever the
test threw, the `Show` of a compared value, a message built lazily. That first
ran in the thread collecting results, so a failure whose rendering throws —
`effectful`'s errors among them — took the suite down after every test had
already run, with the summary and every other result.

`reportUnrenderableFailures` forces a result's rendering in the worker that
produced it, where anything thrown is that test's own failure, and replaces
what could not be rendered with an assertion carrying the message. An
assertion, because that is what both output formats render as the text it is:
the terse output does not print `extraInfo`, and an exception made in the
handler carries a context whose backtrace points into sydtest's own forcing
and holds a package-id hash that differs between builds.

Nothing unrenderable is kept — exception, extra info, failing inputs, labels,
classes and tables all go — because a result that still carries it still has
something that throws when the output reaches it. Forcing once is enough: the
output renders the same value again, and a value that rendered once renders
again.

## Tests

- `UnrenderableDescriptionSpec`: reported as one failing test by each runner,
  a `describe` collapsing in place of its tests, the rest of the suite still
  running, and the failure naming what threw. All seven fail without the fix.
- `UnrenderableFailureSpec`: `reportUnrenderableFailures` directly, including
  extra info that does not render, which the pretty output renders and which
  an earlier version of this branch left in place.
- `sydtest-output-test` gets a case whose `displayException` throws. That
  suite runs its spec through all four runners and golden-tests the rendering,
  so without the fix it dies during the first of the four and never reaches
  the golden tests. The case sits at the end of its spec with its type
  declared below `spec`, because every failure there is numbered and every
  test records its source line, so anything added earlier renumbers the lot.

## Version

0.35.0.0. No API changes, but a suite that passes today with a lazily-unused
bottom description starts failing, which is more than a patch and matches how
0.32.0.0 and 0.33.0.0 were versioned.
PR #160
configurex86_64-linux