diff --git a/crates/mq-test/README.md b/crates/mq-test/README.md index c7d42bbc..aa3179a9 100644 --- a/crates/mq-test/README.md +++ b/crates/mq-test/README.md @@ -102,16 +102,6 @@ def verify_string_empty(): end ``` -```bash -$ mq-test example.mq -✓ add -✓ string_upcase -✓ verify_array_length -✓ verify_string_empty - -4 passed, 0 failed -``` - ## Development ### Running Tests diff --git a/crates/mq-test/src/runner.rs b/crates/mq-test/src/runner.rs index 1bb626a7..c5cbb25c 100644 --- a/crates/mq-test/src/runner.rs +++ b/crates/mq-test/src/runner.rs @@ -3,7 +3,6 @@ use miette::IntoDiagnostic; use mq_lang::{CstNodeKind, CstTrivia}; use std::fs; use std::path::{Path, PathBuf}; - /// Discovers and runs mq test functions from `.mq` files. /// /// A function is treated as a test if: @@ -76,9 +75,18 @@ impl TestRunner { /// - Its `leading_trivia` contains a comment whose text (trimmed) is `@test`. fn discover_test_functions(content: &str) -> Vec { let (nodes, _) = mq_lang::parse_recovery(content); + Self::discover_test_functions_in(&nodes) + } + + fn discover_test_functions_in(nodes: &[mq_lang::Shared]) -> Vec { let mut names = Vec::new(); - for node in &nodes { + for node in nodes { + if node.kind == CstNodeKind::Module { + names.extend(Self::discover_test_functions_in(&node.children)); + continue; + } + if node.kind != CstNodeKind::Def { continue; } @@ -149,6 +157,10 @@ mod tests { vec!["test_first", "annotated"] )] #[case("def helper():\n None\nend\n", vec![])] + #[case( + "module a:\n def test_first():\n None\nend\n\n# @test\ndef annotated():\n None\nend\nend\n", + vec!["test_first", "annotated"] + )] fn test_discover_test_functions(#[case] content: &str, #[case] expected: Vec<&str>) { let names = TestRunner::discover_test_functions(content); assert_eq!(names, expected);