From d05762747d7d63c094edea57cede756a6bbde1c6 Mon Sep 17 00:00:00 2001 From: Remo Senekowitsch Date: Thu, 15 Aug 2024 22:00:41 +0200 Subject: [PATCH] grade-school: sync --- .../grade-school/.meta/additional-tests.json | 62 +++++++++++ .../practice/grade-school/.meta/example.rs | 7 ++ .../grade-school/.meta/test_template.tera | 46 ++++++++ .../practice/grade-school/.meta/tests.toml | 89 ++++++++++++++- .../grade-school/tests/grade-school.rs | 101 ++++++++++-------- 5 files changed, 258 insertions(+), 47 deletions(-) create mode 100644 exercises/practice/grade-school/.meta/additional-tests.json create mode 100644 exercises/practice/grade-school/.meta/test_template.tera diff --git a/exercises/practice/grade-school/.meta/additional-tests.json b/exercises/practice/grade-school/.meta/additional-tests.json new file mode 100644 index 000000000..c4c2c3ace --- /dev/null +++ b/exercises/practice/grade-school/.meta/additional-tests.json @@ -0,0 +1,62 @@ +[ + { + "uuid": "93f3415a-28f4-40e9-9df6-9d61bef26108", + "description": "grades_for_empty_school", + "comments": [ + "The original exercise design contains a `grades` method", + "which should not go untested." + ], + "property": "grades", + "input": { + "students": [] + }, + "expected": [] + }, + { + "uuid": "93f3415a-28f4-40e9-9df6-9d61bef26108", + "description": "grades_for_one_student", + "comments": [ + "The original exercise design contains a `grades` method", + "which should not go untested." + ], + "property": "grades", + "input": { + "students": [["Aimee", 2]] + }, + "expected": [2] + }, + { + "uuid": "93f3415a-28f4-40e9-9df6-9d61bef26108", + "description": "grades_for_several_students_are_sorted", + "comments": [ + "The original exercise design contains a `grades` method", + "which should not go untested." + ], + "property": "grades", + "input": { + "students": [ + ["Aimee", 2], + ["Logan", 7], + ["Blair", 4] + ] + }, + "expected": [2, 4, 7] + }, + { + "uuid": "93f3415a-28f4-40e9-9df6-9d61bef26108", + "description": "grades_when_several_students_have_the_same_grade", + "comments": [ + "The original exercise design contains a `grades` method", + "which should not go untested." + ], + "property": "grades", + "input": { + "students": [ + ["Aimee", 2], + ["Logan", 2], + ["Blair", 2] + ] + }, + "expected": [2] + } +] diff --git a/exercises/practice/grade-school/.meta/example.rs b/exercises/practice/grade-school/.meta/example.rs index 187535581..cacd65fa3 100644 --- a/exercises/practice/grade-school/.meta/example.rs +++ b/exercises/practice/grade-school/.meta/example.rs @@ -12,6 +12,13 @@ impl School { } pub fn add(&mut self, grade: u32, student: &str) { + if self + .grades + .iter() + .any(|(_, students)| students.iter().any(|s| s == student)) + { + return; // don't add duplicate student + } let entry = self.grades.entry(grade).or_default(); entry.push(student.to_string()); entry.sort_unstable(); diff --git a/exercises/practice/grade-school/.meta/test_template.tera b/exercises/practice/grade-school/.meta/test_template.tera new file mode 100644 index 000000000..c05d12f59 --- /dev/null +++ b/exercises/practice/grade-school/.meta/test_template.tera @@ -0,0 +1,46 @@ +use grade_school::*; + +{% for test in cases %} + +{% if test.property == "roster" %} + {# + The original exercise design does not include a method for getting + the roster. Excluding these tests doesn't seem too bad, it would be + difficult to implement this property incorrectly while getting the other + ones right. + #} + {% continue %} +{% endif%} +{% if test.property == "add" %} + {# + The original exercise design doesn't define the add method as fallible. + #} + {% continue %} +{% endif%} + +#[test] +#[ignore] +fn {{ test.description | make_ident }}() { + let {% if test.input.students | length > 0 %} + mut + {% endif %} s = School::new(); + {% for student in test.input.students -%} + s.add({{ student.1 }}, {{ student.0 | json_encode() }}); + {% endfor -%} + {% if test.property == "grade" -%} + assert_eq!( + s.grade({{ test.input.desiredGrade }}), + {% if test.expected | length == 0 -%} + Vec::::new() + {% else -%} + vec!{{ test.expected | json_encode() }} + {% endif -%} + ) + {% elif test.property == "grades" -%} + assert_eq!( + s.grades(), + vec!{{ test.expected | json_encode() }} + ) + {% endif -%} +} +{% endfor -%} diff --git a/exercises/practice/grade-school/.meta/tests.toml b/exercises/practice/grade-school/.meta/tests.toml index be690e975..50c9e2e59 100644 --- a/exercises/practice/grade-school/.meta/tests.toml +++ b/exercises/practice/grade-school/.meta/tests.toml @@ -1,3 +1,86 @@ -# 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. + +[a3f0fb58-f240-4723-8ddc-e644666b85cc] +description = "Roster is empty when no student is added" + +[9337267f-7793-4b90-9b4a-8e3978408824] +description = "Add a student" + +[6d0a30e4-1b4e-472e-8e20-c41702125667] +description = "Student is added to the roster" + +[73c3ca75-0c16-40d7-82f5-ed8fe17a8e4a] +description = "Adding multiple students in the same grade in the roster" + +[233be705-dd58-4968-889d-fb3c7954c9cc] +description = "Multiple students in the same grade are added to the roster" + +[87c871c1-6bde-4413-9c44-73d59a259d83] +description = "Cannot add student to same grade in the roster more than once" + +[c125dab7-2a53-492f-a99a-56ad511940d8] +description = "A student can't be in two different grades" +include = false + +[a0c7b9b8-0e89-47f8-8b4a-c50f885e79d1] +description = "A student can only be added to the same grade in the roster once" +include = false +reimplements = "c125dab7-2a53-492f-a99a-56ad511940d8" + +[d7982c4f-1602-49f6-a651-620f2614243a] +description = "Student not added to same grade in the roster more than once" +reimplements = "a0c7b9b8-0e89-47f8-8b4a-c50f885e79d1" + +[e70d5d8f-43a9-41fd-94a4-1ea0fa338056] +description = "Adding students in multiple grades" + +[75a51579-d1d7-407c-a2f8-2166e984e8ab] +description = "Students in multiple grades are added to the roster" + +[7df542f1-57ce-433c-b249-ff77028ec479] +description = "Cannot add same student to multiple grades in the roster" + +[6a03b61e-1211-4783-a3cc-fc7f773fba3f] +description = "A student cannot be added to more than one grade in the sorted roster" +include = false +reimplements = "c125dab7-2a53-492f-a99a-56ad511940d8" + +[c7ec1c5e-9ab7-4d3b-be5c-29f2f7a237c5] +description = "Student not added to multiple grades in the roster" +reimplements = "6a03b61e-1211-4783-a3cc-fc7f773fba3f" + +[d9af4f19-1ba1-48e7-94d0-dabda4e5aba6] +description = "Students are sorted by grades in the roster" + +[d9fb5bea-f5aa-4524-9d61-c158d8906807] +description = "Students are sorted by name in the roster" + +[180a8ff9-5b94-43fc-9db1-d46b4a8c93b6] +description = "Students are sorted by grades and then by name in the roster" + +[5e67aa3c-a3c6-4407-a183-d8fe59cd1630] +description = "Grade is empty if no students in the roster" + +[1e0cf06b-26e0-4526-af2d-a2e2df6a51d6] +description = "Grade is empty if no students in that grade" + +[2bfc697c-adf2-4b65-8d0f-c46e085f796e] +description = "Student not added to same grade more than once" + +[66c8e141-68ab-4a04-a15a-c28bc07fe6b9] +description = "Student not added to multiple grades" + +[c9c1fc2f-42e0-4d2c-b361-99271f03eda7] +description = "Student not added to other grade for multiple grades" + +[1bfbcef1-e4a3-49e8-8d22-f6f9f386187e] +description = "Students are sorted by name in a grade" diff --git a/exercises/practice/grade-school/tests/grade-school.rs b/exercises/practice/grade-school/tests/grade-school.rs index 3d8a2d51b..d2b1dde81 100644 --- a/exercises/practice/grade-school/tests/grade-school.rs +++ b/exercises/practice/grade-school/tests/grade-school.rs @@ -1,83 +1,96 @@ -use grade_school as school; +use grade_school::*; -fn to_owned(v: &[&str]) -> Vec { - v.iter().map(|s| s.to_string()).collect() +#[test] +fn grade_is_empty_if_no_students_in_the_roster() { + let s = School::new(); + assert_eq!(s.grade(1), Vec::::new()) } #[test] -fn grades_for_empty_school() { - let s = school::School::new(); - assert_eq!(s.grades(), vec![]); +#[ignore] +fn grade_is_empty_if_no_students_in_that_grade() { + let mut s = School::new(); + s.add(2, "Peter"); + s.add(2, "Zoe"); + s.add(2, "Alex"); + s.add(3, "Jim"); + assert_eq!(s.grade(1), Vec::::new()) } #[test] #[ignore] -fn grades_for_one_student() { - let mut s = school::School::new(); - s.add(2, "Aimee"); - assert_eq!(s.grades(), vec![2]); +fn student_not_added_to_same_grade_more_than_once() { + let mut s = School::new(); + s.add(2, "Blair"); + s.add(2, "James"); + s.add(2, "James"); + s.add(2, "Paul"); + assert_eq!(s.grade(2), vec!["Blair", "James", "Paul"]) } #[test] #[ignore] -fn grades_for_several_students_are_sorted() { - let mut s = school::School::new(); - s.add(2, "Aimee"); - s.add(7, "Logan"); - s.add(4, "Blair"); - assert_eq!(s.grades(), vec![2, 4, 7]); +fn student_not_added_to_multiple_grades() { + let mut s = School::new(); + s.add(2, "Blair"); + s.add(2, "James"); + s.add(3, "James"); + s.add(3, "Paul"); + assert_eq!(s.grade(2), vec!["Blair", "James"]) } #[test] #[ignore] -fn grades_when_several_students_have_the_same_grade() { - let mut s = school::School::new(); - s.add(2, "Aimee"); - s.add(2, "Logan"); +fn student_not_added_to_other_grade_for_multiple_grades() { + let mut s = School::new(); s.add(2, "Blair"); - assert_eq!(s.grades(), vec![2]); + s.add(2, "James"); + s.add(3, "James"); + s.add(3, "Paul"); + assert_eq!(s.grade(3), vec!["Paul"]) } #[test] #[ignore] -fn grade_for_empty_school() { - let s = school::School::new(); - assert_eq!(s.grade(1), Vec::::new()); +fn students_are_sorted_by_name_in_a_grade() { + let mut s = School::new(); + s.add(5, "Franklin"); + s.add(5, "Bradley"); + s.add(1, "Jeff"); + assert_eq!(s.grade(5), vec!["Bradley", "Franklin"]) } #[test] #[ignore] -fn grade_when_no_students_have_that_grade() { - let mut s = school::School::new(); - s.add(7, "Logan"); - assert_eq!(s.grade(1), Vec::::new()); +fn grades_for_empty_school() { + let s = School::new(); + assert_eq!(s.grades(), vec![]) } #[test] #[ignore] -fn grade_for_one_student() { - let mut s = school::School::new(); +fn grades_for_one_student() { + let mut s = School::new(); s.add(2, "Aimee"); - assert_eq!(s.grade(2), to_owned(&["Aimee"])); + assert_eq!(s.grades(), vec![2]) } #[test] #[ignore] -fn grade_returns_students_sorted_by_name() { - let mut s = school::School::new(); - s.add(2, "James"); - s.add(2, "Blair"); - s.add(2, "Paul"); - assert_eq!(s.grade(2), to_owned(&["Blair", "James", "Paul"])); +fn grades_for_several_students_are_sorted() { + let mut s = School::new(); + s.add(2, "Aimee"); + s.add(7, "Logan"); + s.add(4, "Blair"); + assert_eq!(s.grades(), vec![2, 4, 7]) } #[test] #[ignore] -fn add_students_to_different_grades() { - let mut s = school::School::new(); - s.add(3, "Chelsea"); - s.add(7, "Logan"); - assert_eq!(s.grades(), vec![3, 7]); - assert_eq!(s.grade(3), to_owned(&["Chelsea"])); - assert_eq!(s.grade(7), to_owned(&["Logan"])); +fn grades_when_several_students_have_the_same_grade() { + let mut s = School::new(); + s.add(2, "Aimee"); + s.add(2, "Logan"); + s.add(2, "Blair"); + assert_eq!(s.grades(), vec![2]) }