Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Sync triangle with problem-specifications #1816

Merged
merged 5 commits into from
Dec 12, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions docs/CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,10 @@ Feel free to add your own in the crate `rust-tooling`.
Custom filters added there will be available to all templates.
How to create such custom filters is documented int he [tera docs][tera-docs-filters].

For a rather complicated example, check out the test template of `triangle`.
It organizes the test cases in modules and dynamically detects which tests to put behind feature gates.
That exercise also reimplements some test cases from upstream in `additional-tests.json`, in order to add more information to them necessary for generating good tests.

[tera-docs]: https://keats.github.io/tera/docs/#templates
[word-count-tmpl]: /exercises/practice/word-count/.meta/test_template.tera
[var-len-q-tmpl]: /exercises/practice/variable-length-quantity/.meta/test_template.tera
Expand Down
52 changes: 52 additions & 0 deletions exercises/practice/triangle/.meta/additional-tests.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
[
{
"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
}
]
2 changes: 1 addition & 1 deletion exercises/practice/triangle/.meta/example.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ where
}

pub fn is_isosceles(&self) -> bool {
self.count_distinct_pairs() == 2
self.count_distinct_pairs() <= 2
}

pub fn is_scalene(&self) -> bool {
Expand Down
85 changes: 85 additions & 0 deletions exercises/practice/triangle/.meta/test_template.tera
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
mod equilateral {
use triangle::Triangle;
{% for test in cases %}
{% if test.property != "equilateral" %}{% continue %}{% endif %}

#[test]
{% if loop.index != 1 -%}
#[ignore]
{% endif -%}
{% if test.description is containing("float") %}
#[cfg(feature = "generic")]
{% endif -%}
fn {{ test.description | slugify | replace(from="-", to="_") }}() {
let input = {{ test.input.sides | json_encode() }};
let output = Triangle::build(input).unwrap();
{%- if test.expected %}
assert!(output.is_equilateral());
{% else %}
assert!(!output.is_equilateral());
{% endif -%}
}
{% endfor -%}
}

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

#[test]
#[ignore]
{% if test.scenarios and test.scenarios is containing("floating-point") %}
#[cfg(feature = "generic")]
{% endif -%}
fn {{ test.description | slugify | replace(from="-", to="_") }}() {
let input = {{ test.input.sides | json_encode() }};
let output = Triangle::build(input).unwrap();
{%- if test.expected %}
assert!(output.is_isosceles());
{% else %}
assert!(!output.is_isosceles());
{% endif -%}
}
{% endfor -%}
}

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

#[test]
#[ignore]
{% if test.scenarios and test.scenarios is containing("floating-point") %}
#[cfg(feature = "generic")]
{% endif -%}
fn {{ test.description | slugify | replace(from="-", to="_") }}() {
let input = {{ test.input.sides | json_encode() }};
let output = Triangle::build(input).unwrap();
{%- if test.expected %}
assert!(output.is_scalene());
{% else %}
assert!(!output.is_scalene());
{% endif -%}
}
{% endfor -%}
}

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

#[test]
#[ignore]
{% if test.scenarios and test.scenarios is containing("floating-point") %}
#[cfg(feature = "generic")]
{% endif -%}
fn {{ test.description | slugify | replace(from="-", to="_") }}() {
let input = {{ test.input.sides | json_encode() }};
let output = Triangle::build(input);
assert!(output.is_none());
}
{% endfor -%}
}
111 changes: 108 additions & 3 deletions exercises/practice/triangle/.meta/tests.toml
Original file line number Diff line number Diff line change
@@ -1,3 +1,108 @@
# This is an auto-generated file. Regular comments will be removed when this
# file is regenerated. Regenerating will not touch any manually added keys,
# so comments can be added in a "comment" key.
# This is an auto-generated file.
#
# Regenerating this file via `configlet sync` will:
# - Recreate every `description` key/value pair
# - Recreate every `reimplements` key/value pair, where they exist in problem-specifications
# - Remove any `include = true` key/value pair (an omitted `include` key implies inclusion)
# - Preserve any other key/value pair
#
# As user-added comments (using the # character) will be removed when this file
# is regenerated, comments can be added via a `comment` key.

