Skip to content

Commit c5998dd

Browse files
authored
Merge branch 'master' into drop-python2
2 parents 3f9f309 + 274f0cb commit c5998dd

4 files changed

Lines changed: 165 additions & 62 deletions

File tree

config/master_template.j2

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
{%- import "generator_macros.j2" as macros with context -%}
2+
{{ macros.header(imports=imports, ignore=ignore) }}
3+
4+
{%- macro test_cases_recursive(cases) -%}
5+
{% for case in cases -%}
6+
{% if "cases" in case %}
7+
# {{ case["description"] }}
8+
{{ test_cases_recursive(case["cases"]) }}
9+
{% else %}
10+
{{ test_case(case) }}
11+
{% endif -%}
12+
{% endfor -%}
13+
{% endmacro %}
14+
15+
{% if not additional_tests -%}
16+
{%- macro additional_tests() -%}
17+
{{ test_cases_recursive(additional_cases) }}
18+
{% endmacro %}
19+
{%- endif %}
20+
21+
class {{ exercise | camel_case }}Test(unittest.TestCase):
22+
{{ test_cases_recursive(cases) }}
23+
24+
{% if additional_cases | length -%}
25+
# Additional tests for this track
26+
{{ additional_tests() }}
27+
{%- endif %}
28+
{{ macros.footer() }}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
{
2+
"cases": [
3+
{
4+
"description": "foldr add string",
5+
"property": "foldr",
6+
"input": {
7+
"list": ["e", "x", "e", "r", "c", "i", "s", "m"],
8+
"initial": "!",
9+
"function": "(x, y) -> x + y"
10+
},
11+
"expected": "exercism!"
12+
},
13+
{
14+
"description": "reverse mixed types",
15+
"property": "reverse",
16+
"input": {
17+
"list": ["xyz", 4.0, "cat", 1]
18+
},
19+
"expected": [1, "cat", 4.0, "xyz"]
20+
}
21+
]
22+
}
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
{%- import "generator_macros.j2" as macros with context -%}
2+
{% macro lambdify(function) -%}
3+
{% set function = function.replace("(", "", 1).replace(")", "", 1).replace(" ->", ":") %}
4+
{% set function = function.replace("modulo", "%") %}
5+
{% set function = function.replace("/", "//") %}
6+
lambda {{function}}
7+
{%- endmacro %}
8+
9+
{% macro stringify(elem) -%}
10+
{% if elem is string %}
11+
"{{ elem }}"
12+
{%- else -%}
13+
{{ elem }}
14+
{%- endif -%}
15+
{%- endmacro %}
16+
17+
{% macro test_case(case) -%}
18+
{%- set input = case["input"] -%}
19+
def test_{{ case["property"] | to_snake }}_{{ case["description"] | to_snake }}(self):
20+
self.assertEqual(
21+
{%- if case["property"] == "filter" or case["property"] == "map" -%}
22+
list_ops_
23+
{%- endif -%}
24+
{{ case["property"] | to_snake }}(
25+
{%- if case["property"] == "append" -%}
26+
{{ input["list1"] }}, {{ input["list2"] }}
27+
{%- elif case["property"] == "concat" -%}
28+
{{ input["lists"] }}
29+
{%- elif case["property"] == "filter" or case["property"] == "map" -%}
30+
{{ lambdify(input["function"]) }}, {{ input["list"] }}
31+
{%- elif case["property"] == "length" or case["property"] == "reverse" -%}
32+
{{ input["list"] }}
33+
{%- elif case["property"] == "foldl" or case["property"] == "foldr" -%}
34+
{{ lambdify(input["function"]) }}, {{ input["list"] }}, {{ stringify(input["initial"]) }}
35+
{%- endif -%}
36+
),
37+
{{ stringify(case["expected"]) }}
38+
)
39+
{%- endmacro %}
40+
{{ macros.header(imports=["append", "concat", "foldl", "foldr", "length", "reverse", "filter as list_ops_filter", "map as list_ops_map"]) }}
41+
42+
class {{ exercise | camel_case }}Test(unittest.TestCase):
43+
{% for casegroup in cases -%}
44+
{% for case in casegroup["cases"] -%}
45+
{{ test_case(case) }}
46+
{% endfor %}
47+
{% endfor %}
48+
{% if additional_cases | length -%}
49+
50+
# Additional tests for this track
51+
52+
{% for case in additional_cases -%}
53+
{{ test_case(case) }}
54+
{% endfor %}
55+
{%- endif %}
56+
57+
58+
{{ macros.footer() }}
Lines changed: 57 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -1,104 +1,99 @@
11
import unittest
2-
import operator
32

4-
import list_ops
3+
from list_ops import (
4+
append,
5+
concat,
6+
foldl,
7+
foldr,
8+
length,
9+
reverse,
10+
filter as list_ops_filter,
11+
map as list_ops_map,
12+
)
513

14+
# Tests adapted from `problem-specifications//canonical-data.json` @ v2.4.1
615

7-
# Tests adapted from `problem-specifications//canonical-data.json` @ v2.4.0
816

917
class ListOpsTest(unittest.TestCase):
10-
11-
# test for append
1218
def test_append_empty_lists(self):
13-
self.assertEqual(list_ops.append([], []), [])
19+
self.assertEqual(append([], []), [])
1420

15-
def test_append_empty_list_to_list(self):
16-
self.assertEqual(list_ops.append([], [1, 2, 3, 4]), [1, 2, 3, 4])
21+
def test_append_list_to_empty_list(self):
22+
self.assertEqual(append([], [1, 2, 3, 4]), [1, 2, 3, 4])
1723

18-
def test_append_nonempty_lists(self):
19-
self.assertEqual(list_ops.append([1, 2], [2, 3, 4, 5]),
20-
[1, 2, 2, 3, 4, 5])
24+
def test_append_non_empty_lists(self):
25+
self.assertEqual(append([1, 2], [2, 3, 4, 5]), [1, 2, 2, 3, 4, 5])
2126

22-
# tests for concat
2327
def test_concat_empty_list(self):
24-
self.assertEqual(list_ops.concat([]), [])
28+
self.assertEqual(concat([]), [])
2529

2630
def test_concat_list_of_lists(self):
27-
self.assertEqual(list_ops.concat([[1, 2], [3], [], [4, 5, 6]]),
28-
[1, 2, 3, 4, 5, 6])
31+
self.assertEqual(concat([[1, 2], [3], [], [4, 5, 6]]), [1, 2, 3, 4, 5, 6])
2932

3033
def test_concat_list_of_nested_lists(self):
3134
self.assertEqual(
32-
list_ops.concat([[[1], [2]], [[3]], [[]], [[4, 5, 6]]]),
33-
[[1], [2], [3], [], [4, 5, 6]])
35+
concat([[[1], [2]], [[3]], [[]], [[4, 5, 6]]]),
36+
[[1], [2], [3], [], [4, 5, 6]],
37+
)
3438

35-
# tests for filter
3639
def test_filter_empty_list(self):
37-
self.assertEqual(list_ops.filter(lambda x: x % 2 == 1, []), [])
40+
self.assertEqual(list_ops_filter(lambda x: x % 2 == 1, []), [])
3841

39-
def test_filter_nonempty_list(self):
40-
self.assertEqual(
41-
list_ops.filter(lambda x: x % 2 == 1, [1, 2, 3, 4, 5]),
42-
[1, 3, 5])
42+
def test_filter_non_empty_list(self):
43+
self.assertEqual(list_ops_filter(lambda x: x % 2 == 1, [1, 2, 3, 5]), [1, 3, 5])
4344

44-
# tests for length
4545
def test_length_empty_list(self):
46-
self.assertEqual(list_ops.length([]), 0)
46+
self.assertEqual(length([]), 0)
4747

48-
def test_length_nonempty_list(self):
49-
self.assertEqual(list_ops.length([1, 2, 3, 4]), 4)
48+
def test_length_non_empty_list(self):
49+
self.assertEqual(length([1, 2, 3, 4]), 4)
5050

51-
# tests for map
5251
def test_map_empty_list(self):
53-
self.assertEqual(list_ops.map(lambda x: x + 1, []), [])
52+
self.assertEqual(list_ops_map(lambda x: x + 1, []), [])
5453

55-
def test_map_nonempty_list(self):
56-
self.assertEqual(list_ops.map(lambda x: x + 1, [1, 3, 5, 7]),
57-
[2, 4, 6, 8])
54+
def test_map_non_empty_list(self):
55+
self.assertEqual(list_ops_map(lambda x: x + 1, [1, 3, 5, 7]), [2, 4, 6, 8])
5856

59-
# tests for foldl
6057
def test_foldl_empty_list(self):
61-
self.assertEqual(list_ops.foldl(operator.mul, [], 2), 2)
58+
self.assertEqual(foldl(lambda x, y: x * y, [], 2), 2)
6259

63-
def test_foldl_nonempty_list_addition(self):
64-
self.assertEqual(list_ops.foldl(operator.add, [1, 2, 3, 4], 5), 15)
60+
def test_foldl_direction_independent_function_applied_to_non_empty_list(self):
61+
self.assertEqual(foldl(lambda x, y: x + y, [1, 2, 3, 4], 5), 15)
6562

66-
def test_foldl_nonempty_list_floordiv(self):
67-
self.assertEqual(list_ops.foldl(operator.floordiv, [2, 5], 5), 0)
63+
def test_foldl_direction_dependent_function_applied_to_non_empty_list(self):
64+
self.assertEqual(foldl(lambda x, y: x // y, [2, 5], 5), 0)
6865

69-
# tests for foldr
7066
def test_foldr_empty_list(self):
71-
self.assertEqual(list_ops.foldr(operator.mul, [], 2), 2)
67+
self.assertEqual(foldr(lambda x, y: x * y, [], 2), 2)
7268

73-
def test_foldr_nonempty_list_addition(self):
74-
self.assertEqual(list_ops.foldr(operator.add, [1, 2, 3, 4], 5), 15)
69+
def test_foldr_direction_independent_function_applied_to_non_empty_list(self):
70+
self.assertEqual(foldr(lambda x, y: x + y, [1, 2, 3, 4], 5), 15)
7571

76-
def test_foldr_nonempty_list_floordiv(self):
77-
self.assertEqual(list_ops.foldr(operator.floordiv, [2, 5], 5), 2)
78-
79-
# additional test for foldr
80-
def test_foldr_add_str(self):
81-
self.assertEqual(
82-
list_ops.foldr(operator.add,
83-
["e", "x", "e", "r", "c", "i", "s", "m"], "!"),
84-
"exercism!")
72+
def test_foldr_direction_dependent_function_applied_to_non_empty_list(self):
73+
self.assertEqual(foldr(lambda x, y: x // y, [2, 5], 5), 2)
8574

86-
# tests for reverse
8775
def test_reverse_empty_list(self):
88-
self.assertEqual(list_ops.reverse([]), [])
76+
self.assertEqual(reverse([]), [])
8977

90-
def test_reverse_nonempty_list(self):
91-
self.assertEqual(list_ops.reverse([1, 3, 5, 7]), [7, 5, 3, 1])
78+
def test_reverse_non_empty_list(self):
79+
self.assertEqual(reverse([1, 3, 5, 7]), [7, 5, 3, 1])
9280

93-
def test_reverse_list_of_lists_not_flattened(self):
94-
self.assertEqual(list_ops.reverse([[1, 2], [3], [], [4, 5, 6]]),
95-
[[4, 5, 6], [], [3], [1, 2]])
81+
def test_reverse_list_of_lists_is_not_flattened(self):
82+
self.assertEqual(
83+
reverse([[1, 2], [3], [], [4, 5, 6]]), [[4, 5, 6], [], [3], [1, 2]]
84+
)
85+
86+
# Additional tests for this track
9687

97-
# additional test for reverse
98-
def test_reverse_mixed_types(self):
88+
def test_foldr_foldr_add_string(self):
9989
self.assertEqual(
100-
list_ops.reverse(["xyz", 4.0, "cat", 1]), [1, "cat", 4.0, "xyz"])
90+
foldr(lambda x, y: x + y, ["e", "x", "e", "r", "c", "i", "s", "m"], "!"),
91+
"exercism!",
92+
)
93+
94+
def test_reverse_reverse_mixed_types(self):
95+
self.assertEqual(reverse(["xyz", 4.0, "cat", 1]), [1, "cat", 4.0, "xyz"])
10196

10297

103-
if __name__ == '__main__':
98+
if __name__ == "__main__":
10499
unittest.main()

0 commit comments

Comments
 (0)