Skip to content

Commit

Permalink
generator: retain nested test case structure (#1889)
Browse files Browse the repository at this point in the history
Previously, the generator flattened any nesting of test cases from
problem-specifications. This worked alright for medium-complexity
exercises. However, it makes writing a functional test template harder
in the general case. An example is the exercise `forth`, which has test
cases with _the same description_ across different test groups.
Flattening the groups leads to tests with the same name being generated.
Preserving the structure makes it possible to organize the tests into
one module per test group, solving the naming conflicts.
  • Loading branch information
senekor authored Apr 2, 2024
1 parent c341cc1 commit e318d66
Show file tree
Hide file tree
Showing 15 changed files with 144 additions and 114 deletions.
5 changes: 4 additions & 1 deletion exercises/practice/affine-cipher/.meta/test_template.tera
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
use affine_cipher::*;

use affine_cipher::AffineCipherError::NotCoprime;
{% for test in cases %}

{% for test_group in cases %}
{% for test in test_group.cases %}
#[test]
#[ignore]
fn {{ test.description | snake_case }}() {
Expand All @@ -16,3 +18,4 @@ fn {{ test.description | snake_case }}() {
assert_eq!(output, expected);
}
{% endfor -%}
{% endfor -%}
4 changes: 3 additions & 1 deletion exercises/practice/allergies/.meta/test_template.tera
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@ fn compare_allergy_vectors(expected: &[Allergen], actual: &[Allergen]) {
}
}

{% for test in cases %}
{% for test_group in cases %}
{% for test in test_group.cases %}
#[test]
#[ignore]
{%- if test.property == "allergicTo" %}
Expand All @@ -39,3 +40,4 @@ fn {{ test.description | snake_case }}() {
{% endif -%}
}
{% endfor -%}
{% endfor -%}
5 changes: 4 additions & 1 deletion exercises/practice/custom-set/.meta/test_template.tera
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
use custom_set::CustomSet;
{% for test in cases %}

{% for test_group in cases %}
{% for test in test_group.cases %}
#[test]
#[ignore]
fn {{ test.description | snake_case }}() {
Expand Down Expand Up @@ -56,3 +58,4 @@ fn {{ test.description | snake_case }}() {
{%- endif %}
}
{% endfor -%}
{% endfor -%}
4 changes: 3 additions & 1 deletion exercises/practice/perfect-numbers/.meta/test_template.tera
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use perfect_numbers::*;

{% for test in cases %}
{% for test_group in cases %}
{% for test in test_group.cases %}
#[test]
#[ignore]
fn {{ test.description | snake_case }}() {
Expand All @@ -14,3 +15,4 @@ fn {{ test.description | snake_case }}() {
{% endif -%}
}
{% endfor -%}
{% endfor -%}
4 changes: 3 additions & 1 deletion exercises/practice/pig-latin/.meta/test_template.tera
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use pig_latin::*;

{% for test in cases %}
{% for test_group in cases %}
{% for test in test_group.cases %}
#[test]
#[ignore]
fn {{ test.description | snake_case }}() {
Expand All @@ -10,3 +11,4 @@ fn {{ test.description | snake_case }}() {
assert_eq!(output, expected);
}
{% endfor -%}
{% endfor -%}
4 changes: 3 additions & 1 deletion exercises/practice/queen-attack/.meta/test_template.tera
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use queen_attack::*;

{% for test in cases %}
{% for test_group in cases %}
{% for test in test_group.cases %}
#[test]
#[ignore]
fn {{ test.description | snake_case }}() {
Expand All @@ -22,3 +23,4 @@ fn {{ test.description | snake_case }}() {
{% endif %}
}
{% endfor -%}
{% endfor -%}
29 changes: 17 additions & 12 deletions exercises/practice/rail-fence-cipher/.meta/additional-tests.json
Original file line number Diff line number Diff line change
@@ -1,16 +1,21 @@
[
{
"uuid": "46dc5c50-5538-401d-93a5-41102680d068",
"description": "encode wide characters",
"comments": [
"Unicode tests are not suitable to be upstreamed.",
"Handling unicode is tedious in many languages."
],
"property": "encode",
"input": {
"msg": "古池蛙飛び込む水の音",
"rails": 3
},
"expected": "古びの池飛込水音蛙む"
"description": "unicode",
"cases": [
{
"uuid": "46dc5c50-5538-401d-93a5-41102680d068",
"description": "encode wide characters",
"comments": [
"Unicode tests are not suitable to be upstreamed.",
"Handling unicode is tedious in many languages."
],
"property": "encode",
"input": {
"msg": "古池蛙飛び込む水の音",
"rails": 3
},
"expected": "古びの池飛込水音蛙む"
}
]
}
]
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
use rail_fence_cipher::RailFence;
{% for test in cases %}

{% for test_group in cases %}
{% for test in test_group.cases %}
#[test]
#[ignore]
fn {{ test.description | snake_case }}() {
Expand All @@ -15,3 +17,4 @@ fn {{ test.description | snake_case }}() {
assert_eq!(output, expected);
}
{% endfor -%}
{% endfor -%}
4 changes: 3 additions & 1 deletion exercises/practice/robot-simulator/.meta/test_template.tera
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use robot_simulator::*;

{% for test in cases %}
{% for test_group in cases %}
{% for test in test_group.cases %}
#[test]
#[ignore]
fn {{ test.description | snake_case }}() {
Expand All @@ -26,3 +27,4 @@ fn {{ test.description | snake_case }}() {
assert_eq!(robot_end.direction(), &Direction::{{ test.expected.direction | title }});
}
{% endfor -%}
{% endfor -%}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use run_length_encoding as rle;

{% for test in cases %}
{% for test_group in cases %}
{% for test in test_group.cases %}
#[test]
#[ignore]
fn {{ test.property }}_{{ test.description | snake_case }}() {
Expand All @@ -14,3 +15,4 @@ fn {{ test.property }}_{{ test.description | snake_case }}() {
assert_eq!(output, expected);
}
{% endfor -%}
{% endfor -%}
103 changes: 54 additions & 49 deletions exercises/practice/triangle/.meta/additional-tests.json
Original file line number Diff line number Diff line change
@@ -1,52 +1,57 @@
[
{
"uuid": "3ddc03ad-4066-41b0-8ba2-1b0ce0146064",
"description": "all zero sides is not a triangle",
"comments": ["reimplements 16e8ceb0-eadb-46d1-b892-c50327479251"],
"property": "invalid",
"input": {
"sides": [0, 0, 0]
},
"expected": false
},
{
"uuid": "3ddc03ad-4066-41b0-8ba2-1b0ce0146064",
"description": "first triangle inequality violation",
"comments": ["reimplements 2eba0cfb-6c65-4c40-8146-30b608905eae"],
"property": "invalid",
"input": {
"sides": [1, 1, 3]
},
"expected": false
},
{
"uuid": "3ddc03ad-4066-41b0-8ba2-1b0ce0146064",
"description": "second triangle inequality violation",
"comments": ["reimplements 278469cb-ac6b-41f0-81d4-66d9b828f8ac"],
"property": "invalid",
"input": {
"sides": [1, 3, 1]
},
"expected": false
},
{
"uuid": "3ddc03ad-4066-41b0-8ba2-1b0ce0146064",
"description": "third triangle inequality violation",
"comments": ["reimplements 90efb0c7-72bb-4514-b320-3a3892e278ff"],
"property": "invalid",
"input": {
"sides": [3, 1, 1]
},
"expected": false
},
{
"uuid": "3ddc03ad-4066-41b0-8ba2-1b0ce0146064",
"description": "may not violate triangle inequality",
"comments": ["reimplements 70ad5154-0033-48b7-af2c-b8d739cd9fdc"],
"property": "invalid",
"input": {
"sides": [7, 3, 2]
},
"expected": false
"description": "invalid triangle",
"cases": [
{
"uuid": "3ddc03ad-4066-41b0-8ba2-1b0ce0146064",
"description": "all zero sides is not a triangle",
"comments": ["reimplements 16e8ceb0-eadb-46d1-b892-c50327479251"],
"property": "invalid",
"input": {
"sides": [0, 0, 0]
},
"expected": false
},
{
"uuid": "3ddc03ad-4066-41b0-8ba2-1b0ce0146064",
"description": "first triangle inequality violation",
"comments": ["reimplements 2eba0cfb-6c65-4c40-8146-30b608905eae"],
"property": "invalid",
"input": {
"sides": [1, 1, 3]
},
"expected": false
},
{
"uuid": "3ddc03ad-4066-41b0-8ba2-1b0ce0146064",
"description": "second triangle inequality violation",
"comments": ["reimplements 278469cb-ac6b-41f0-81d4-66d9b828f8ac"],
"property": "invalid",
"input": {
"sides": [1, 3, 1]
},
"expected": false
},
{
"uuid": "3ddc03ad-4066-41b0-8ba2-1b0ce0146064",
"description": "third triangle inequality violation",
"comments": ["reimplements 90efb0c7-72bb-4514-b320-3a3892e278ff"],
"property": "invalid",
"input": {
"sides": [3, 1, 1]
},
"expected": false
},
{
"uuid": "3ddc03ad-4066-41b0-8ba2-1b0ce0146064",
"description": "may not violate triangle inequality",
"comments": ["reimplements 70ad5154-0033-48b7-af2c-b8d739cd9fdc"],
"property": "invalid",
"input": {
"sides": [7, 3, 2]
},
"expected": false
}
]
}
]
]
39 changes: 13 additions & 26 deletions exercises/practice/triangle/.meta/test_template.tera
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
mod equilateral {
use triangle::Triangle;
{% for test in cases %}
{% if test.property != "equilateral" %}{% continue %}{% endif %}
{% for test_group in cases %}
mod {{ test_group.description | split(pat=" ") | first }} {
use triangle::Triangle;

{% for test in test_group.cases %}

{% if test.property == "equilateral" %}
#[test]
#[ignore]
{% if test.description is containing("float") %}
Expand All @@ -17,14 +19,8 @@ fn {{ test.description | snake_case }}() {
assert!(!output.is_equilateral());
{% endif -%}
}
{% endfor -%}
}

mod isosceles {
use triangle::Triangle;
{% for test in cases %}
{% if test.property != "isosceles" %}{% continue %}{% endif %}

{% elif test.property == "isosceles" %}
#[test]
#[ignore]
{% if test.scenarios and test.scenarios is containing("floating-point") %}
Expand All @@ -39,14 +35,8 @@ fn {{ test.description | snake_case }}() {
assert!(!output.is_isosceles());
{% endif -%}
}
{% endfor -%}
}

mod scalene {
use triangle::Triangle;
{% for test in cases %}
{% if test.property != "scalene" %}{% continue %}{% endif %}

{% elif test.property == "scalene" %}
#[test]
#[ignore]
{% if test.scenarios and test.scenarios is containing("floating-point") %}
Expand All @@ -61,14 +51,8 @@ fn {{ test.description | snake_case }}() {
assert!(!output.is_scalene());
{% endif -%}
}
{% endfor -%}
}

mod invalid {
use triangle::Triangle;
{% for test in cases %}
{% if test.property != "invalid" %}{% continue %}{% endif %}

{% elif test.property == "invalid" %}
#[test]
#[ignore]
{% if test.scenarios and test.scenarios is containing("floating-point") %}
Expand All @@ -79,5 +63,8 @@ fn {{ test.description | snake_case }}() {
let output = Triangle::build(input);
assert!(output.is_none());
}
{% endfor -%}

{% endif %}
{% endfor %}
}
{% endfor %}
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
use variable_length_quantity as vlq;
{% for test in cases %}

{% for test_group in cases %}
{% for test in test_group.cases %}
#[test]
#[ignore]
fn {{ test.description | snake_case }}() {
Expand Down Expand Up @@ -29,3 +31,4 @@ fn {{ test.description | snake_case }}() {
assert_eq!(output, expected);
}
{% endfor -%}
{% endfor -%}
22 changes: 15 additions & 7 deletions rust-tooling/ci-tests/tests/additional_tests_are_documented.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
use std::path::Path;

use glob::glob;
use models::problem_spec::SingleTestCase;
use models::problem_spec::TestCase;
use utils::fs::cd_into_repo_root;

#[test]
Expand All @@ -9,14 +11,20 @@ fn additional_tests_are_documented() {
let path = entry.unwrap();
let f = std::fs::File::open(&path).unwrap();
let reader = std::io::BufReader::new(f);
let test_cases: Vec<SingleTestCase> = serde_json::from_reader(reader).unwrap();
let test_cases: Vec<TestCase> = serde_json::from_reader(reader).unwrap();

fn rec(case: TestCase, path: &Path) {
match case {
TestCase::Single { case } => assert!(
!case.comments.unwrap_or_default().is_empty(),
"missing documentation for additional tests in {}",
path.display()
),
TestCase::Group { cases, .. } => cases.into_iter().for_each(|c| rec(c, path)),
}
}
for case in test_cases {
assert!(
!case.comments.unwrap_or_default().is_empty(),
"missing documentation for additional tests in {}",
path.display()
);
rec(case, &path);
}
}
}
Loading

0 comments on commit e318d66

Please sign in to comment.