Skip to content

qase-pytest should retry transient failures in result upload #504

Description

@ArtyrKa1300

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions