Skip to content

Commit 3a29c43

Browse files
authored
Fix filtering and command docs (#649)
## Introduced changes - Filtering now uses whole module tree path - Fixed `snforge` command docs ## Checklist - [x] Linked relevant issue - [x] Updated relevant documentation - [x] Added relevant tests - [x] Performed self-review of the code - [x] Added changes to `CHANGELOG.md`
1 parent 2e10edf commit 3a29c43

File tree

6 files changed

+83
-43
lines changed

6 files changed

+83
-43
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1313

1414
- `deploy_at` cheatcode
1515
- printing failures summary at the end of an execution
16+
- filtering tests now uses an absolute module tree path — it is possible to filter tests by module names, etc.
1617

1718
### Fixed
1819

crates/forge/src/lib.rs

Lines changed: 33 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -156,7 +156,7 @@ fn collect_tests_from_tree(
156156
)?;
157157

158158
let test_cases = if let Some(test_name_filter) = &runner_config.test_name_filter {
159-
filter_tests_by_name(test_name_filter, runner_config.exact_match, tests_configs)?
159+
filter_tests_by_name(test_name_filter, runner_config.exact_match, tests_configs)
160160
} else {
161161
tests_configs
162162
};
@@ -299,27 +299,18 @@ fn filter_tests_by_name(
299299
test_name_filter: &str,
300300
exact_match: bool,
301301
test_cases: Vec<TestCase>,
302-
) -> Result<Vec<TestCase>> {
302+
) -> Vec<TestCase> {
303303
let mut result = vec![];
304304
for test in test_cases {
305305
if exact_match {
306306
if test.name == test_name_filter {
307307
result.push(test);
308308
}
309-
} else if test_name_contains(test_name_filter, &test)? {
309+
} else if test.name.contains(test_name_filter) {
310310
result.push(test);
311311
}
312312
}
313-
Ok(result)
314-
}
315-
316-
fn test_name_contains(test_name_filter: &str, test: &TestCase) -> Result<bool> {
317-
let name = test
318-
.name
319-
.rsplit("::")
320-
.next()
321-
.context(format!("Failed to get test name from = {}", test.name))?;
322-
Ok(name.contains(test_name_filter))
313+
result
323314
}
324315

325316
#[cfg(test)]
@@ -372,7 +363,7 @@ mod tests {
372363
},
373364
];
374365

