A precondition is an input condition that must hold before a scenario or operation begins. In requirements, it records the state users or systems must establish before following the main path, while a postcondition records the expected result afterward. section 2.1.4
A scenario precondition
For a scenario that generates a new random world, “the game is launched” is the precondition. The user then opens the generation window, supplies a seed or world parameters, and starts generation; a new world is the postcondition. section 2.1.4
In property-based testing, preconditions filter generated inputs before the tested logic runs. A formally correct condition can still produce a poor test when the generator rarely creates acceptable values: QuickCheck may reject too many inputs and give up before exercising the implementation sufficiently. section 15.1.3
When a generated-input precondition is too selective, adjust the test strategy:
- Generate values from a narrower type or provide a better Arbitrary instance. section 15.1.3
- Remove the filter and include negative cases in the property being checked. section 15.1.3
- Customize generation depth, run counts, or generated values so meaningful inputs reach the operation. section 15.1.3
Listing 15.5 Adjusting the test data generator
...
$ monadicIO $ do
x :: Int <- pick arbitrary #1
y :: Int <- pick arbitrary
pre (x >= 4 && x <= 10 && y >= 4 && y <= 10) #2
let action = generateLabyrinth (x, y) 3 3 #3
eLab <- run (try (runLangL coreRuntime action)) #4
case eLab of #5
Left (err :: SomeException) -> assert False
Right lab -> do
let (x, y) = getBounds lab
assert (x * y >= 16 && x * y <= 100)
This listing shows a precondition restricting generated dimensions to the valid range before labyrinth generation is executed. section 15.1.3







