Analyze test failures and categorize by patterns.
(self, results_file: Path)
| 173 | print(f"Warning: Could not store test results: {e}") |
| 174 | |
| 175 | def analyze_failure_patterns(self, results_file: Path) -> List[FailurePattern]: |
| 176 | """Analyze test failures and categorize by patterns.""" |
| 177 | if not results_file.exists(): |
| 178 | return [] |
| 179 | |
| 180 | try: |
| 181 | with open(results_file, 'r') as f: |
| 182 | data = json.load(f) |
| 183 | except json.JSONDecodeError: |
| 184 | return [] |
| 185 | |
| 186 | # Collect all failure messages |
| 187 | failures = [] |
| 188 | for test in data.get('tests', []): |
| 189 | if test['outcome'] == 'failed': |
| 190 | error_msg = str(test.get('call', {}).get('longrepr', '')) |
| 191 | failures.append({ |
| 192 | 'test': test['nodeid'], |
| 193 | 'error': error_msg |
| 194 | }) |
| 195 | |
| 196 | # Categorize failures by patterns |
| 197 | pattern_matches = defaultdict(list) |
| 198 | |
| 199 | for failure in failures: |
| 200 | matched = False |
| 201 | for category, pattern_info in self.failure_patterns.items(): |
| 202 | if re.search(pattern_info['pattern'], failure['error'], re.IGNORECASE): |
| 203 | pattern_matches[category].append(failure['test']) |
| 204 | matched = True |
| 205 | break |
| 206 | |
| 207 | if not matched: |
| 208 | pattern_matches['other'].append(failure['test']) |
| 209 | |
| 210 | # Create FailurePattern objects |
| 211 | patterns = [] |
| 212 | for category, tests in pattern_matches.items(): |
| 213 | if category == 'other': |
| 214 | description = 'Uncategorized failures' |
| 215 | suggested_fix = 'Manual investigation required' |
| 216 | pattern = 'N/A' |
| 217 | else: |
| 218 | pattern_info = self.failure_patterns[category] |
| 219 | description = pattern_info['description'] |
| 220 | suggested_fix = pattern_info['suggested_fix'] |
| 221 | pattern = pattern_info['pattern'] |
| 222 | |
| 223 | patterns.append(FailurePattern( |
| 224 | category=category, |
| 225 | pattern=pattern, |
| 226 | description=description, |
| 227 | frequency=len(tests), |
| 228 | affected_tests=tests, |
| 229 | suggested_fix=suggested_fix |
| 230 | )) |
| 231 | |
| 232 | return sorted(patterns, key=lambda x: x.frequency, reverse=True) |
no test coverage detected