How do I assert conditions in a test in EK9?

← Testing · Ref: Q156

EK9 provides assert for test assertions and require for production preconditions. Both are built-in keywords, not library functions.

ASSERT KEYWORD

Use assert in test programs to verify conditions:

  assert result == 5
  assert name?
  assert items.length() > 0

Assert is only allowed in test context (programs marked with @Test). It throws an exception if the condition is false.

REQUIRE FOR PRECONDITIONS

Use require in production code for preconditions:

  require name?
  require age > 0

Require works in any context and enforces that callers provide valid inputs.

ASSERT VS REQUIRE

assert is for test verification: 'did the code produce the right result?'
require is for defensive programming: 'are the inputs valid before proceeding?'
Assert is restricted to test programs. Require works everywhere.

OUTPUT-BASED TESTING AS ALTERNATIVE

For cleaner tests, print values to stdout and compare against expected_output.txt files. This avoids assert bytecode contamination in @BYTECODE directives and provides two independent validations: output verifies runtime behavior, directives verify code generation.

See Q155 for writing tests. See Q134 for try/catch. See Q135 for throwing exceptions. See Q204 for black-box testing. See Q209 for exception testing.

See Q305 for require vs assert vs throw. See Q306 for assertThrows. See Q307 for assertDoesNotThrow.

Example

#!ek9
defines module qa.testing.assertions

  defines function

    add() as pure
      ->
        a as Integer
        b as Integer
      <- rtn as Integer: a + b

    isPositive() as pure
      -> number as Integer
      <- rtn as Boolean: number > 0

  defines program

    // === ASSERT IN TESTS ===

    @Test
    BasicAssertTest()
      stdout <- Stdout()

      result <- add(2, 3)
      assert result == 5

      assert isPositive(42)

      name <- "EK9"
      assert name?

      stdout.println("All assertions passed")

    // === REQUIRE FOR PRECONDITIONS ===

    @Test
    RequireTest()
      stdout <- Stdout()

      count <- 10
      require count > 0

      text <- "Hello"
      require text?

      assert count == 10
      assert text == "Hello"
      stdout.println("All preconditions met")

    // === OUTPUT-BASED ALTERNATIVE ===

    @Test
    OutputBasedTest()
      stdout <- Stdout()

      // Print values and compare against expected_output.txt
      result <- add(10, 20)
      assert result == 30
      stdout.println("Result: " + $result)

Common mistakes

E07530 — The assert keyword requires a Boolean expression. Passing an Integer or String directly triggers E07530 — only compatible with Boolean type. Use a comparison operator to produce a Boolean. See ek9 -h E07530 for details.

Incorrect:

assert result

Correct:

assert result == 5

E50060 — Integer has no toString() method. Use the $ prefix operator for string conversion or string interpolation. See ek9 -h E50060 for details.

Incorrect:

stdout.println(result.toString())

Correct:

stdout.println("All assertions passed")

E50060 — Integer has no valueOf() method. Use the $ prefix operator or string concatenation with + for string conversion. See ek9 -h E50060 for details.

Incorrect:

stdout.println(result.valueOf())

Correct:

stdout.println("Result: " + $result)
Other ways to ask this
  • What assertion keywords does EK9 have?
  • How do I use assert and require in EK9?
  • What is the difference between assert and require in EK9?

Coming from another language?

Java: assertEquals/assertTrue from JUnit, assertThrows for exceptions. Python: assert statement or pytest.raises for exceptions. Rust: assert!, assert_eq!, assert_ne! macros. Go: t.Error() and t.Fatal() on testing.T. EK9: built-in assert keyword for tests, require keyword for preconditions, plus output-based testing as a cleaner alternative.

Keywords: assert, assertion, check, condition, precondition, require, test, throws, verify