diff --git a/bin/generate_tests.py b/bin/generate_tests.py index 6df6ba562b..f09db7a81a 100755 --- a/bin/generate_tests.py +++ b/bin/generate_tests.py @@ -78,11 +78,22 @@ def get_tested_properties(spec): def error_case(case): return ( + "expected" in case and isinstance(case["expected"], dict) and "error" in case["expected"] ) +def has_error_case(cases): + cases = cases[:] + while cases: + case = cases.pop(0) + if error_case(case): + return True + cases.extend(case.get("cases", [])) + return False + + def load_canonical(exercise, spec_path): """ Loads the canonical data for an exercise as a nested dictionary @@ -129,6 +140,7 @@ def generate_exercise(env, spec_path, exercise, check=False): tests_path = os.path.join( exercise, f'{to_snake(slug)}_test.py' ) + spec["has_error_case"] = has_error_case(spec["cases"]) rendered = template.render(**spec) with NamedTemporaryFile('w', delete=False) as tmp: tmp.write(rendered) diff --git a/config/generator_macros.j2 b/config/generator_macros.j2 index 924affac49..4a087cd961 100644 --- a/config/generator_macros.j2 +++ b/config/generator_macros.j2 @@ -1,10 +1,33 @@ {# Usage: {%- import "generator_macros.j2" as macros -%} #} -{# {{ macros.canonical_ref(version) }} #} +{# {{ macros.linebreak(text) }} #} + +{%- macro linebreak(s) %} +{%- set parts = s.split(": ") -%} +"{{ parts[0] }}: " +{% for part in parts[1].split(", ") %} +"{{ part }}{% if not loop.last %}, {% endif %}" +{%- endfor %} +{% endmacro -%} + +{% macro properties(exercise, properties) -%} +from {{ exercise | to_snake }} import {% for prop in properties -%} + {{ prop | to_snake }} + {%- if not loop.last %}, {% endif -%} +{% endfor %} +{% endmacro -%} {% macro canonical_ref(version) -%} # Tests adapted from `problem-specifications//canonical-data.json` @ v{{ version }} {%- endmacro %} +{% macro header(exercise, props, version) -%} +import unittest + +{{ properties(exercise, props) }} + +{{ canonical_ref(version) }} +{%- endmacro %} + {% macro utility() -%}# Utility functions def setUp(self): try: @@ -15,3 +38,11 @@ def assertRaisesWithMessage(self, exception): return self.assertRaisesRegex(exception, r".+") {%- endmacro %} + +{% macro footer(has_error_case) -%} +{% if has_error_case %} +{{ utility() }} +{% endif %} +if __name__ == '__main__': + unittest.main() +{%- endmacro %} diff --git a/exercises/twelve-days/.meta/template.j2 b/exercises/twelve-days/.meta/template.j2 new file mode 100644 index 0000000000..06cc4adbae --- /dev/null +++ b/exercises/twelve-days/.meta/template.j2 @@ -0,0 +1,23 @@ +{%- import "generator_macros.j2" as macros -%} +{{ macros.header(exercise, properties, version) }} + +class {{ exercise | camel_case }}Test(unittest.TestCase): + {# All test cases in this exercise are nested, so use two for loops -#} + {% for supercase in cases -%}{% for case in supercase["cases"] -%} + {% set input = case["input"] -%} + def test_{{ case["description"] | to_snake }}(self): + {% if supercase["description"] == "verse" -%} + expected = [ + {{ macros.linebreak(case["expected"][0]) }} + ] + {% else -%} + expected = [recite(n, n)[0] for n in range( + {{- input["startVerse"] }}, + {{- input["endVerse"] + 1 }})] + {% endif -%} + self.assertEqual({{ case["property"]}}( + {{- input["startVerse"] }}, + {{- input["endVerse"] }}), expected) + {% endfor %}{% endfor %} + +{{ macros.footer(has_error_case) }} diff --git a/exercises/twelve-days/twelve_days_test.py b/exercises/twelve-days/twelve_days_test.py index a70132ecaa..e94e0a11de 100644 --- a/exercises/twelve-days/twelve_days_test.py +++ b/exercises/twelve-days/twelve_days_test.py @@ -5,146 +5,170 @@ # Tests adapted from `problem-specifications//canonical-data.json` @ v1.2.0 + class TwelveDaysTest(unittest.TestCase): - def test_verse1(self): - expected = ["On the first day of Christmas my true love gave to me: " - "a Partridge in a Pear Tree."] + def test_first_day_a_partridge_in_a_pear_tree(self): + expected = [ + "On the first day of Christmas my true love gave to me: " + "a Partridge in a Pear Tree." + ] self.assertEqual(recite(1, 1), expected) - def test_verse2(self): - expected = ["On the second day of Christmas my true love gave to me: " - "two Turtle Doves, " - "and a Partridge in a Pear Tree."] + def test_second_day_two_turtle_doves(self): + expected = [ + "On the second day of Christmas my true love gave to me: " + "two Turtle Doves, " + "and a Partridge in a Pear Tree." + ] self.assertEqual(recite(2, 2), expected) - def test_verse3(self): - expected = ["On the third day of Christmas my true love gave to me: " - "three French Hens, " - "two Turtle Doves, " - "and a Partridge in a Pear Tree."] + def test_third_day_three_french_hens(self): + expected = [ + "On the third day of Christmas my true love gave to me: " + "three French Hens, " + "two Turtle Doves, " + "and a Partridge in a Pear Tree." + ] self.assertEqual(recite(3, 3), expected) - def test_verse4(self): - expected = ["On the fourth day of Christmas my true love gave to me: " - "four Calling Birds, " - "three French Hens, " - "two Turtle Doves, " - "and a Partridge in a Pear Tree."] + def test_fourth_day_four_calling_birds(self): + expected = [ + "On the fourth day of Christmas my true love gave to me: " + "four Calling Birds, " + "three French Hens, " + "two Turtle Doves, " + "and a Partridge in a Pear Tree." + ] self.assertEqual(recite(4, 4), expected) - def test_verse5(self): - expected = ["On the fifth day of Christmas my true love gave to me: " - "five Gold Rings, " - "four Calling Birds, " - "three French Hens, " - "two Turtle Doves, " - "and a Partridge in a Pear Tree."] + def test_fifth_day_five_gold_rings(self): + expected = [ + "On the fifth day of Christmas my true love gave to me: " + "five Gold Rings, " + "four Calling Birds, " + "three French Hens, " + "two Turtle Doves, " + "and a Partridge in a Pear Tree." + ] self.assertEqual(recite(5, 5), expected) - def test_verse6(self): - expected = ["On the sixth day of Christmas my true love gave to me: " - "six Geese-a-Laying, " - "five Gold Rings, " - "four Calling Birds, " - "three French Hens, " - "two Turtle Doves, " - "and a Partridge in a Pear Tree."] + def test_sixth_day_six_geese_a_laying(self): + expected = [ + "On the sixth day of Christmas my true love gave to me: " + "six Geese-a-Laying, " + "five Gold Rings, " + "four Calling Birds, " + "three French Hens, " + "two Turtle Doves, " + "and a Partridge in a Pear Tree." + ] self.assertEqual(recite(6, 6), expected) - def test_verse7(self): - expected = ["On the seventh day of Christmas my true love gave to me: " - "seven Swans-a-Swimming, " - "six Geese-a-Laying, " - "five Gold Rings, " - "four Calling Birds, " - "three French Hens, " - "two Turtle Doves, " - "and a Partridge in a Pear Tree."] + def test_seventh_day_seven_swans_a_swimming(self): + expected = [ + "On the seventh day of Christmas my true love gave to me: " + "seven Swans-a-Swimming, " + "six Geese-a-Laying, " + "five Gold Rings, " + "four Calling Birds, " + "three French Hens, " + "two Turtle Doves, " + "and a Partridge in a Pear Tree." + ] self.assertEqual(recite(7, 7), expected) - def test_verse8(self): - expected = ["On the eighth day of Christmas my true love gave to me: " - "eight Maids-a-Milking, " - "seven Swans-a-Swimming, " - "six Geese-a-Laying, " - "five Gold Rings, " - "four Calling Birds, " - "three French Hens, " - "two Turtle Doves, " - "and a Partridge in a Pear Tree."] + def test_eighth_day_eight_maids_a_milking(self): + expected = [ + "On the eighth day of Christmas my true love gave to me: " + "eight Maids-a-Milking, " + "seven Swans-a-Swimming, " + "six Geese-a-Laying, " + "five Gold Rings, " + "four Calling Birds, " + "three French Hens, " + "two Turtle Doves, " + "and a Partridge in a Pear Tree." + ] self.assertEqual(recite(8, 8), expected) - def test_verse9(self): - expected = ["On the ninth day of Christmas my true love gave to me: " - "nine Ladies Dancing, " - "eight Maids-a-Milking, " - "seven Swans-a-Swimming, " - "six Geese-a-Laying, " - "five Gold Rings, " - "four Calling Birds, " - "three French Hens, " - "two Turtle Doves, " - "and a Partridge in a Pear Tree."] + def test_ninth_day_nine_ladies_dancing(self): + expected = [ + "On the ninth day of Christmas my true love gave to me: " + "nine Ladies Dancing, " + "eight Maids-a-Milking, " + "seven Swans-a-Swimming, " + "six Geese-a-Laying, " + "five Gold Rings, " + "four Calling Birds, " + "three French Hens, " + "two Turtle Doves, " + "and a Partridge in a Pear Tree." + ] self.assertEqual(recite(9, 9), expected) - def test_verse10(self): - expected = ["On the tenth day of Christmas my true love gave to me: " - "ten Lords-a-Leaping, " - "nine Ladies Dancing, " - "eight Maids-a-Milking, " - "seven Swans-a-Swimming, " - "six Geese-a-Laying, " - "five Gold Rings, " - "four Calling Birds, " - "three French Hens, " - "two Turtle Doves, " - "and a Partridge in a Pear Tree."] + def test_tenth_day_ten_lords_a_leaping(self): + expected = [ + "On the tenth day of Christmas my true love gave to me: " + "ten Lords-a-Leaping, " + "nine Ladies Dancing, " + "eight Maids-a-Milking, " + "seven Swans-a-Swimming, " + "six Geese-a-Laying, " + "five Gold Rings, " + "four Calling Birds, " + "three French Hens, " + "two Turtle Doves, " + "and a Partridge in a Pear Tree." + ] self.assertEqual(recite(10, 10), expected) - def test_verse11(self): - expected = ["On the eleventh day of Christmas " - "my true love gave to me: " - "eleven Pipers Piping, " - "ten Lords-a-Leaping, " - "nine Ladies Dancing, " - "eight Maids-a-Milking, " - "seven Swans-a-Swimming, " - "six Geese-a-Laying, " - "five Gold Rings, " - "four Calling Birds, " - "three French Hens, " - "two Turtle Doves, " - "and a Partridge in a Pear Tree."] + def test_eleventh_day_eleven_pipers_piping(self): + expected = [ + "On the eleventh day of Christmas my true love gave to me: " + "eleven Pipers Piping, " + "ten Lords-a-Leaping, " + "nine Ladies Dancing, " + "eight Maids-a-Milking, " + "seven Swans-a-Swimming, " + "six Geese-a-Laying, " + "five Gold Rings, " + "four Calling Birds, " + "three French Hens, " + "two Turtle Doves, " + "and a Partridge in a Pear Tree." + ] self.assertEqual(recite(11, 11), expected) - def test_verse12(self): - expected = ["On the twelfth day of Christmas my true love gave to me: " - "twelve Drummers Drumming, " - "eleven Pipers Piping, " - "ten Lords-a-Leaping, " - "nine Ladies Dancing, " - "eight Maids-a-Milking, " - "seven Swans-a-Swimming, " - "six Geese-a-Laying, " - "five Gold Rings, " - "four Calling Birds, " - "three French Hens, " - "two Turtle Doves, " - "and a Partridge in a Pear Tree."] + def test_twelfth_day_twelve_drummers_drumming(self): + expected = [ + "On the twelfth day of Christmas my true love gave to me: " + "twelve Drummers Drumming, " + "eleven Pipers Piping, " + "ten Lords-a-Leaping, " + "nine Ladies Dancing, " + "eight Maids-a-Milking, " + "seven Swans-a-Swimming, " + "six Geese-a-Laying, " + "five Gold Rings, " + "four Calling Birds, " + "three French Hens, " + "two Turtle Doves, " + "and a Partridge in a Pear Tree." + ] self.assertEqual(recite(12, 12), expected) - def test_first_three_verses_of_the_song(self): + def test_recites_first_three_verses_of_the_song(self): expected = [recite(n, n)[0] for n in range(1, 4)] self.assertEqual(recite(1, 3), expected) - def test_three_verses_from_the_middle_of_the_song(self): + def test_recites_three_verses_from_the_middle_of_the_song(self): expected = [recite(n, n)[0] for n in range(4, 7)] self.assertEqual(recite(4, 6), expected) - def test_the_whole_song(self): + def test_recites_the_whole_song(self): expected = [recite(n, n)[0] for n in range(1, 13)] self.assertEqual(recite(1, 12), expected) -if __name__ == '__main__': +if __name__ == "__main__": unittest.main()