375-
let filtered = filter_tests_by_name("do", false, mocked_tests.clone()).unwrap();
366+
let filtered = filter_tests_by_name("do", false, mocked_tests.clone());
376367
assert_eq!(
377368
filtered,
378369
vec![TestCase {
@@ -382,7 +373,7 @@ mod tests {
382373
},]
383374
);
384375

385-
let filtered = filter_tests_by_name("run", false, mocked_tests.clone()).unwrap();
376+
let filtered = filter_tests_by_name("run", false, mocked_tests.clone());
386377
assert_eq!(
387378
filtered,
388379
vec![TestCase {
@@ -392,7 +383,7 @@ mod tests {
392383
},]
393384
);
394385

395-
let filtered = filter_tests_by_name("thing", false, mocked_tests.clone()).unwrap();
386+
let filtered = filter_tests_by_name("thing", false, mocked_tests.clone());
396387
assert_eq!(
397388
filtered,
398389
vec![
@@ -414,10 +405,10 @@ mod tests {
414405
]
415406
);
416407

417-
let filtered = filter_tests_by_name("nonexistent", false, mocked_tests.clone()).unwrap();
408+
let filtered = filter_tests_by_name("nonexistent", false, mocked_tests.clone());
418409
assert_eq!(filtered, vec![]);
419410

420-
let filtered = filter_tests_by_name("", false, mocked_tests).unwrap();
411+
let filtered = filter_tests_by_name("", false, mocked_tests);
421412
assert_eq!(
422413
filtered,
423414
vec![
@@ -441,7 +432,7 @@ mod tests {
441432
}
442433

443434
#[test]
444-
fn filtering_tests_only_uses_name() {
435+
fn filtering_tests_uses_whole_path() {
445436
let mocked_tests: Vec<TestCase> = vec![
446437
TestCase {
447438
name: "crate1::do_thing".to_string(),
@@ -460,8 +451,22 @@ mod tests {
460451
},
461452
];
462453

463-
let filtered = filter_tests_by_name("crate", false, mocked_tests).unwrap();
464-
assert_eq!(filtered, vec![]);
454+
let filtered = filter_tests_by_name("crate2::", false, mocked_tests);
455+
assert_eq!(
456+
filtered,
457+
vec![
458+
TestCase {
459+
name: "crate2::run_other_thing".to_string(),
460+
available_gas: None,
461+
expected_result: ExpectedTestResult::Success,
462+
},
463+
TestCase {
464+
name: "outer::crate2::run_other_thing".to_string(),
465+
available_gas: None,
466+
expected_result: ExpectedTestResult::Success,
467+
},
468+
]
469+
);
465470
}
466471

467472
#[test]
@@ -489,13 +494,13 @@ mod tests {
489494
},
490495
];
491496

492-
let filtered = filter_tests_by_name("", true, mocked_tests.clone()).unwrap();
497+
let filtered = filter_tests_by_name("", true, mocked_tests.clone());
493498
assert_eq!(filtered, vec![]);
494499

495-
let filtered = filter_tests_by_name("thing", true, mocked_tests.clone()).unwrap();
500+
let filtered = filter_tests_by_name("thing", true, mocked_tests.clone());
496501
assert_eq!(filtered, vec![]);
497502

498-
let filtered = filter_tests_by_name("do_thing", true, mocked_tests.clone()).unwrap();
503+
let filtered = filter_tests_by_name("do_thing", true, mocked_tests.clone());
499504
assert_eq!(
500505
filtered,
501506
vec![TestCase {
@@ -505,8 +510,7 @@ mod tests {
505510
},]
506511
);
507512

508-
let filtered =
509-
filter_tests_by_name("crate1::do_thing", true, mocked_tests.clone()).unwrap();
513+
let filtered = filter_tests_by_name("crate1::do_thing", true, mocked_tests.clone());
510514
assert_eq!(
511515
filtered,
512516
vec![TestCase {
@@ -516,12 +520,10 @@ mod tests {
516520
},]
517521
);
518522

519-
let filtered =
520-
filter_tests_by_name("crate3::run_other_thing", true, mocked_tests.clone()).unwrap();
523+
let filtered = filter_tests_by_name("crate3::run_other_thing", true, mocked_tests.clone());
521524
assert_eq!(filtered, vec![]);
522525

523-
let filtered =
524-
filter_tests_by_name("outer::crate3::run_other_thing", true, mocked_tests).unwrap();
526+
let filtered = filter_tests_by_name("outer::crate3::run_other_thing", true, mocked_tests);
525527
assert_eq!(
526528
filtered,
527529
vec![TestCase {
@@ -552,7 +554,7 @@ mod tests {
552554
},
553555
];
554556

555-
let result = filter_tests_by_name("thing", false, mocked_tests).unwrap();
557+
let result = filter_tests_by_name("thing", false, mocked_tests);
556558
assert_eq!(
557559
result,
558560
vec![

crates/forge/src/main.rs

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -25,15 +25,14 @@ static PREDEPLOYED_CONTRACTS: Dir = include_dir!("crates/cheatnet/predeployed-co
2525
#[command(version)]
2626
struct Args {
2727
/// Name used to filter tests
28-
test_name: Option<String>,
28+
test_filter: Option<String>,
2929
/// Use exact matches for `test_filter`
3030
#[arg(short, long)]
3131
exact: bool,
32-
/// Create a new forge project with <name> in current directory
33-
#[clap(long)]
32+
/// Create a new directory and forge project named <NAME>
33+
#[arg(long, value_name = "NAME")]
3434
init: Option<String>,
35-
36-
/// Stop test execution after first failed test
35+
/// Stop test execution after the first failed test
3736
#[arg(short = 'x', long)]
3837
exit_first: bool,
3938
}
@@ -94,7 +93,7 @@ fn main_execution() -> Result<bool> {
9493
let target_name = target_name_for_package(&scarb_metadata, package)?;
9594
let corelib_path = corelib_for_package(&scarb_metadata, package)?;
9695
let runner_config = RunnerConfig::new(
97-
args.test_name.clone(),
96+
args.test_filter.clone(),
9897
args.exact,
9998
args.exit_first,
10099
&forge_config,

crates/forge/tests/e2e/running.rs

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,31 @@ fn with_filter() {
168168
"#});
169169
}
170170

171+
#[test]
172+
fn with_filter_matching_module() {
173+
let temp = setup_package("simple_package");
174+
let snapbox = runner();
175+
176+
snapbox
177+
.current_dir(&temp)
178+
.arg("ext_function_test::")
179+
.assert()
180+
.success()
181+
.stdout_matches(indoc! {r#"
182+
[..]Compiling[..]
183+
[..]Finished[..]
184+
Collected 2 test(s) and 5 test file(s)
185+
Running 0 test(s) from simple_package package
186+
Running 0 test(s) from tests/contract.cairo
187+
Running 2 test(s) from tests/ext_function_test.cairo
188+
[PASS] ext_function_test::test_my_test
189+
[PASS] ext_function_test::test_simple
190+
Running 0 test(s) from tests/test_simple.cairo
191+
Running 0 test(s) from tests/without_prefix.cairo
192+
Tests: 2 passed, 0 failed, 0 skipped
193+
"#});
194+
}
195+
171196
#[test]
172197
fn with_exact_filter() {
173198
let temp = setup_package("simple_package");

docs/src/appendix/forge.md

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,28 @@
1-
# `snforge [test filter]`
1+
# `snforge`
22

33
Run forge in the current directory
44

5-
## `[test filter]`
5+
## `[TEST_FILTER]`
66

7-
Passing a test filter will only run tests with a name containing this filter.
7+
Passing a test filter will only run tests with an [absolute module tree path](https://book.cairo-lang.org/ch06-03-paths-for-referring-to-an-item-in-the-module-tree.html?highlight=path#paths-for-referring-to-an-item-in-the-module-tree)
8+
containing this filter.
89

9-
## `--exact`
10+
## `-e`, `--exact`
1011

1112
Will only run a test with a name exactly matching the test filter.
1213
Test filter must be a whole qualified test name e.g. `package_name::my_test` instead of just `my_test`.
1314

14-
## `--exit-first`
15+
## `--init <NAME>`
16+
17+
Create a new directory and forge project named `<NAME>`.
18+
19+
## `-x`, `--exit-first`
1520

1621
Stop executing tests after the first failed test.
22+
23+
## `-h`, `--help`
24+
Print help.
25+
26+
## `-V`, `--version`
27+
28+
Print version.

docs/src/testing/running-tests.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,8 @@ Tests: 3 passed, 0 failed, 0 skipped
1515
## Filtering Tests
1616

1717
You can pass a filter string after the `snforge` command to filter tests.
18-
By default, any test name matching the filter will be run.
18+
By default, any test with an [absolute module tree path](https://book.cairo-lang.org/ch06-03-paths-for-referring-to-an-item-in-the-module-tree.html?highlight=path#paths-for-referring-to-an-item-in-the-module-tree)
19+
matching the filter will be run.
1920

2021
```shell
2122
$ snforge calling

0 commit comments

Comments
 (0)