Skip to content

Commit cb972f5

Browse files
committed
feat: imporve test cases in cookiecutter template
1 parent 5c93771 commit cb972f5

File tree

110 files changed

+3297
-542
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

110 files changed

+3297
-542
lines changed

.cursor/.dev/1-update-cookiecutter-test-template.md

Lines changed: 11 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ Update the cookiecutter template for `test_solution.py` to use a for loop approa
6767
- Change from `{{method.test_cases}}` to `{{method.test_cases.list | join(', ')}}`
6868
- This follows the existing pattern used by other list fields in the template
6969
- Template line 30: `@pytest.mark.parametrize("{{method.parametrize}}", [{{method.test_cases.list | join(', ')}}])`
70+
- **✅ Validated:** Correctly follows existing "list" pattern used by `_tags`, `_readme_examples`, etc.
7071

7172
### Phase 2: Create JSON Migration Script
7273

@@ -83,14 +84,7 @@ Update the cookiecutter template for `test_solution.py` to use a for loop approa
8384
- Create backup of original files
8485
- Validate migrated JSON structure
8586

86-
### Phase 4: Update Template Generation Logic
87-
88-
1. **Modify cookiecutter generation code**
89-
- Update any code that generates the `test_cases` field to output JSON arrays instead of strings
90-
- Ensure new list format is used when creating new problems
91-
- Keep all other generation logic the same
92-
93-
### Phase 5: Testing and Validation
87+
### Phase 4: Testing and Validation
9488

9589
1. **Test generated templates**
9690
- Generate a test problem using updated template
@@ -105,7 +99,7 @@ Update the cookiecutter template for `test_solution.py` to use a for loop approa
10599
- Verify no regressions in test functionality
106100
- Document any issues found and fix them
107101

108-
### Phase 6: Update Documentation
102+
### Phase 5: Update Documentation
109103

110104
1. **Update problem creation documentation**
111105
- Update `.cursor/commands/problem-creation.md` to reflect new JSON structure
@@ -140,16 +134,18 @@ Update the cookiecutter template for `test_solution.py` to use a for loop approa
140134

141135
### Generation Code
142136

143-
- Any code that creates the `test_cases` field (to be identified)
137+
- **No changes needed** - The `test_cases` field is created manually, not by automated code
138+
- The existing "list" pattern is already established and working correctly
139+
- Phase 4 removed after investigation showed no automated generation code exists
144140

145141
## Implementation Steps
146142

147143
1. ✅ Create this plan document
148-
2. 🔄 Update cookiecutter template
149-
3. 🔄 Create migration script
150-
4. 🔄 Run migration on all JSON files
151-
5. 🔄 Test updated template generation
152-
6. 🔄 Validate all tests still work
144+
2. Update cookiecutter template
145+
3. Create migration script
146+
4. Run migration on all JSON files
147+
5. Test updated template generation
148+
6. Validate all tests still work
153149
7. 🔄 Update documentation (separate step - do not combine with implementation)
154150

155151
## Risk Mitigation

