Repository: cdent/gabbi

Issue:
Tests don't retry after `httpx.ReadTimeout` even with `poll` set
Example test:
```yaml
---
tests:
  - name: Poll test
    url: https://httpstat.us/200?sleep=3000
    timeout: 1
    poll:
      count: 3
```

It fails after the first request:
```text
... #### Poll test ####
> GET https://httpstat.us/200?sleep=3000
> user-agent: gabbi/4.1.0 (Python httpx)
E gabbi-runner.input_poll_test

ERROR: gabbi-runner.input_poll_test
        The read operation timed out
----------------------------------------------------------------------
Ran 1 test in 1.367s

FAILED (errors=1)
```

Discussion:

Fix (patch):
diff --git a/gabbi/case.py b/gabbi/case.py
index 1199032..cdbd9aa 100644
--- a/gabbi/case.py
+++ b/gabbi/case.py
@@ -21,6 +21,7 @@ from collections import OrderedDict
 import copy
 import functools
 from http import cookies
+import httpx
 import numbers
 import os
 import re
@@ -592,7 +593,11 @@ class HTTPTestCase(unittest.TestCase):
                     self._assert_response()
                     failure = None
                     break
-                except (AssertionError, utils.ConnectionRefused) as exc:
+                except (
+                    AssertionError,
+                    utils.ConnectionRefused,
+                    httpx.ReadTimeout
+                ) as exc:
                     failure = exc
 
                 count -= 1


Test changes:
diff --git a/gabbi/tests/test_runner.py b/gabbi/tests/test_runner.py
index ac6d775..0f257ed 100644
--- a/gabbi/tests/test_runner.py
+++ b/gabbi/tests/test_runner.py
@@ -13,6 +13,7 @@
 """Test that the CLI works as expected
 """
 
+import httpx
 from io import StringIO
 import os
 import socket
@@ -20,6 +21,7 @@ import subprocess
 import sys
 import time
 import unittest
+from unittest import mock
 
 from gabbi import exception
 from gabbi.handlers import base
@@ -382,6 +384,31 @@ class RunnerTest(unittest.TestCase):
         self.assertEqual('', stdoutput)
         self.assertEqual('', stderror)
 
+    def test_poll_with_timeout(self):
+        """Confirm poll works with a HTTP timeout"""
+        sys.stdin = StringIO(
+            """
+        tests:
+        - name: expected success after multiple attempts
+          POST: /
+          poll:
+            count: 3
+        """
+        )
+
+        with mock.patch(
+            "httpx.Client.request",
+            side_effect=[
+                httpx.ReadTimeout("Read timeout"),
+                httpx.ReadTimeout("Read timeout"),
+                httpx.Response(200),
+            ],
+        ):
+            try:
+                runner.run()
+            except SystemExit as err:
+                self.assertSuccess(err)
+
     def assertSuccess(self, exitError):
         errors = exitError.args[0]
         if errors: