What is the dev context and how does it relate to testing in EK9?
← Code Quality · Ref: Q767
EK9 enforces a strict compile-time boundary between test code and production code using the 'dev context' concept.
THE DEV CONTEXT
When you compile with -cd, -Cd, or run tests with -t, the compiler includes dev code (programs marked with @Test and all code they reach). When you compile with -c or -C (production builds), @Test programs and their assertions are stripped entirely.
ASSERT VS REQUIRE
- assert: Test-only. Validates expected outcomes. Only allowed in code reachable from @Test programs. Triggers E81012 if found in production code paths.
- require: Production-safe. Enforces preconditions. Works everywhere. Use this in production functions and methods.
THE CALL GRAPH ENFORCES THIS
EK9 performs call graph analysis from all program entry points. If a non-@Test program can reach code containing assert, the compiler raises E81012 (PRODUCTION_ASSERTION). If assert exists in code NOT reachable from any program (test or production), it raises E81011 (ORPHAN_ASSERTION).
WHY THIS MATTERS
1. assert has overhead (expression capture, stack traces) — not wanted in production
2. Mixing test and production validation indicates confused design intent
3. Production code should use require for preconditions, not test assertions
4. Stripping test code from production builds reduces binary size and attack surface
THIS EXAMPLE
The main file has the production program and functions using require. The companion dev file (QA0767_dev_tests.ek9) has the @Test programs using assert. The dev file is only compiled in dev builds (-cd, -t).
See Q155 for writing tests. See Q156 for assertions. See Q157 for running tests. See Q305 for require vs assert vs throw.
Example
defines module qa.codequality.devcontext defines function <?- This function uses 'require' for preconditions. It is called ONLY from the PRODUCTION program below. If assert were used instead of require, E81012 would trigger because the call graph shows it is reachable from non-@Test code. -?> validateInput() -> input as Integer <- valid as Boolean: false require input? require input > 0 valid: true <?- Helper for tests only — called exclusively from @Test programs in the companion dev file. -?> doubleValue() -> input as Integer <- result as Integer: input * 2 defines program <?- PRODUCTION PROGRAM — no @Test directive. Calls validateInput which uses require (correct). If validateInput used assert, E81012 would fire. -?> ProductionEntry() stdout <- Stdout() if validateInput(42) stdout.println("Input is valid")
Companion: QA0767_dev_tests.ek9
#!ek9 defines module qa.codequality.devcontext defines program //TEST PROGRAM — marked with @Test. //This program only exists in dev builds (-cd, -t). //It CAN use assert because it is a test program. @Test TestDoubleValue() stdout <- Stdout() result <- doubleValue(5) assert result == 10 result2 <- doubleValue(7) assert result2 == 14 stdout.println("doubleValue tests passed") //EOF
Common mistakes
E81015 — Using assert in a non-dev source file triggers E81015 TEST_CONSTRUCT_IN_NON_DEV_SOURCE. The assert keyword is only allowed in files within a dev/ directory or matching the QA####_dev_ naming convention. Use require for production preconditions. See ek9 -h E81015 for details.
Incorrect:
assert input? assert input > 0
Correct:
require input? require input > 0
Other ways to ask this
- Why can I only use assert in @Test programs?
- What is the difference between dev and production builds?
- How does EK9 separate test code from production code?
- What triggers E81012 production assertion?
- Why does EK9 restrict assert to dev context?
Coming from another language?
Java: assert works everywhere but disabled by default (-ea to enable), JUnit assertions are library methods callable from anywhere — no compile-time enforcement. Python: assert works everywhere, stripped with -O flag — no compile-time boundary. Rust: assert! works everywhere, debug_assert! stripped in release builds — but no call graph analysis to enforce boundaries. Go: no assert keyword, testing.T methods technically callable from non-test code. EK9: compile-time call graph analysis enforces that assert only appears in code reachable from @Test programs.
Keywords: test, assert, E81012, E81011, context, call-graph, require, @Test, compile, boundary, production, dev