Skip to content

Commit ddb656f

Browse files
tests: parse test output
1 parent a6a5578 commit ddb656f

File tree

2 files changed

+147
-5
lines changed

2 files changed

+147
-5
lines changed

codeflash/verification/parse_test_output.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -556,7 +556,7 @@ def merge_test_results(
556556
TEST_HEADER_RE = re.compile(r"_{3,}\s*(.*?)\s*_{3,}$")
557557

558558

559-
def parse_test_failures_from_stdout(test_results: TestResults, stdout: str) -> TestResults:
559+
def parse_test_failures_from_stdout(stdout: str) -> dict[str, str]:
560560
"""Extract individual pytest test failures from stdout grouped by test case qualified name, and add them to the test results."""
561561
lines = stdout.splitlines()
562562
start = end = None
@@ -567,7 +567,7 @@ def parse_test_failures_from_stdout(test_results: TestResults, stdout: str) -> T
567567
break
568568

569569
if start is None:
570-
return test_results
570+
return {}
571571

572572
for j in range(start + 1, len(lines)):
573573
stripped = lines[j].strip()
@@ -603,8 +603,7 @@ def parse_test_failures_from_stdout(test_results: TestResults, stdout: str) -> T
603603
if current_name:
604604
failures[current_name] = "".join(current_lines)
605605

606-
test_results.test_failures = failures
607-
return test_results
606+
return failures
608607

609608

610609
def parse_test_results(
@@ -663,7 +662,8 @@ def parse_test_results(
663662
)
664663
coverage.log_coverage()
665664
try:
666-
parse_test_failures_from_stdout(results, run_result.stdout)
665+
failures = parse_test_failures_from_stdout(run_result.stdout)
666+
results.test_failures = failures
667667
except Exception as e:
668668
logger.exception(e)
669669

Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
1+
2+
from codeflash.verification.parse_test_output import parse_test_failures_from_stdout
3+
4+
5+
def test_extracting_single_pytest_error_from_stdout():
6+
stdout = '''
7+
F... [100%]
8+
=================================== FAILURES ===================================
9+
_______________________ test_calculate_portfolio_metrics _______________________
10+
11+
def test_calculate_portfolio_metrics():
12+
# Test case 1: Basic portfolio
13+
investments = [
14+
('Stocks', 0.6, 0.12),
15+
('Bonds', 0.3, 0.04),
16+
('Cash', 0.1, 0.01)
17+
]
18+
19+
result = calculate_portfolio_metrics(investments)
20+
21+
# Check weighted return calculation
22+
expected_return = 0.6*0.12 + 0.3*0.04 + 0.1*0.01
23+
assert abs(result['weighted_return'] - expected_return) < 1e-10
24+
25+
# Check volatility calculation
26+
expected_vol = math.sqrt((0.6*0.12)**2 + (0.3*0.04)**2 + (0.1*0.01)**2)
27+
assert abs(result['volatility'] - expected_vol) < 1e-10
28+
29+
# Check Sharpe ratio
30+
expected_sharpe = (expected_return - 0.02) / expected_vol
31+
> assert abs(result['sharpe_ratio'] - expected_sharpe) < 1e-10
32+
E assert 4.109589046841222e-08 < 1e-10
33+
E + where 4.109589046841222e-08 = abs((0.890411 - 0.8904109589041095))
34+
35+
code_to_optimize/tests/pytest/test_multiple_helpers.py:26: AssertionError
36+
=========================== short test summary info ============================
37+
FAILED code_to_optimize/tests/pytest/test_multiple_helpers.py::test_calculate_portfolio_metrics[ 1 ]
38+
1 failed, 3 passed in 0.15s
39+
40+
41+
'''
42+
errors = parse_test_failures_from_stdout(stdout)
43+
assert errors
44+
assert len(errors.keys()) == 1
45+
assert errors['test_calculate_portfolio_metrics'] == '''
46+
def test_calculate_portfolio_metrics():
47+
# Test case 1: Basic portfolio
48+
investments = [
49+
('Stocks', 0.6, 0.12),
50+
('Bonds', 0.3, 0.04),
51+
('Cash', 0.1, 0.01)
52+
]
53+
54+
result = calculate_portfolio_metrics(investments)
55+
56+
# Check weighted return calculation
57+
expected_return = 0.6*0.12 + 0.3*0.04 + 0.1*0.01
58+
assert abs(result['weighted_return'] - expected_return) < 1e-10
59+
60+
# Check volatility calculation
61+
expected_vol = math.sqrt((0.6*0.12)**2 + (0.3*0.04)**2 + (0.1*0.01)**2)
62+
assert abs(result['volatility'] - expected_vol) < 1e-10
63+
64+
# Check Sharpe ratio
65+
expected_sharpe = (expected_return - 0.02) / expected_vol
66+
> assert abs(result['sharpe_ratio'] - expected_sharpe) < 1e-10
67+
E assert 4.109589046841222e-08 < 1e-10
68+
E + where 4.109589046841222e-08 = abs((0.890411 - 0.8904109589041095))
69+
70+
code_to_optimize/tests/pytest/test_multiple_helpers.py:26: AssertionError
71+
'''
72+
73+
def test_extracting_no_pytest_failures():
74+
stdout = '''
75+
.... [100%]
76+
4 passed in 0.12s
77+
'''
78+
errors = parse_test_failures_from_stdout(stdout)
79+
assert errors == {}
80+
81+
82+
def test_extracting_multiple_pytest_failures_with_class_method():
83+
print("hi")
84+
85+
stdout = '''
86+
F.F [100%]
87+
=================================== FAILURES ===================================
88+
________________________ test_simple_failure ________________________
89+
90+
def test_simple_failure():
91+
x = 1 + 1
92+
> assert x == 3
93+
E assert 2 == 3
94+
95+
code_to_optimize/tests/test_simple.py:10: AssertionError
96+
________________ TestCalculator.test_divide_by_zero ________________
97+
98+
class TestCalculator:
99+
def test_divide_by_zero(self):
100+
> Calculator().divide(10, 0)
101+
E ZeroDivisionError: division by zero
102+
103+
code_to_optimize/tests/test_calculator.py:22: ZeroDivisionError
104+
=========================== short test summary info ============================
105+
FAILED code_to_optimize/tests/test_simple.py::test_simple_failure
106+
FAILED code_to_optimize/tests/test_calculator.py::TestCalculator::test_divide_by_zero
107+
2 failed, 1 passed in 0.18s
108+
'''
109+
errors = parse_test_failures_from_stdout(stdout)
110+
print(errors)
111+
assert len(errors) == 2
112+
113+
assert 'test_simple_failure' in errors
114+
assert errors['test_simple_failure'] == '''
115+
def test_simple_failure():
116+
x = 1 + 1
117+
> assert x == 3
118+
E assert 2 == 3
119+
120+
code_to_optimize/tests/test_simple.py:10: AssertionError
121+
'''
122+
123+
assert 'TestCalculator.test_divide_by_zero' in errors
124+
assert '''
125+
class TestCalculator:
126+
def test_divide_by_zero(self):
127+
> Calculator().divide(10, 0)
128+
E ZeroDivisionError: division by zero
129+
130+
code_to_optimize/tests/test_calculator.py:22: ZeroDivisionError
131+
''' == errors['TestCalculator.test_divide_by_zero']
132+
133+
def test_extracting_from_invalid_pytest_stdout():
134+
stdout = '''
135+
Running tests...
136+
Everything seems fine
137+
No structured output here
138+
Just some random logs
139+
'''
140+
141+
errors = parse_test_failures_from_stdout(stdout)
142+
assert errors == {}

0 commit comments

Comments
 (0)