diff --git a/exercises/rational-numbers/.meta/template.j2 b/exercises/rational-numbers/.meta/template.j2 new file mode 100644 index 00000000000..3af451e0416 --- /dev/null +++ b/exercises/rational-numbers/.meta/template.j2 @@ -0,0 +1,97 @@ +{%- import "generator_macros.j2" as macros with context -%} + +{%- set operators = { + "add": "+", + "sub": "-", + "mul": "*", + "div": "/", + "exprational": "**", + "expreal": "**" +} -%} + +{% macro test_case_arithmetic(case) -%} + {%- set r1 = "Rational({}, {})".format(case["input"]["r1"][0], case["input"]["r1"][1]) -%} + {%- set r2 = "Rational({}, {})".format(case["input"]["r2"][0], case["input"]["r2"][1]) -%} + {%- set expected = "Rational({}, {})".format(case["expected"][0], case["expected"][1]) -%} + {%- set operator = operators[case["property"]] -%} + + def test_{{ case["description"] | to_snake }}(self): + self.assertEqual({{r1}} {{operator}} {{r2}}, {{expected}}) +{%- endmacro %} + +{% macro test_case_absolutevalue(case) -%} + {%- set r = "Rational({}, {})".format(case["input"]["r"][0], case["input"]["r"][1]) -%} + {%- set expected = "Rational({}, {})".format(case["expected"][0], case["expected"][1]) -%} + {%- set method = case["property"] -%} + def test_{{ case["description"] | to_snake }}(self): + self.assertEqual({{method}}({{r}}), {{expected}}) +{%- endmacro %} + +{% macro test_case_exponentiation(case) -%} + {%- set r = "Rational({}, {})".format(case["input"]["r"][0], case["input"]["r"][1]) -%} + {%- set n = case["input"]["n"] -%} + {%- set expected = "Rational({}, {})".format(case["expected"][0], case["expected"][1]) -%} + {%- set operator = operators[case["property"]] -%} + + def test_{{ case["description"] | to_snake }}(self): + self.assertEqual({{r}} {{operator}} {{n}}, {{expected}}) +{%- endmacro %} + +{% macro test_case_exponentiation_real(case) -%} + {%- set x = case["input"]["x"] -%} + {%- set r = "Rational({}, {})".format(case["input"]["r"][0], case["input"]["r"][1]) -%} + {%- set expected = case["expected"] -%} + {%- set operator = operators[case["property"]] -%} + + def test_{{ case["description"] | to_snake }}(self): + self.assertAlmostEqual({{x}} {{operator}} {{r}}, {{expected}}, places=8) +{%- endmacro %} + +{% macro test_case_reduction(case) -%} + {%- set r = "Rational({}, {})".format(case["input"]["r"][0], case["input"]["r"][1]) -%} + {%- set expected = "Rational({}, {})".format(case["expected"][0], case["expected"][1]) -%} + + def test_{{ case["description"] | to_snake }}(self): + self.assertEqual({{r}}, {{expected}}) +{%- endmacro %} + +{% macro render_arithmetic_cases(mathtypescases) -%} + + {% for mathoperationcases in mathtypescases["cases"] %} + # {{ mathoperationcases["description"] }} + {% for case in mathoperationcases["cases"] %} + {{ test_case_arithmetic(case) }} + {% endfor %} + {% endfor %} + +{%- endmacro %} + +{% macro render_other_cases(mathtypescases) -%} + + {% for case in mathtypescases["cases"] %} + {% if mathtypescases["description"] == 'Absolute value' %} + {{ test_case_absolutevalue(case) }} + {% elif mathtypescases["description"] == 'Exponentiation of a rational number' %} + {{ test_case_exponentiation(case) }} + {% elif mathtypescases["description"] == 'Exponentiation of a real number to a rational number' %} + {{ test_case_exponentiation_real(case) }} + {% elif mathtypescases["description"] == 'Reduction to lowest terms' %} + {{ test_case_reduction(case) }} + {% endif %} + {% endfor %} + +{%- endmacro %} + +from __future__ import division +{{ macros.header(imports=["Rational"]) }} + +class {{ exercise | camel_case }}Test(unittest.TestCase): + {% for mathtypescases in cases %} + # Tests of type: {{ mathtypescases["description"] }} + {% if mathtypescases["description"] == 'Arithmetic' %} + {{ render_arithmetic_cases(mathtypescases) }} + {% else %} + {{ render_other_cases(mathtypescases) }} + {% endif %} + {% endfor %} +{{ macros.footer() }} diff --git a/exercises/rational-numbers/rational_numbers_test.py b/exercises/rational-numbers/rational_numbers_test.py index a7fe7812f5a..d44729954a0 100644 --- a/exercises/rational-numbers/rational_numbers_test.py +++ b/exercises/rational-numbers/rational_numbers_test.py @@ -1,93 +1,104 @@ from __future__ import division - import unittest from rational_numbers import Rational - # Tests adapted from `problem-specifications//canonical-data.json` @ v1.1.0 + class RationalNumbersTest(unittest.TestCase): - # Test addition - def test_add_two_positive(self): + # Tests of type: Arithmetic + + # Addition + + def test_add_two_positive_rational_numbers(self): self.assertEqual(Rational(1, 2) + Rational(2, 3), Rational(7, 6)) - def test_add_positive_and_negative(self): + def test_add_a_positive_rational_number_and_a_negative_rational_number(self): self.assertEqual(Rational(1, 2) + Rational(-2, 3), Rational(-1, 6)) - def test_add_two_negative(self): + def test_add_two_negative_rational_numbers(self): self.assertEqual(Rational(-1, 2) + Rational(-2, 3), Rational(-7, 6)) - def test_add_opposite(self): + def test_add_a_rational_number_to_its_additive_inverse(self): self.assertEqual(Rational(1, 2) + Rational(-1, 2), Rational(0, 1)) - # Test subtraction - def test_subtract_two_positive(self): + # Subtraction + + def test_subtract_two_positive_rational_numbers(self): self.assertEqual(Rational(1, 2) - Rational(2, 3), Rational(-1, 6)) - def test_subtract_positive_and_negative(self): + def test_subtract_a_positive_rational_number_and_a_negative_rational_number(self): self.assertEqual(Rational(1, 2) - Rational(-2, 3), Rational(7, 6)) - def test_subtract_two_negative(self): + def test_subtract_two_negative_rational_numbers(self): self.assertEqual(Rational(-1, 2) - Rational(-2, 3), Rational(1, 6)) - def test_subtract_from_self(self): + def test_subtract_a_rational_number_from_itself(self): self.assertEqual(Rational(1, 2) - Rational(1, 2), Rational(0, 1)) - # Test multiplication - def test_multiply_two_positive(self): + # Multiplication + + def test_multiply_two_positive_rational_numbers(self): self.assertEqual(Rational(1, 2) * Rational(2, 3), Rational(1, 3)) - def test_multiply_negative_by_positive(self): + def test_multiply_a_negative_rational_number_by_a_positive_rational_number(self): self.assertEqual(Rational(-1, 2) * Rational(2, 3), Rational(-1, 3)) - def test_multiply_two_negative(self): + def test_multiply_two_negative_rational_numbers(self): self.assertEqual(Rational(-1, 2) * Rational(-2, 3), Rational(1, 3)) - def test_multiply_reciprocal(self): + def test_multiply_a_rational_number_by_its_reciprocal(self): self.assertEqual(Rational(1, 2) * Rational(2, 1), Rational(1, 1)) - def test_multiply_by_one(self): + def test_multiply_a_rational_number_by_1(self): self.assertEqual(Rational(1, 2) * Rational(1, 1), Rational(1, 2)) - def test_multiply_by_zero(self): + def test_multiply_a_rational_number_by_0(self): self.assertEqual(Rational(1, 2) * Rational(0, 1), Rational(0, 1)) - # Test division - def test_divide_two_positive(self): + # Division + + def test_divide_two_positive_rational_numbers(self): self.assertEqual(Rational(1, 2) / Rational(2, 3), Rational(3, 4)) - def test_divide_positive_by_negative(self): + def test_divide_a_positive_rational_number_by_a_negative_rational_number(self): self.assertEqual(Rational(1, 2) / Rational(-2, 3), Rational(-3, 4)) - def test_divide_two_negative(self): + def test_divide_two_negative_rational_numbers(self): self.assertEqual(Rational(-1, 2) / Rational(-2, 3), Rational(3, 4)) - def test_divide_by_one(self): + def test_divide_a_rational_number_by_1(self): self.assertEqual(Rational(1, 2) / Rational(1, 1), Rational(1, 2)) - # Test absolute value - def test_absolute_value_of_positive(self): + # Tests of type: Absolute value + + def test_absolute_value_of_a_positive_rational_number(self): self.assertEqual(abs(Rational(1, 2)), Rational(1, 2)) - def test_absolute_value_of_positive_negative_numerator_denominator(self): + def test_absolute_value_of_a_positive_rational_number_with_negative_numerator_and_denominator( + self + ): self.assertEqual(abs(Rational(-1, -2)), Rational(1, 2)) - def test_absolute_value_of_negative(self): + def test_absolute_value_of_a_negative_rational_number(self): self.assertEqual(abs(Rational(-1, 2)), Rational(1, 2)) - def test_absolute_value_of_negative_with_negative_denominator(self): + def test_absolute_value_of_a_negative_rational_number_with_negative_denominator( + self + ): self.assertEqual(abs(Rational(1, -2)), Rational(1, 2)) def test_absolute_value_of_zero(self): self.assertEqual(abs(Rational(0, 1)), Rational(0, 1)) - # Test exponentiation of a rational number - def test_raise_a_positive_rational_to_a_positive_integer_power(self): + # Tests of type: Exponentiation of a rational number + + def test_raise_a_positive_rational_number_to_a_positive_integer_power(self): self.assertEqual(Rational(1, 2) ** 3, Rational(1, 8)) - def test_raise_a_negative_rational_to_a_positive_integer_power(self): + def test_raise_a_negative_rational_number_to_a_positive_integer_power(self): self.assertEqual(Rational(-1, 2) ** 3, Rational(-1, 8)) def test_raise_zero_to_an_integer_power(self): @@ -96,43 +107,43 @@ def test_raise_zero_to_an_integer_power(self): def test_raise_one_to_an_integer_power(self): self.assertEqual(Rational(1, 1) ** 4, Rational(1, 1)) - def test_raise_a_positive_rational_to_the_power_of_zero(self): + def test_raise_a_positive_rational_number_to_the_power_of_zero(self): self.assertEqual(Rational(1, 2) ** 0, Rational(1, 1)) - def test_raise_a_negative_rational_to_the_power_of_zero(self): + def test_raise_a_negative_rational_number_to_the_power_of_zero(self): self.assertEqual(Rational(-1, 2) ** 0, Rational(1, 1)) - # Test exponentiation of a real number to a rational number - def test_raise_a_real_number_to_a_positive_rational(self): + # Tests of type: Exponentiation of a real number to a rational number + + def test_raise_a_real_number_to_a_positive_rational_number(self): self.assertAlmostEqual(8 ** Rational(4, 3), 16.0, places=8) - def test_raise_a_real_number_to_a_negative_rational(self): - self.assertAlmostEqual( - 9 ** Rational(-1, 2), 0.3333333333333333, places=8 - ) + def test_raise_a_real_number_to_a_negative_rational_number(self): + self.assertAlmostEqual(9 ** Rational(-1, 2), 0.3333333333333333, places=8) - def test_raise_a_real_number_to_a_zero_rational(self): + def test_raise_a_real_number_to_a_zero_rational_number(self): self.assertAlmostEqual(2 ** Rational(0, 1), 1.0, places=8) - # Test reduction to lowest terms - def test_reduce_positive(self): + # Tests of type: Reduction to lowest terms + + def test_reduce_a_positive_rational_number_to_lowest_terms(self): self.assertEqual(Rational(2, 4), Rational(1, 2)) - def test_reduce_negative(self): + def test_reduce_a_negative_rational_number_to_lowest_terms(self): self.assertEqual(Rational(-4, 6), Rational(-2, 3)) - def test_reduce_rational_with_negative_denominator(self): + def test_reduce_a_rational_number_with_a_negative_denominator_to_lowest_terms(self): self.assertEqual(Rational(3, -9), Rational(-1, 3)) - def test_reduce_zero(self): + def test_reduce_zero_to_lowest_terms(self): self.assertEqual(Rational(0, 6), Rational(0, 1)) - def test_reduce_integer(self): + def test_reduce_an_integer_to_lowest_terms(self): self.assertEqual(Rational(-14, 7), Rational(-2, 1)) - def test_reduce_one(self): + def test_reduce_one_to_lowest_terms(self): self.assertEqual(Rational(13, 13), Rational(1, 1)) -if __name__ == '__main__': +if __name__ == "__main__": unittest.main()