Skip to content

Commit 0df91b4

Browse files
authored
Merge pull request #337 from cs50/patch-jar-check
Patch jar check
2 parents 6416381 + 68f626c commit 0df91b4

File tree

1 file changed

+68
-0
lines changed

1 file changed

+68
-0
lines changed

jar/__init__.py

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import check50
22
import re
3+
import ast
34

45

56
@check50.check()
@@ -77,3 +78,70 @@ def test_number_functions():
7778
raise check50.Failure(
7879
"test_jar.py does not contain at least four valid functions"
7980
)
81+
82+
83+
@check50.check(test_student_file_passes)
84+
def test_named_functions():
85+
"""test_jar.py defines test_init, test_str, test_deposit, and test_withdraw"""
86+
result = check50.run("pytest test_jar.py --collect-only -q").stdout()
87+
collected_tests = []
88+
for line in result.strip().split('\n'):
89+
if '::test_' in line:
90+
test_name = line.split('::')[1].strip()
91+
collected_tests.append(test_name)
92+
93+
required_funcs = ["test_init", "test_str", "test_deposit", "test_withdraw"]
94+
missing_funcs = []
95+
for func in required_funcs:
96+
if func not in collected_tests:
97+
missing_funcs.append(func)
98+
99+
if missing_funcs:
100+
raise check50.Failure(
101+
f"Function(s) not collected by pytest in test_jar.py: {', '.join(missing_funcs)}")
102+
103+
104+
@check50.check(test_student_file_passes)
105+
def test_valid_testing():
106+
"""test_jar.py contains implemented functions"""
107+
with open("test_jar.py") as f:
108+
contents = f.read()
109+
110+
try:
111+
tree = ast.parse(contents)
112+
except SyntaxError:
113+
raise check50.Failure("test_jar.py contains syntax errors")
114+
115+
required_funcs = ["test_init", "test_str", "test_deposit", "test_withdraw"]
116+
implemented_funcs = []
117+
118+
for node in ast.walk(tree):
119+
if isinstance(node, ast.FunctionDef) and node.name in required_funcs:
120+
has_test_content = False
121+
122+
# Walk through all nodes in the function to find test-related code
123+
for child in ast.walk(node):
124+
# Check for assert statements
125+
if isinstance(child, ast.Assert):
126+
has_test_content = True
127+
break
128+
# Check for pytest.raises or with statements (for context managers)
129+
elif isinstance(child, ast.With):
130+
has_test_content = True
131+
break
132+
# Check for calls to pytest functions or assert methods
133+
elif isinstance(child, ast.Call):
134+
if isinstance(child.func, ast.Attribute):
135+
# Check for pytest.* or self.assert* calls
136+
if (hasattr(child.func.value, 'id') and child.func.value.id == 'pytest') or \
137+
child.func.attr.startswith('assert'):
138+
has_test_content = True
139+
break
140+
141+
if has_test_content:
142+
implemented_funcs.append(node.name)
143+
144+
missing_or_empty = set(required_funcs) - set(implemented_funcs)
145+
if missing_or_empty:
146+
raise check50.Failure(
147+
f"Missing or empty function(s) in test_jar.py: {', '.join(sorted(missing_or_empty))}")

0 commit comments

Comments
 (0)