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

generator: remove custom context #1886

Merged
merged 12 commits into from
Apr 2, 2024
12 changes: 1 addition & 11 deletions docs/CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -134,18 +134,10 @@ let expected = {% if test.expected is object -%}
{%- endif %};
```

If every test case needs to do some crunching of the inputs,
you can add utils functions at the top of the tera template.
See [`word-count`'s template][word-count-tmpl] for an example.
Comment on lines -137 to -139
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a piggy-back, I removed this recommendation because of reasons explained in #1824


Some exercises have multiple functions that need to be implemented
by the student and therefore tested.
The canonical data contains a field `property` in that case.
The template also has access to a value `fn_names`,
which is an array of functions found in `lib.rs`.
So, you can construct if-else-chains based on `test.property`
and render a different element of `fn_names` based on that.
See [`variable-length-quantity`'s template][var-len-q-tmpl] for an example.
You can construct if-else-chains based on `test.property` and render a different function based on that.

There is a custom tera fiter `to_hex`, which formats ints in hexadecimal.
Feel free to add your own in the crate `rust-tooling`.
Expand All @@ -157,8 +149,6 @@ It organizes the test cases in modules and dynamically detects which tests to pu
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
[tera-docs-filters]: https://keats.github.io/tera/docs/#filters

## Syllabus
Expand Down
6 changes: 3 additions & 3 deletions exercises/practice/acronym/.meta/test_template.tera
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
use acronym::*;

{% for test in cases %}
#[test]
{% if loop.index != 1 -%}
#[ignore]
{% endif -%}
fn {{ test.description | slugify | replace(from="-", to="_") }}() {
let input = {{ test.input.phrase | json_encode() }};
let output = {{ crate_name }}::{{ fn_names[0] }}(input);
let output = abbreviate(input);
let expected = {{ test.expected | json_encode() }};
assert_eq!(output, expected);
}
Expand Down
22 changes: 12 additions & 10 deletions exercises/practice/acronym/tests/acronym.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
use acronym::*;

#[test]
fn basic() {
let input = "Portable Network Graphics";
let output = acronym::abbreviate(input);
let output = abbreviate(input);
let expected = "PNG";
assert_eq!(output, expected);
}
Expand All @@ -10,7 +12,7 @@ fn basic() {
#[ignore]
fn lowercase_words() {
let input = "Ruby on Rails";
let output = acronym::abbreviate(input);
let output = abbreviate(input);
let expected = "ROR";
assert_eq!(output, expected);
}
Expand All @@ -19,7 +21,7 @@ fn lowercase_words() {
#[ignore]
fn punctuation() {
let input = "First In, First Out";
let output = acronym::abbreviate(input);
let output = abbreviate(input);
let expected = "FIFO";
assert_eq!(output, expected);
}
Expand All @@ -28,7 +30,7 @@ fn punctuation() {
#[ignore]
fn all_caps_word() {
let input = "GNU Image Manipulation Program";
let output = acronym::abbreviate(input);
let output = abbreviate(input);
let expected = "GIMP";
assert_eq!(output, expected);
}
Expand All @@ -37,7 +39,7 @@ fn all_caps_word() {
#[ignore]
fn punctuation_without_whitespace() {
let input = "Complementary metal-oxide semiconductor";
let output = acronym::abbreviate(input);
let output = abbreviate(input);
let expected = "CMOS";
assert_eq!(output, expected);
}
Expand All @@ -46,7 +48,7 @@ fn punctuation_without_whitespace() {
#[ignore]
fn very_long_abbreviation() {
let input = "Rolling On The Floor Laughing So Hard That My Dogs Came Over And Licked Me";
let output = acronym::abbreviate(input);
let output = abbreviate(input);
let expected = "ROTFLSHTMDCOALM";
assert_eq!(output, expected);
}
Expand All @@ -55,7 +57,7 @@ fn very_long_abbreviation() {
#[ignore]
fn consecutive_delimiters() {
let input = "Something - I made up from thin air";
let output = acronym::abbreviate(input);
let output = abbreviate(input);
let expected = "SIMUFTA";
assert_eq!(output, expected);
}
Expand All @@ -64,7 +66,7 @@ fn consecutive_delimiters() {
#[ignore]
fn apostrophes() {
let input = "Halley's Comet";
let output = acronym::abbreviate(input);
let output = abbreviate(input);
let expected = "HC";
assert_eq!(output, expected);
}
Expand All @@ -73,7 +75,7 @@ fn apostrophes() {
#[ignore]
fn underscore_emphasis() {
let input = "The Road _Not_ Taken";
let output = acronym::abbreviate(input);
let output = abbreviate(input);
let expected = "TRNT";
assert_eq!(output, expected);
}
Expand All @@ -82,7 +84,7 @@ fn underscore_emphasis() {
#[ignore]
fn camelcase() {
let input = "HyperText Markup Language";
let output = acronym::abbreviate(input);
let output = abbreviate(input);
let expected = "HTML";
assert_eq!(output, expected);
}
6 changes: 3 additions & 3 deletions exercises/practice/affine-cipher/.meta/test_template.tera
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
use affine_cipher::*;

use affine_cipher::AffineCipherError::NotCoprime;
{% for test in cases %}
#[test]
{% if loop.index != 1 -%}
#[ignore]
{% endif -%}
fn {{ test.description | slugify | replace(from="-", to="_") }}() {
let phrase = {{ test.input.phrase | json_encode() }};
let (a, b) = ({{ test.input.key.a }}, {{ test.input.key.b }});
let output = {{ crate_name }}::{{ test.property }}(phrase, a, b);
let output = {{ test.property }}(phrase, a, b);
let expected = {% if test.expected is object -%}
Err(NotCoprime({{ test.input.key.a }}))
{%- else -%}
Expand Down
34 changes: 18 additions & 16 deletions exercises/practice/affine-cipher/tests/affine-cipher.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
use affine_cipher::*;

use affine_cipher::AffineCipherError::NotCoprime;

#[test]
fn encode_yes() {
let phrase = "yes";
let (a, b) = (5, 7);
let output = affine_cipher::encode(phrase, a, b);
let output = encode(phrase, a, b);
let expected = Ok("xbt".into());
assert_eq!(output, expected);
}
Expand All @@ -14,7 +16,7 @@ fn encode_yes() {
fn encode_no() {
let phrase = "no";
let (a, b) = (15, 18);
let output = affine_cipher::encode(phrase, a, b);
let output = encode(phrase, a, b);
let expected = Ok("fu".into());
assert_eq!(output, expected);
}
Expand All @@ -24,7 +26,7 @@ fn encode_no() {
fn encode_omg() {
let phrase = "OMG";
let (a, b) = (21, 3);
let output = affine_cipher::encode(phrase, a, b);
let output = encode(phrase, a, b);
let expected = Ok("lvz".into());
assert_eq!(output, expected);
}
Expand All @@ -34,7 +36,7 @@ fn encode_omg() {
fn encode_o_m_g() {
let phrase = "O M G";
let (a, b) = (25, 47);
let output = affine_cipher::encode(phrase, a, b);
let output = encode(phrase, a, b);
let expected = Ok("hjp".into());
assert_eq!(output, expected);
}
Expand All @@ -44,7 +46,7 @@ fn encode_o_m_g() {
fn encode_mindblowingly() {
let phrase = "mindblowingly";
let (a, b) = (11, 15);
let output = affine_cipher::encode(phrase, a, b);
let output = encode(phrase, a, b);
let expected = Ok("rzcwa gnxzc dgt".into());
assert_eq!(output, expected);
}
Expand All @@ -54,7 +56,7 @@ fn encode_mindblowingly() {
fn encode_numbers() {
let phrase = "Testing,1 2 3, testing.";
let (a, b) = (3, 4);
let output = affine_cipher::encode(phrase, a, b);
let output = encode(phrase, a, b);
let expected = Ok("jqgjc rw123 jqgjc rw".into());
assert_eq!(output, expected);
}
Expand All @@ -64,7 +66,7 @@ fn encode_numbers() {
fn encode_deep_thought() {
let phrase = "Truth is fiction.";
let (a, b) = (5, 17);
let output = affine_cipher::encode(phrase, a, b);
let output = encode(phrase, a, b);
let expected = Ok("iynia fdqfb ifje".into());
assert_eq!(output, expected);
}
Expand All @@ -74,7 +76,7 @@ fn encode_deep_thought() {
fn encode_all_the_letters() {
let phrase = "The quick brown fox jumps over the lazy dog.";
let (a, b) = (17, 33);
let output = affine_cipher::encode(phrase, a, b);
let output = encode(phrase, a, b);
let expected = Ok("swxtj npvyk lruol iejdc blaxk swxmh qzglf".into());
assert_eq!(output, expected);
}
Expand All @@ -84,7 +86,7 @@ fn encode_all_the_letters() {
fn encode_with_a_not_coprime_to_m() {
let phrase = "This is a test.";
let (a, b) = (6, 17);
let output = affine_cipher::encode(phrase, a, b);
let output = encode(phrase, a, b);
let expected = Err(NotCoprime(6));
assert_eq!(output, expected);
}
Expand All @@ -94,7 +96,7 @@ fn encode_with_a_not_coprime_to_m() {
fn decode_exercism() {
let phrase = "tytgn fjr";
let (a, b) = (3, 7);
let output = affine_cipher::decode(phrase, a, b);
let output = decode(phrase, a, b);
let expected = Ok("exercism".into());
assert_eq!(output, expected);
}
Expand All @@ -104,7 +106,7 @@ fn decode_exercism() {
fn decode_a_sentence() {
let phrase = "qdwju nqcro muwhn odqun oppmd aunwd o";
let (a, b) = (19, 16);
let output = affine_cipher::decode(phrase, a, b);
let output = decode(phrase, a, b);
let expected = Ok("anobstacleisoftenasteppingstone".into());
assert_eq!(output, expected);
}
Expand All @@ -114,7 +116,7 @@ fn decode_a_sentence() {
fn decode_numbers() {
let phrase = "odpoz ub123 odpoz ub";
let (a, b) = (25, 7);
let output = affine_cipher::decode(phrase, a, b);
let output = decode(phrase, a, b);
let expected = Ok("testing123testing".into());
assert_eq!(output, expected);
}
Expand All @@ -124,7 +126,7 @@ fn decode_numbers() {
fn decode_all_the_letters() {
let phrase = "swxtj npvyk lruol iejdc blaxk swxmh qzglf";
let (a, b) = (17, 33);
let output = affine_cipher::decode(phrase, a, b);
let output = decode(phrase, a, b);
let expected = Ok("thequickbrownfoxjumpsoverthelazydog".into());
assert_eq!(output, expected);
}
Expand All @@ -134,7 +136,7 @@ fn decode_all_the_letters() {
fn decode_with_no_spaces_in_input() {
let phrase = "swxtjnpvyklruoliejdcblaxkswxmhqzglf";
let (a, b) = (17, 33);
let output = affine_cipher::decode(phrase, a, b);
let output = decode(phrase, a, b);
let expected = Ok("thequickbrownfoxjumpsoverthelazydog".into());
assert_eq!(output, expected);
}
Expand All @@ -144,7 +146,7 @@ fn decode_with_no_spaces_in_input() {
fn decode_with_too_many_spaces() {
let phrase = "vszzm cly yd cg qdp";
let (a, b) = (15, 16);
let output = affine_cipher::decode(phrase, a, b);
let output = decode(phrase, a, b);
let expected = Ok("jollygreengiant".into());
assert_eq!(output, expected);
}
Expand All @@ -154,7 +156,7 @@ fn decode_with_too_many_spaces() {
fn decode_with_a_not_coprime_to_m() {
let phrase = "Test";
let (a, b) = (13, 5);
let output = affine_cipher::decode(phrase, a, b);
let output = decode(phrase, a, b);
let expected = Err(NotCoprime(13));
assert_eq!(output, expected);
}
4 changes: 1 addition & 3 deletions exercises/practice/allergies/.meta/test_template.tera
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use {{ crate_name }}::*;
use allergies::*;

fn compare_allergy_vectors(expected: &[Allergen], actual: &[Allergen]) {
for element in expected {
Expand All @@ -16,9 +16,7 @@ fn compare_allergy_vectors(expected: &[Allergen], actual: &[Allergen]) {

{% for test in cases %}
#[test]
{% if loop.index != 1 -%}
#[ignore]
{% endif -%}
{%- if test.property == "allergicTo" %}
{# canonical data contains multiple cases named "allergic to everything" for different items #}
fn {{ test.description | slugify | replace(from="-", to="_") }}_{{ test.input.item }}() {
Expand Down
10 changes: 0 additions & 10 deletions exercises/practice/allergies/tests/allergies.rs
Original file line number Diff line number Diff line change
Expand Up @@ -335,7 +335,6 @@ fn allergic_to_everything_cats() {

#[test]
#[ignore]

fn no_allergies() {
let allergies = Allergies::new(0).allergies();
let expected = &[];
Expand All @@ -345,7 +344,6 @@ fn no_allergies() {

#[test]
#[ignore]

fn just_eggs() {
let allergies = Allergies::new(1).allergies();
let expected = &[Allergen::Eggs];
Expand All @@ -355,7 +353,6 @@ fn just_eggs() {

#[test]
#[ignore]

fn just_peanuts() {
let allergies = Allergies::new(2).allergies();
let expected = &[Allergen::Peanuts];
Expand All @@ -365,7 +362,6 @@ fn just_peanuts() {

#[test]
#[ignore]

fn just_strawberries() {
let allergies = Allergies::new(8).allergies();
let expected = &[Allergen::Strawberries];
Expand All @@ -375,7 +371,6 @@ fn just_strawberries() {

#[test]
#[ignore]

fn eggs_and_peanuts() {
let allergies = Allergies::new(3).allergies();
let expected = &[Allergen::Eggs, Allergen::Peanuts];
Expand All @@ -385,7 +380,6 @@ fn eggs_and_peanuts() {

#[test]
#[ignore]

fn more_than_eggs_but_not_peanuts() {
let allergies = Allergies::new(5).allergies();
let expected = &[Allergen::Eggs, Allergen::Shellfish];
Expand All @@ -395,7 +389,6 @@ fn more_than_eggs_but_not_peanuts() {

#[test]
#[ignore]

fn lots_of_stuff() {
let allergies = Allergies::new(248).allergies();
let expected = &[
Expand All @@ -411,7 +404,6 @@ fn lots_of_stuff() {

#[test]
#[ignore]

fn everything() {
let allergies = Allergies::new(255).allergies();
let expected = &[
Expand All @@ -430,7 +422,6 @@ fn everything() {

#[test]
#[ignore]

fn no_allergen_score_parts() {
let allergies = Allergies::new(509).allergies();
let expected = &[
Expand All @@ -448,7 +439,6 @@ fn no_allergen_score_parts() {

#[test]
#[ignore]

fn no_allergen_score_parts_without_highest_valid_score() {
let allergies = Allergies::new(257).allergies();
let expected = &[Allergen::Eggs];
Expand Down
Loading