[8b2c43ac-7257-43f9-b552-7631a91988af]
description = "equilateral triangle -> all sides are equal"

[33eb6f87-0498-4ccf-9573-7f8c3ce92b7b]
description = "equilateral triangle -> any side is unequal"

[c6585b7d-a8c0-4ad8-8a34-e21d36f7ad87]
description = "equilateral triangle -> no sides are equal"

[16e8ceb0-eadb-46d1-b892-c50327479251]
description = "equilateral triangle -> all zero sides is not a triangle"
include = false
comment = """
This is testing an invalid triangle, which we chose to implement
using an option. The problem specifications make it hard to detect
invalid triangles. We therefore skip this test and reimplement it
in .meta/additional-tests.json with the custom property "invalid".
"""

[3022f537-b8e5-4cc1-8f12-fd775827a00c]
description = "equilateral triangle -> sides may be floats"

[cbc612dc-d75a-4c1c-87fc-e2d5edd70b71]
description = "isosceles triangle -> last two sides are equal"

[e388ce93-f25e-4daf-b977-4b7ede992217]
description = "isosceles triangle -> first two sides are equal"

[d2080b79-4523-4c3f-9d42-2da6e81ab30f]
description = "isosceles triangle -> first and last sides are equal"

[8d71e185-2bd7-4841-b7e1-71689a5491d8]
description = "isosceles triangle -> equilateral triangles are also isosceles"

[840ed5f8-366f-43c5-ac69-8f05e6f10bbb]
description = "isosceles triangle -> no sides are equal"

[2eba0cfb-6c65-4c40-8146-30b608905eae]
description = "isosceles triangle -> first triangle inequality violation"
include = false
comment = """
This is testing an invalid triangle, which we chose to implement
using an option. The problem specifications make it hard to detect
invalid triangles. We therefore skip this test and reimplement it
in .meta/additional-tests.json with the custom property "invalid".
"""

[278469cb-ac6b-41f0-81d4-66d9b828f8ac]
description = "isosceles triangle -> second triangle inequality violation"
include = false
comment = """
This is testing an invalid triangle, which we chose to implement
using an option. The problem specifications make it hard to detect
invalid triangles. We therefore skip this test and reimplement it
in .meta/additional-tests.json with the custom property "invalid".
"""

[90efb0c7-72bb-4514-b320-3a3892e278ff]
description = "isosceles triangle -> third triangle inequality violation"
include = false
comment = """
This is testing an invalid triangle, which we chose to implement
using an option. The problem specifications make it hard to detect
invalid triangles. We therefore skip this test and reimplement it
in .meta/additional-tests.json with the custom property "invalid".
"""

[adb4ee20-532f-43dc-8d31-e9271b7ef2bc]
description = "isosceles triangle -> sides may be floats"

[e8b5f09c-ec2e-47c1-abec-f35095733afb]
description = "scalene triangle -> no sides are equal"

[2510001f-b44d-4d18-9872-2303e7977dc1]
description = "scalene triangle -> all sides are equal"

[c6e15a92-90d9-4fb3-90a2-eef64f8d3e1e]
description = "scalene triangle -> first and second sides are equal"

[3da23a91-a166-419a-9abf-baf4868fd985]
description = "scalene triangle -> first and third sides are equal"

[b6a75d98-1fef-4c42-8e9a-9db854ba0a4d]
description = "scalene triangle -> second and third sides are equal"

[70ad5154-0033-48b7-af2c-b8d739cd9fdc]
description = "scalene triangle -> may not violate triangle inequality"
include = false
comment = """
This is testing an invalid triangle, which we chose to implement
using an option. The problem specifications make it hard to detect
invalid triangles. We therefore skip this test and reimplement it
in .meta/additional-tests.json with the custom property "invalid".
"""

[26d9d59d-f8f1-40d3-ad58-ae4d54123d7d]
description = "scalene triangle -> sides may be floats"
Loading