Run a single test and capture its output
(
test_file: Path, verbose: bool = False, enable_stack_trace: bool = False
)
| 250 | |
| 251 | |
| 252 | def run_test( |
| 253 | test_file: Path, verbose: bool = False, enable_stack_trace: bool = False |
| 254 | ) -> TestResult: |
| 255 | """Run a single test and capture its output""" |
| 256 | global _ABORT_EVENT |
| 257 | if _ABORT_EVENT.is_set(): |
| 258 | return TestResult( |
| 259 | name=test_file.stem, |
| 260 | success=False, |
| 261 | duration=0.0, |
| 262 | output="Test aborted because _ABORT_EVENT was set.", |
| 263 | captured_lines=[], |
| 264 | ) |
| 265 | start_time = time.time() |
| 266 | |
| 267 | # Build command with doctest flags |
| 268 | # Convert to absolute path for Windows compatibility |
| 269 | test_executable = test_file.resolve() |
| 270 | cmd = [str(test_executable)] |
| 271 | if not verbose: |
| 272 | cmd.append("--minimal") # Only show output for failures |
| 273 | captured_lines: list[str] = [] |
| 274 | try: |
| 275 | # Set timeout when stack traces are enabled to ensure stack trace functionality works |
| 276 | timeout = ( |
| 277 | 120 if enable_stack_trace else None |
| 278 | ) # 2 minutes timeout for stack traces |
| 279 | |
| 280 | process = RunningProcess( |
| 281 | command=cmd, |
| 282 | cwd=_PROJECT_ROOT, |
| 283 | check=False, |
| 284 | shell=False, |
| 285 | auto_run=True, |
| 286 | timeout=timeout, |
| 287 | output_formatter=TimestampFormatter(), |
| 288 | ) |
| 289 | |
| 290 | with process.line_iter(timeout=30) as it: |
| 291 | if _ABORT_EVENT.is_set(): |
| 292 | return TestResult( |
| 293 | name=test_file.stem, |
| 294 | success=False, |
| 295 | duration=time.time() - start_time, |
| 296 | output="Test execution interrupted by user", |
| 297 | captured_lines=[], |
| 298 | return_code=130, # SIGINT equivalent |
| 299 | ) |
| 300 | for line in it: |
| 301 | captured_lines.append(line) |
| 302 | # Only print output if verbose is enabled |
| 303 | if verbose: |
| 304 | print(line) |
| 305 | |
| 306 | # Wait for process to complete |
| 307 | process.wait() |
| 308 | return_code = process.poll() |
| 309 | success = return_code == 0 |
nothing calls this directly
no test coverage detected