Skip to content

Commit a9ae466

Browse files
feature: add retry to datasets tests
1 parent 9da4616 commit a9ae466

2 files changed

Lines changed: 353 additions & 31 deletions

File tree

tests/test_datasets.py

Lines changed: 190 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,10 @@
1+
import socket
2+
import urllib.error
3+
4+
import pytest
5+
16
from wefe.datasets.datasets import (
7+
_retry_request,
28
fetch_debias_multiclass,
39
fetch_debiaswe,
410
fetch_eds,
@@ -137,6 +143,7 @@ def test_load_weat() -> None:
137143
"weapons",
138144
"european_american_names_5",
139145
"african_american_names_5",
146+
"unpleasant_5b",
140147
"european_american_names_7",
141148
"african_american_names_7",
142149
"pleasant_9",
@@ -180,3 +187,186 @@ def test_load_gn_glove() -> None:
180187
for word in set_:
181188
assert isinstance(word, str)
182189
assert len(word) > 0
190+
191+
192+
# Tests for retry functionality
193+
class TestRetryRequest:
194+
"""Test cases for the _retry_request function."""
195+
196+
def test_retry_request_success_on_first_attempt(self):
197+
"""Test _retry_request result when function succeeds on first attempt."""
198+
from unittest.mock import Mock
199+
200+
mock_func = Mock(return_value="success")
201+
202+
result = _retry_request(mock_func, "arg1", "arg2", kwarg1="value1")
203+
204+
assert result == "success"
205+
mock_func.assert_called_once_with("arg1", "arg2", kwarg1="value1")
206+
207+
def test_retry_request_rate_limit_error(self, monkeypatch):
208+
"""Test retry behavior for HTTP 429 rate limit errors."""
209+
from unittest.mock import Mock
210+
211+
mock_sleep = Mock()
212+
mock_warning = Mock()
213+
monkeypatch.setattr("time.sleep", mock_sleep)
214+
monkeypatch.setattr("logging.warning", mock_warning)
215+
216+
mock_func = Mock()
217+
218+
# Create HTTPError with code 429
219+
from email.message import EmailMessage
220+
221+
headers = EmailMessage()
222+
http_error = urllib.error.HTTPError(
223+
url="http://test.com",
224+
code=429,
225+
msg="Too Many Requests",
226+
hdrs=headers,
227+
fp=None,
228+
)
229+
230+
# First two calls fail with 429, third succeeds
231+
mock_func.side_effect = [http_error, http_error, "success"]
232+
233+
result = _retry_request(mock_func, n_retries=3)
234+
235+
assert result == "success"
236+
assert mock_func.call_count == 3
237+
assert mock_sleep.call_count == 2
238+
assert mock_warning.call_count == 2
239+
240+
# Check exponential backoff sleep times
241+
mock_sleep.assert_any_call(1) # 2^0 = 1
242+
mock_sleep.assert_any_call(2) # 2^1 = 2
243+
244+
def test_retry_request_timeout_error(self, monkeypatch):
245+
"""Test retry behavior for timeout errors."""
246+
from unittest.mock import Mock
247+
248+
mock_sleep = Mock()
249+
mock_warning = Mock()
250+
monkeypatch.setattr("time.sleep", mock_sleep)
251+
monkeypatch.setattr("logging.warning", mock_warning)
252+
253+
mock_func = Mock()
254+
255+
# First call fails with timeout, second succeeds
256+
mock_func.side_effect = [socket.timeout("Connection timeout"), "success"]
257+
258+
result = _retry_request(mock_func, n_retries=2)
259+
260+
assert result == "success"
261+
assert mock_func.call_count == 2
262+
mock_sleep.assert_called_once_with(1) # 2^0 = 1
263+
mock_warning.assert_called_once()
264+
265+
def test_retry_request_timeout_error_os_error(self, monkeypatch):
266+
"""Test retry behavior for OSError (network timeout)."""
267+
from unittest.mock import Mock
268+
269+
mock_sleep = Mock()
270+
mock_warning = Mock()
271+
monkeypatch.setattr("time.sleep", mock_sleep)
272+
monkeypatch.setattr("logging.warning", mock_warning)
273+
274+
mock_func = Mock()
275+
276+
# First call fails with OSError, second succeeds
277+
mock_func.side_effect = [OSError("Network timeout"), "success"]
278+
279+
result = _retry_request(mock_func, n_retries=2)
280+
281+
assert result == "success"
282+
assert mock_func.call_count == 2
283+
mock_sleep.assert_called_once_with(1) # 2^0 = 1
284+
mock_warning.assert_called_once()
285+
286+
def test_retry_request_generic_exception(self, monkeypatch):
287+
"""Test retry behavior for generic exceptions."""
288+
from unittest.mock import Mock
289+
290+
mock_sleep = Mock()
291+
mock_warning = Mock()
292+
monkeypatch.setattr("time.sleep", mock_sleep)
293+
monkeypatch.setattr("logging.warning", mock_warning)
294+
295+
mock_func = Mock()
296+
297+
# First call fails with generic exception, second succeeds
298+
mock_func.side_effect = [ValueError("Generic error"), "success"]
299+
300+
result = _retry_request(mock_func, n_retries=2)
301+
302+
assert result == "success"
303+
assert mock_func.call_count == 2
304+
mock_sleep.assert_called_once_with(1) # Fixed 1-second delay
305+
mock_warning.assert_called_once()
306+
307+
def test_retry_request_non_retryable_http_error(self):
308+
"""Test that non-retryable HTTP errors are not retried."""
309+
from unittest.mock import Mock
310+
311+
mock_func = Mock()
312+
313+
# 404 Not Found should not be retried
314+
from email.message import EmailMessage
315+
316+
headers = EmailMessage()
317+
http_error = urllib.error.HTTPError(
318+
url="http://test.com", code=404, msg="Not Found", hdrs=headers, fp=None
319+
)
320+
mock_func.side_effect = http_error
321+
322+
with pytest.raises(urllib.error.HTTPError) as exc_info:
323+
_retry_request(mock_func, n_retries=3)
324+
325+
assert exc_info.value.code == 404
326+
mock_func.assert_called_once() # Should only be called once
327+
328+
def test_retry_request_exhaust_retries(self, monkeypatch):
329+
"""Test that function raises exception when all retries are exhausted."""
330+
from unittest.mock import Mock
331+
332+
mock_sleep = Mock()
333+
mock_warning = Mock()
334+
monkeypatch.setattr("time.sleep", mock_sleep)
335+
monkeypatch.setattr("logging.warning", mock_warning)
336+
337+
mock_func = Mock()
338+
339+
# Always fail with rate limit error
340+
from email.message import EmailMessage
341+
342+
headers = EmailMessage()
343+
http_error = urllib.error.HTTPError(
344+
url="http://test.com",
345+
code=429,
346+
msg="Too Many Requests",
347+
hdrs=headers,
348+
fp=None,
349+
)
350+
mock_func.side_effect = http_error
351+
352+
with pytest.raises(urllib.error.HTTPError) as exc_info:
353+
_retry_request(mock_func, n_retries=2)
354+
355+
assert exc_info.value.code == 429
356+
assert mock_func.call_count == 3 # Initial call + 2 retries
357+
assert mock_sleep.call_count == 2
358+
assert mock_warning.call_count == 2
359+
360+
def test_retry_request_url_error(self):
361+
"""Test that URLError without code is not retried."""
362+
from unittest.mock import Mock
363+
364+
mock_func = Mock()
365+
366+
url_error = urllib.error.URLError("Connection failed")
367+
mock_func.side_effect = url_error
368+
369+
with pytest.raises(urllib.error.URLError):
370+
_retry_request(mock_func, n_retries=3)
371+
372+
mock_func.assert_called_once() # Should only be called once

0 commit comments

Comments
 (0)