leetcode_py/cli/resources/leetcode/json/problems/accounts_merge.json

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,9 @@
55
"problem_title": "Accounts Merge",
66
"difficulty": "Medium",
77
"topics": "Array, Hash Table, String, Depth-First Search, Breadth-First Search, Union Find, Sorting",
8-
"_tags": { "list": ["grind-75"] },
8+
"_tags": {
9+
"list": ["grind-75"]
10+
},
911
"readme_description": "Given a list of `accounts` where each element `accounts[i]` is a list of strings, where the first element `accounts[i][0]` is a name, and the rest of the elements are emails representing emails of the account.\n\nNow, we would like to merge these accounts. Two accounts definitely belong to the same person if there is some common email to both accounts. Note that even if two accounts have the same name, they may belong to different people as people could have the same name. A person can have any number of accounts initially, but all of their accounts definitely have the same name.\n\nAfter merging the accounts, return the accounts in the following format: the first element of each account is the name, and the rest of the elements are emails in sorted order. The accounts themselves can be returned in any order.",
1012
"_readme_examples": {
1113
"list": [
@@ -44,15 +46,36 @@
4446
]
4547
},
4648
"_test_helper_methods": {
47-
"list": [{ "name": "setup_method", "parameters": "", "body": "self.solution = Solution()" }]
49+
"list": [
50+
{
51+
"name": "setup_method",
52+
"parameters": "",
53+
"body": "self.solution = Solution()"
54+
}
55+
]
4856
},
4957
"_test_methods": {
5058
"list": [
5159
{
5260
"name": "test_accounts_merge",
5361
"signature": "(self, accounts: list[list[str]], expected: list[list[str]])",
5462
"parametrize": "accounts, expected",
55-
"test_cases": "[([['John', '[email protected]', '[email protected]'], ['John', '[email protected]', '[email protected]'], ['Mary', '[email protected]'], ['John', '[email protected]']], [['John', '[email protected]', '[email protected]', '[email protected]'], ['Mary', '[email protected]'], ['John', '[email protected]']]), ([['Gabe', '[email protected]', '[email protected]', '[email protected]'], ['Kevin', '[email protected]', '[email protected]', '[email protected]'], ['Ethan', '[email protected]', '[email protected]', '[email protected]'], ['Hanzo', '[email protected]', '[email protected]', '[email protected]'], ['Fern', '[email protected]', '[email protected]', '[email protected]']], [['Ethan', '[email protected]', '[email protected]', '[email protected]'], ['Gabe', '[email protected]', '[email protected]', '[email protected]'], ['Hanzo', '[email protected]', '[email protected]', '[email protected]'], ['Kevin', '[email protected]', '[email protected]', '[email protected]'], ['Fern', '[email protected]', '[email protected]', '[email protected]']]), ([['Alice', '[email protected]']], [['Alice', '[email protected]']]), ([['Bob', '[email protected]'], ['Bob', '[email protected]']], [['Bob', '[email protected]'], ['Bob', '[email protected]']]), ([['Alice', '[email protected]', '[email protected]'], ['Alice', '[email protected]', '[email protected]']], [['Alice', '[email protected]', '[email protected]', '[email protected]']]), ([['A', '[email protected]', '[email protected]'], ['B', '[email protected]', '[email protected]'], ['C', '[email protected]', '[email protected]']], [['A', '[email protected]', '[email protected]', '[email protected]', '[email protected]']]), ([['David', '[email protected]'], ['David', '[email protected]']], [['David', '[email protected]']]), ([['Alex', '[email protected]'], ['Bob', '[email protected]'], ['Charlie', '[email protected]']], [['Alex', '[email protected]'], ['Bob', '[email protected]'], ['Charlie', '[email protected]']]), ([['John', '[email protected]', '[email protected]'], ['John', '[email protected]'], ['Jane', '[email protected]']], [['John', '[email protected]', '[email protected]'], ['John', '[email protected]'], ['Jane', '[email protected]']]), ([['User', '[email protected]', '[email protected]'], ['User', '[email protected]', '[email protected]'], ['User', '[email protected]', '[email protected]']], [['User', '[email protected]', '[email protected]', '[email protected]', '[email protected]']]), ([['Test', '[email protected]'], ['Test', '[email protected]'], ['Test', '[email protected]', '[email protected]']], [['Test', '[email protected]'], ['Test', '[email protected]', '[email protected]']]), ([['Name', '[email protected]', '[email protected]', '[email protected]'], ['Name', '[email protected]', '[email protected]'], ['Name', '[email protected]', '[email protected]']], [['Name', '[email protected]', '[email protected]'], ['Name', '[email protected]', '[email protected]', '[email protected]', '[email protected]']])]",
63+
"test_cases": {
64+
"list": [
65+
66+
67+
"([['Alice', '[email protected]']], [['Alice', '[email protected]']])",
68+
"([['Bob', '[email protected]'], ['Bob', '[email protected]']], [['Bob', '[email protected]'], ['Bob', '[email protected]']])",
69+
70+
71+
"([['David', '[email protected]'], ['David', '[email protected]']], [['David', '[email protected]']])",
72+
"([['Alex', '[email protected]'], ['Bob', '[email protected]'], ['Charlie', '[email protected]']], [['Alex', '[email protected]'], ['Bob', '[email protected]'], ['Charlie', '[email protected]']])",
73+
"([['John', '[email protected]', '[email protected]'], ['John', '[email protected]'], ['Jane', '[email protected]']], [['John', '[email protected]', '[email protected]'], ['John', '[email protected]'], ['Jane', '[email protected]']])",
74+
75+
"([['Test', '[email protected]'], ['Test', '[email protected]'], ['Test', '[email protected]', '[email protected]']], [['Test', '[email protected]'], ['Test', '[email protected]', '[email protected]']])",
76+
77+
]
78+
},
5679
"body": " result = run_accounts_merge(Solution, accounts)\n assert_accounts_merge(result, expected)"
5780
}
5881
]

leetcode_py/cli/resources/leetcode/json/problems/add_binary.json

Lines changed: 31 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,18 @@
55
"problem_title": "Add Binary",
66
"difficulty": "Easy",
77
"topics": "Math, String, Bit Manipulation, Simulation",
8-
"_tags": { "list": ["grind-75"] },
8+
"_tags": {
9+
"list": ["grind-75"]
10+
},
911
"readme_description": "Given two binary strings `a` and `b`, return *their sum as a binary string*.",
1012
"_readme_examples": {
1113
"list": [
12-
{ "content": "```\nInput: a = \"11\", b = \"1\"\nOutput: \"100\"\n```" },
13-
{ "content": "```\nInput: a = \"1010\", b = \"1011\"\nOutput: \"10101\"\n```" }
14+
{
15+
"content": "```\nInput: a = \"11\", b = \"1\"\nOutput: \"100\"\n```"
16+
},
17+
{
18+
"content": "```\nInput: a = \"1010\", b = \"1011\"\nOutput: \"10101\"\n```"
19+
}
1420
]
1521
},
1622
"readme_constraints": "- `1 <= a.length, b.length <= 10^4`\n- `a` and `b` consist only of `'0'` or `'1'` characters.\n- Each string does not contain leading zeros except for the zero itself.",
@@ -40,15 +46,35 @@
4046
]
4147
},
4248
"_test_helper_methods": {
43-
"list": [{ "name": "setup_method", "parameters": "", "body": "self.solution = Solution()" }]
49+
"list": [
50+
{
51+
"name": "setup_method",
52+
"parameters": "",
53+
"body": "self.solution = Solution()"
54+
}
55+
]
4456
},
4557
"_test_methods": {
4658
"list": [
4759
{
4860
"name": "test_add_binary",
4961
"signature": "(self, a: str, b: str, expected: str)",
5062
"parametrize": "a, b, expected",
51-
"test_cases": "[('11', '1', '100'), ('1010', '1011', '10101'), ('0', '0', '0'), ('1', '1', '10'), ('1111', '1111', '11110'), ('1', '0', '1'), ('0', '1', '1'), ('1', '111', '1000'), ('111', '1', '1000'), ('1010', '1', '1011'), ('1111', '1', '10000')]",
63+
"test_cases": {
64+
"list": [
65+
"('11', '1', '100')",
66+
"('1010', '1011', '10101')",
67+
"('0', '0', '0')",
68+
"('1', '1', '10')",
69+
"('1111', '1111', '11110')",
70+
"('1', '0', '1')",
71+
"('0', '1', '1')",
72+
"('1', '111', '1000')",
73+
"('111', '1', '1000')",
74+
"('1010', '1', '1011')",
75+
"('1111', '1', '10000')"
76+
]
77+
},
5278
"body": " result = run_add_binary(Solution, a, b)\n assert_add_binary(result, expected)"
5379
}
5480
]

leetcode_py/cli/resources/leetcode/json/problems/alien_dictionary.json

Lines changed: 35 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,18 @@
55
"problem_title": "Alien Dictionary",
66
"difficulty": "Hard",
77
"topics": "Array, String, Depth-First Search, Breadth-First Search, Graph, Topological Sort",
8-
"_tags": { "list": ["grind-75"] },
8+
"_tags": {
9+
"list": ["grind-75"]
10+
},
911
"readme_description": "There is a new alien language that uses the English alphabet. However, the order among the letters is unknown to you.\n\nYou are given a list of strings `words` from the alien language's dictionary, where the strings in `words` are **sorted lexicographically** by the rules of this new language.\n\nReturn *a string of the unique letters in the new alien language sorted in **lexicographically increasing order** by the new language's rules. If there is no solution, return* `\"\"`*. If there are multiple solutions, return **any of them***.",
1012
"_readme_examples": {
1113
"list": [
1214
{
1315
"content": "```\nInput: words = [\"wrt\",\"wrf\",\"er\",\"ett\",\"rftt\"]\nOutput: \"wertf\"\n```"
1416
},
15-
{ "content": "```\nInput: words = [\"z\",\"x\"]\nOutput: \"zx\"\n```" },
17+
{
18+
"content": "```\nInput: words = [\"z\",\"x\"]\nOutput: \"zx\"\n```"
19+
},
1620
{
1721
"content": "```\nInput: words = [\"z\",\"x\",\"z\"]\nOutput: \"\"\nExplanation: The order is invalid, so return \"\".\n```"
1822
}
@@ -45,15 +49,42 @@
4549
]
4650
},
4751
"_test_helper_methods": {
48-
"list": [{ "name": "setup_method", "parameters": "", "body": "self.solution = Solution()" }]
52+
"list": [
53+
{
54+
"name": "setup_method",
55+
"parameters": "",
56+
"body": "self.solution = Solution()"
57+
}
58+
]
4959
},
5060
"_test_methods": {
5161
"list": [
5262
{
5363
"name": "test_alien_order",
5464
"signature": "(self, words: list[str], expected: str)",
5565
"parametrize": "words, expected",
56-
"test_cases": "[(['wrt', 'wrf', 'er', 'ett', 'rftt'], 'wertf'), (['z', 'x'], 'zx'), (['z', 'x', 'z'], ''), (['z', 'z'], 'z'), (['abc', 'ab'], ''), (['ab', 'adc'], 'abdc'), (['ac', 'ab', 'zc', 'zb'], 'acbz'), (['z'], 'z'), (['za', 'zb', 'ca', 'cb'], 'zcab'), (['zy', 'zx'], 'zyx'), (['a', 'b', 'ca', 'cc'], 'abc'), (['abc', 'bcd', 'cde'], 'abcde'), (['a', 'aa'], 'a'), (['ab', 'abc'], 'abc'), (['abc', 'ab'], ''), (['a', 'b', 'c', 'd'], 'abcd'), (['d', 'c', 'b', 'a'], 'dcba'), (['ac', 'ab', 'b'], 'acb')]",
66+
"test_cases": {
67+
"list": [
68+
"(['wrt', 'wrf', 'er', 'ett', 'rftt'], 'wertf')",
69+
"(['z', 'x'], 'zx')",
70+
"(['z', 'x', 'z'], '')",
71+
"(['z', 'z'], 'z')",
72+
"(['abc', 'ab'], '')",
73+
"(['ab', 'adc'], 'abdc')",
74+
"(['ac', 'ab', 'zc', 'zb'], 'acbz')",
75+
"(['z'], 'z')",
76+
"(['za', 'zb', 'ca', 'cb'], 'zcab')",
77+
"(['zy', 'zx'], 'zyx')",
78+
"(['a', 'b', 'ca', 'cc'], 'abc')",
79+
"(['abc', 'bcd', 'cde'], 'abcde')",
80+
"(['a', 'aa'], 'a')",
81+
"(['ab', 'abc'], 'abc')",
82+
"(['abc', 'ab'], '')",
83+
"(['a', 'b', 'c', 'd'], 'abcd')",
84+
"(['d', 'c', 'b', 'a'], 'dcba')",
85+
"(['ac', 'ab', 'b'], 'acb')"
86+
]
87+
},
5788
"body": " result = run_alien_order(Solution, words)\n assert_alien_order(result, expected)"
5889
}
5990
]

leetcode_py/cli/resources/leetcode/json/problems/balanced_binary_tree.json

Lines changed: 32 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,9 @@
55
"problem_title": "Balanced Binary Tree",
66
"difficulty": "Easy",
77
"topics": "Tree, Depth-First Search, Binary Tree",
8-
"_tags": { "list": ["grind-75"] },
8+
"_tags": {
9+
"list": ["grind-75"]
10+
},
911
"readme_description": "Given a binary tree, determine if it is **height-balanced**.\n\nA height-balanced binary tree is a binary tree in which the depth of the two subtrees of every node never differs by more than one.",
1012
"_readme_examples": {
1113
"list": [
@@ -15,7 +17,9 @@
1517
{
1618
"content": "![Example 2](https://assets.leetcode.com/uploads/2020/10/06/balance_2.jpg)\n\n```\nInput: root = [1,2,2,3,3,null,null,4,4]\nOutput: false\n```"
1719
},
18-
{ "content": "```\nInput: root = []\nOutput: true\n```" }
20+
{
21+
"content": "```\nInput: root = []\nOutput: true\n```"
22+
}
1923
]
2024
},
2125
"readme_constraints": "- The number of nodes in the tree is in the range `[0, 5000]`.\n- `-10^4 <= Node.val <= 10^4`",
@@ -45,15 +49,39 @@
4549
]
4650
},
4751
"_test_helper_methods": {
48-
"list": [{ "name": "setup_method", "parameters": "", "body": "self.solution = Solution()" }]
52+
"list": [
53+
{
54+
"name": "setup_method",
55+
"parameters": "",
56+
"body": "self.solution = Solution()"
57+
}
58+
]
4959
},
5060
"_test_methods": {
5161
"list": [
5262
{
5363
"name": "test_is_balanced",
5464
"signature": "(self, root_list: list[int | None], expected: bool)",
5565
"parametrize": "root_list, expected",
56-
"test_cases": "[([3, 9, 20, None, None, 15, 7], True), ([1, 2, 2, 3, 3, None, None, 4, 4], False), ([], True), ([1], True), ([1, 2], True), ([1, None, 2], True), ([1, 2, 3, 4], True), ([1, 2, 2, 3, None, None, 3, 4, None, None, 4], False), ([1, 2, 3], True), ([1, 2, None, 3], False), ([1, None, 2, None, 3], False), ([1, 2, 3, 4, 5, 6, 7], True), ([1, 2, 3, None, None, 4, None, None, 5], False), ([5, 1, 4, None, None, 3, 6], True), ([1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, None, None, 5, 5], True)]",
66+
"test_cases": {
67+
"list": [
68+
"([3, 9, 20, None, None, 15, 7], True)",
69+
"([1, 2, 2, 3, 3, None, None, 4, 4], False)",
70+
"([], True)",
71+
"([1], True)",
72+
"([1, 2], True)",
73+
"([1, None, 2], True)",
74+
"([1, 2, 3, 4], True)",
75+
"([1, 2, 2, 3, None, None, 3, 4, None, None, 4], False)",
76+
"([1, 2, 3], True)",
77+
"([1, 2, None, 3], False)",
78+
"([1, None, 2, None, 3], False)",
79+
"([1, 2, 3, 4, 5, 6, 7], True)",
80+
"([1, 2, 3, None, None, 4, None, None, 5], False)",
81+
"([5, 1, 4, None, None, 3, 6], True)",
82+
"([1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, None, None, 5, 5], True)"
83+
]
84+
},
5785
"body": " result = run_is_balanced(Solution, root_list)\n assert_is_balanced(result, expected)"
5886
}
5987
]

0 commit comments

Comments
 (0)