Testing the semantic layer
Write tests that pin your metric definitions in place so future changes can't silently break the numbers.
Your metric definitions are now business-critical infrastructure. Treat them like it: test them. A test suite lets you refactor the compiler or tweak a metric and instantly know if any number moved.
What's worth testing
- Known totals. Total revenue is $743,772.80 for the seeded data. Pin it — if it ever changes unexpectedly, a definition drifted.
- Invariants. The sum of revenue across all channels must equal total revenue. Parts should sum to the whole.
- Refusals. An impossible metric×dimension combination (marketing spend by product category) should raise
SemanticError, not return data. - Ratios. AOV should equal revenue ÷ orders_count computed independently.
from semantic_layer import SemanticLayer, SemanticError
L = SemanticLayer()
def test_total_revenue():
assert L.query(["revenue"])["rows"][0]["revenue"] == 743772.8
def test_channels_sum_to_total():
total = L.query(["revenue"])["rows"][0]["revenue"]
by_channel = L.query(["revenue"], ["channel"])["rows"]
assert round(sum(r["revenue"] for r in by_channel), 2) == total
def test_impossible_combo_is_refused():
try:
L.query(["marketing_spend"], ["product_category"])
assert False, "should have refused"
except SemanticError:
passRunning the tests
pip install pytest
pytest test_semantic_layer.py # pytest auto-discovers every test_* function
# or, with no new installs — add a __main__ runner to the file, then:
python3 test_semantic_layer.pyFor the no-pytest route, the runner is one line at the bottom of the file: if __name__ == "__main__": test_total_revenue(); test_channels_sum_to_total(); test_impossible_combo_is_refused(). Plain asserts either way — and both commands assume your venv is active and you're in the starter-kit root, where semantic_layer/ is importable.
In Part 2 the agent will lean entirely on these metrics. If a definition silently breaks, every AI answer becomes wrong. A green test suite is your guarantee that the foundation under the agent is solid.
The 'parts sum to the whole' test is especially powerful — it catches fan-out, missing filters, and join bugs in one assertion, because all of those make the pieces stop adding up.