Why does EK9 use compile-check-discard for generated tests?

← Fuzzing and Mutation Testing · Ref: Q755

EK9 test generation uses a compile-check-discard pattern: generate a candidate test, compile it, keep it only if compilation succeeds. This is fundamentally different from every other test generation tool.

THE COMPILER IS THE FILTER

Other tools generate tests and hope they are valid. EK9 generates candidates and uses its own compiler as an oracle. A candidate that fails type checking, violates purity, uses an invalid operator, or triggers any quality check is silently discarded. Only programs that pass ALL compiler checks survive.

WHY THIS WORKS IN EK9

EK9 has no warnings. Every check is pass or fail. This means the compiler gives a definitive answer: this candidate is either fully valid or it is not. There is no ambiguity, no 'valid with warnings' gray area.

TYPE-AWARE GENERATION

Because the generator knows the type system, it generates calls with correct types. But edge-case combinations (empty string to a function expecting non-empty, zero to a divider) may fail purity or data-flow checks. Compile-check-discard handles this automatically.

PRACTICAL BENEFIT

The output file contains ONLY tests that:

  1. Parse correctly (valid EK9 syntax).
  2. Pass type checking (correct argument types).
  3. Pass data flow analysis (no uninitialised variables).
  4. Pass quality checks (no magic literals, no dead code).

This is a guarantee no other test generator provides.

NO OTHER LANGUAGE DOES THIS

AFL, libFuzzer, EvoSuite, Hypothesis, and cargo-fuzz all generate inputs, not full programs. EK9 generates complete @Test programs and validates them against the full compiler pipeline.

See Q749 for fuzzing overview. See Q754 for test generation. See Q753 for mutation testing. See Q310 for quality at compile time.

Example

defines module qa.fuzzingandmutation.compilecheckdiscard

  <?-
    Demonstrates functions whose edge-case combinations
    could fail quality checks. The compile-check-discard
    pattern automatically handles these cases.
  -?>

  defines function

    <?-
      Test generator might try dividing by zero.
      The guard prevents a crash, but a candidate test
      calling this with zero would still compile because
      the guard handles it. Compile-check-discard keeps it.
    -?>
    safeDivide() as pure
      ->
        numerator as Integer
        divisor as Integer
      <- result as Integer: 0

      zero <- 0
      if divisor <> zero
        result: numerator / divisor

    <?-
      Test generator might try empty strings.
      The guard prevents accessing an empty string.
      Generated tests with empty input compile and exercise the guard.
    -?>
    safeFirstChar() as pure
      -> text as String
      <- found as Character: Character()

      if text?
        found :=? text.first()

    validateAge() as pure
      -> age as Integer
      <- valid as Boolean: false

      minimumAge <- 0
      maximumAge <- 150
      if age >= minimumAge and age <= maximumAge
        valid: true

  defines program

    CompileCheckDiscardDemo()
      stdout <- Stdout()

      ten <- 10
      three <- 3
      zero <- 0
      stdout.println(`10 / 3 = ${safeDivide(ten, three)}`)
      stdout.println(`10 / 0 = ${safeDivide(ten, zero)}`)

      greeting <- "Hello"
      emptyText <- String()
      stdout.println(`first of Hello: ${safeFirstChar(greeting)}`)
      stdout.println(`first of empty: ${safeFirstChar(emptyText)}`)

      for age in [0, 25, 150, -1, 200]
        stdout.println(`age ${age} valid: ${validateAge(age)}`)
Other ways to ask this
  • How does EK9 ensure generated tests are valid?
  • What is the compile-check-discard pattern in EK9 test generation?
  • Why does EK9 compile generated tests before outputting them?

Coming from another language?

Java: EvoSuite generates tests that may not compile or may have warnings. Python: Hypothesis generates inputs, not full test programs. Rust: proptest generates values, not complete test functions. Go: go test -fuzz generates corpus entries, not test functions. EK9: generates complete @Test programs validated by the full compiler pipeline, discarding any that fail any check.

Keywords: test, aware, check, guarantee, generation, filter, discard, compile, type, quality, oracle, valid