Problem
We are seeing intermittent missing results in Qase TestOps when using qase-pytest in CI with pytest-xdist.
The test run itself completes, but one of the background result-sending threads fails with a transient network error:
/usr/local/lib/python3.13/site-packages/_pytest/threadexception.py:58: PytestUnhandledThreadExceptionWarning: Exception in thread Thread-720 (_send_results_threaded)
ConnectionResetError: [Errno 104] Connection reset by peer
During handling of the above exception, another exception occurred:
File "/usr/local/lib/python3.13/site-packages/qase/commons/reporters/testops.py", line 73, in _send_results_threaded
self.client.send_results(self.project_code, self.run_id, results)
File "/usr/local/lib/python3.13/site-packages/qase/commons/client/api_v2_client.py", line 133, in send_results
api_results.create_results_v2(...)
File "/usr/local/lib/python3.13/site-packages/qase/api_client_v2/rest.py", line 189, in request
r = self.pool_manager.request(...)
urllib3.exceptions.ProtocolError: ('Connection aborted.', ConnectionResetError(104, 'Connection reset by peer'))
After this happens, the pytest process continues and prints the final summary, but the affected batch of results may be missing in Qase.
Environment
Python: 3.13.14
pytest: 9.0.3
pytest-xdist: 3.8.0
qase-pytest: 8.3.1
qase-python-commons: 5.1.2
urllib3: 2.7.0
Run mode:
--qase-mode=testops
pytest-xdist enabled: -n 4
batch size: 25-50
custom Qase host / proxy is used
Current behavior
When send_results() fails due to a transient network issue such as:
•ConnectionResetError
•urllib3.exceptions.ProtocolError
•ReadTimeoutError
•HTTP 429
•HTTP 5xx
the background thread raises an exception. The exception is reported by pytest as PytestUnhandledThreadExceptionWarning, but the result batch is not retried.
This can lead to missing test results in Qase even though the pytest run has completed.
Expected behavior
qase-pytest / qase-python-commons should retry transient failures when sending result batches to TestOps.
Suggested behavior:
1.Retry send_results() for transient network/API failures.
2.Use bounded retry with exponential backoff.
3.Respect Retry-After for HTTP 429 if available.
4.Make retry settings configurable, for example:
{
"testops": {
"api": {
"timeout": 30,
"retries": 3,
"retryBackoff": 2
}
}
}
5.If all retries fail, the plugin should either:
◦fail the pytest run explicitly, or
◦clearly log that a specific batch was not delivered.
At minimum, the failed batch should not be silently lost.
Why this matters
In large parallel CI runs, transient network/proxy failures are expected occasionally. Without retry, one temporary ConnectionResetError can cause missing results in Qase TestOps.
Reducing batch size limits the damage, but does not solve the underlying reliability issue.
Problem
We are seeing intermittent missing results in Qase TestOps when using
qase-pytestin CI withpytest-xdist.The test run itself completes, but one of the background result-sending threads fails with a transient network error:
After this happens, the pytest process continues and prints the final summary, but the affected batch of results may be missing in Qase.
Environment
Python: 3.13.14
pytest: 9.0.3
pytest-xdist: 3.8.0
qase-pytest: 8.3.1
qase-python-commons: 5.1.2
urllib3: 2.7.0
Run mode:
--qase-mode=testops
pytest-xdist enabled: -n 4
batch size: 25-50
custom Qase host / proxy is used
Current behavior
When send_results() fails due to a transient network issue such as:
•ConnectionResetError
•urllib3.exceptions.ProtocolError
•ReadTimeoutError
•HTTP 429
•HTTP 5xx
the background thread raises an exception. The exception is reported by pytest as PytestUnhandledThreadExceptionWarning, but the result batch is not retried.
This can lead to missing test results in Qase even though the pytest run has completed.
Expected behavior
qase-pytest / qase-python-commons should retry transient failures when sending result batches to TestOps.
Suggested behavior:
1.Retry send_results() for transient network/API failures.
2.Use bounded retry with exponential backoff.
3.Respect Retry-After for HTTP 429 if available.
4.Make retry settings configurable, for example:
5.If all retries fail, the plugin should either:
◦fail the pytest run explicitly, or
◦clearly log that a specific batch was not delivered.
At minimum, the failed batch should not be silently lost.
Why this matters
In large parallel CI runs, transient network/proxy failures are expected occasionally. Without retry, one temporary ConnectionResetError can cause missing results in Qase TestOps.
Reducing batch size limits the damage, but does not solve the underlying reliability issue.