tests: Improve HTTP errors reporting
Add helper functions to check HTTP responses in tests implementation.
If an unexpected HTTP status code is encountered, the traceback that led to the error will be displayed in pytest report. See (fake error) example below:
==================================================================================================== FAILURES ====================================================================================================
___________________________________________________________________________________________ test_api_content_filetype ____________________________________________________________________________________________
api_client = <rest_framework.test.APIClient object at 0x7febef719da0>, indexer_data = <swh.web.tests.conftest._IndexerData object at 0x7febef7d74e0>
@given(content())
> def test_api_content_filetype(api_client, indexer_data, content):
swh/web/tests/api/views/test_content.py:21:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
swh/web/tests/api/views/test_content.py:26: in test_api_content_filetype
rv = check_api_get_responses(api_client, url, status_code=200)
swh/web/tests/utils.py:110: in check_api_get_responses
api_client, url, status_code, content_type="application/json"
swh/web/tests/utils.py:62: in check_http_get_response
content_type=content_type,
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
response = <Response status_code=500, "application/json">, status_code = 200, content_type = 'application/json'
def _assert_http_response(
response: HttpResponse, status_code: int, content_type: str
) -> HttpResponse:
if isinstance(response, Response):
drf_response = cast(Response, response)
error_context = (
drf_response.data.pop("traceback")
if isinstance(drf_response.data, dict) and "traceback" in drf_response.data
else drf_response.data
)
else:
error_context = (
getattr(response, "traceback")
if hasattr(response, "traceback")
else response.content
)
> assert response.status_code == status_code, error_context
E AssertionError: Traceback (most recent call last):
E File "/home/anlambert/.virtualenvs/swh/lib/python3.7/site-packages/rest_framework/views.py", line 502, in dispatch
E response = handler(request, *args, **kwargs)
E File "/home/anlambert/.virtualenvs/swh/lib/python3.7/site-packages/rest_framework/decorators.py", line 50, in handler
E return func(*args, **kwargs)
E File "/home/anlambert/swh/swh-environment/swh-web/swh/web/api/apiurls.py", line 92, in api_view_f
E response = f(request, **kwargs)
E File "/home/anlambert/swh/swh-environment/swh-web/swh/web/api/apidoc.py", line 348, in documented_view
E raise exc
E File "/home/anlambert/swh/swh-environment/swh-web/swh/web/api/apidoc.py", line 345, in documented_view
E return {"data": f(request, **kwargs), "doc_data": doc_data}
E File "/home/anlambert/swh/swh-environment/swh-web/swh/web/api/views/content.py", line 65, in api_content_filetype
E request=request,
E File "/home/anlambert/swh/swh-environment/swh-web/swh/web/api/views/utils.py", line 67, in api_lookup
E res = lookup_fn(*args)
E File "/home/anlambert/swh/swh-environment/swh-web/swh/web/common/archive.py", line 182, in lookup_content_filetype
E filetype = _first_element(list(idx_storage.content_mimetype_get([sha1])))
E File "/home/anlambert/swh/swh-environment/swh-indexer/swh/indexer/storage/in_memory.py", line 290, in content_mimetype_get
E return self._mimetypes.get(ds)
E NameError: name 'ds' is not defined
E
E assert 500 == 200
E + where 500 = <Response status_code=500, "application/json">.status_code
swh/web/tests/utils.py:34: AssertionError
____________________________________________________________________________________ test_api_content_filetype_sha_not_found _____________________________________________________________________________________
api_client = <rest_framework.test.APIClient object at 0x7febef719da0>
def test_api_content_filetype_sha_not_found(api_client):
unknown_content_ = random_content()
url = reverse(
"api-1-content-filetype", url_args={"q": "sha1:%s" % unknown_content_["sha1"]}
)
> rv = check_api_get_responses(api_client, url, status_code=404)
swh/web/tests/api/views/test_content.py:44:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
swh/web/tests/utils.py:110: in check_api_get_responses
api_client, url, status_code, content_type="application/json"
swh/web/tests/utils.py:62: in check_http_get_response
content_type=content_type,
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
response = <Response status_code=500, "application/json">, status_code = 404, content_type = 'application/json'
def _assert_http_response(
response: HttpResponse, status_code: int, content_type: str
) -> HttpResponse:
if isinstance(response, Response):
drf_response = cast(Response, response)
error_context = (
drf_response.data.pop("traceback")
if isinstance(drf_response.data, dict) and "traceback" in drf_response.data
else drf_response.data
)
else:
error_context = (
getattr(response, "traceback")
if hasattr(response, "traceback")
else response.content
)
> assert response.status_code == status_code, error_context
E AssertionError: Traceback (most recent call last):
E File "/home/anlambert/.virtualenvs/swh/lib/python3.7/site-packages/rest_framework/views.py", line 502, in dispatch
E response = handler(request, *args, **kwargs)
E File "/home/anlambert/.virtualenvs/swh/lib/python3.7/site-packages/rest_framework/decorators.py", line 50, in handler
E return func(*args, **kwargs)
E File "/home/anlambert/swh/swh-environment/swh-web/swh/web/api/apiurls.py", line 92, in api_view_f
E response = f(request, **kwargs)
E File "/home/anlambert/swh/swh-environment/swh-web/swh/web/api/apidoc.py", line 348, in documented_view
E raise exc
E File "/home/anlambert/swh/swh-environment/swh-web/swh/web/api/apidoc.py", line 345, in documented_view
E return {"data": f(request, **kwargs), "doc_data": doc_data}
E File "/home/anlambert/swh/swh-environment/swh-web/swh/web/api/views/content.py", line 65, in api_content_filetype
E request=request,
E File "/home/anlambert/swh/swh-environment/swh-web/swh/web/api/views/utils.py", line 67, in api_lookup
E res = lookup_fn(*args)
E File "/home/anlambert/swh/swh-environment/swh-web/swh/web/common/archive.py", line 182, in lookup_content_filetype
E filetype = _first_element(list(idx_storage.content_mimetype_get([sha1])))
E File "/home/anlambert/swh/swh-environment/swh-indexer/swh/indexer/storage/in_memory.py", line 290, in content_mimetype_get
E return self._mimetypes.get(ds)
E NameError: name 'ds' is not defined
E
E assert 500 == 404
E + where 500 = <Response status_code=500, "application/json">.status_code
swh/web/tests/utils.py:34: AssertionError
Closes #2657 (closed)
Depends on !428 (closed)
Migrated from D4278 (view on Phabricator)