diff --git a/src/core/runner.py b/src/core/runner.py index 754f467..2c6b36a 100644 --- a/src/core/runner.py +++ b/src/core/runner.py @@ -1,8 +1,43 @@ +import pickle import time -from django.test.runner import DiscoverRunner +from django.test.runner import DiscoverRunner, ParallelTestSuite, RemoteTestRunner + + +class _Py313SafeRemoteTestRunner(RemoteTestRunner): + """Prevents Python 3.13 'cannot pickle traceback' crash in parallel workers. + + In Python 3.13, traceback objects are not picklable. Django's parallel + runner tries to pickle test errors to pass them back to the main process. + When a Selenium test crashes the browser, the resulting exception traceback + fails to pickle, aborting the entire parallel run with a confusing TypeError. + + Fix: strip the traceback (replace with None) before it reaches pickle. + Error type and message are preserved; only the traceback is lost in transit. + """ + + @staticmethod + def _strip_tb_if_needed(err): + exc_type, exc_value, exc_tb = err + try: + pickle.dumps((exc_type, exc_value, exc_tb)) + except (TypeError, AttributeError): + return (exc_type, exc_value, None) + return err + + def addError(self, test, err): + super().addError(test, self._strip_tb_if_needed(err)) + + def addFailure(self, test, err): + super().addFailure(test, self._strip_tb_if_needed(err)) + + +class _SafeParallelTestSuite(ParallelTestSuite): + runner_class = _Py313SafeRemoteTestRunner class RobustCompressorTestRunner(DiscoverRunner): + parallel_test_suite = _SafeParallelTestSuite + def setup_test_environment(self, **kwargs): super().setup_test_environment(**kwargs) from compressor.storage import CompressorFileStorage