Skip to content

Commit

Permalink
Refactor integration tests to have no side-effects (#3544)
Browse files Browse the repository at this point in the history
Co-authored-by: sarayourfriend <[email protected]>
Co-authored-by: Madison Swain-Bowden <[email protected]>
  • Loading branch information
3 people authored Feb 13, 2024
1 parent 0c92ab5 commit 01cce2e
Show file tree
Hide file tree
Showing 18 changed files with 740 additions and 1,504 deletions.
473 changes: 0 additions & 473 deletions api/test/api_live_integration.py

This file was deleted.

43 changes: 0 additions & 43 deletions api/test/api_live_search_qa.py

This file was deleted.

5 changes: 5 additions & 0 deletions api/test/conftest.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
"""Fixtures usable by or necessary for both unit and integration tests."""

from test.fixtures.asynchronous import ensure_asgi_lifecycle, get_new_loop, session_loop
from test.fixtures.cache import (
django_cache,
redis,
unreachable_django_cache,
unreachable_redis,
)
from test.fixtures.rest_framework import api_client, request_factory


__all__ = [
Expand All @@ -15,4 +18,6 @@
"redis",
"unreachable_django_cache",
"unreachable_redis",
"api_client",
"request_factory",
]
15 changes: 15 additions & 0 deletions api/test/fixtures/rest_framework.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
from rest_framework.test import APIClient, APIRequestFactory

import pytest


@pytest.fixture
def api_client():
return APIClient()


@pytest.fixture
def request_factory() -> APIRequestFactory():
request_factory = APIRequestFactory(defaults={"REMOTE_ADDR": "192.0.2.1"})

return request_factory
13 changes: 13 additions & 0 deletions api/test/integration/conftest.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import pytest


@pytest.fixture
def django_db_setup():
"""
We want the integration tests to use the real database so that we can test
the complete behaviour of the system. This fixture overrides the fixture
from ``pytest-django`` that sets up the tests database and because it's a
no-op, the tests will use the real database.
"""

pass
29 changes: 29 additions & 0 deletions api/test/integration/test_audio_integration.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
"""
End-to-end API tests for audio.
Can be used to verify a live deployment is functioning as designed.
Run with the `pytest -s` command from this directory, inside the Docker
container.
Tests common to all media types are in ``test_media_integration.py``.
"""

import pytest


pytestmark = pytest.mark.django_db


def test_audio_detail_without_thumb(api_client):
resp = api_client.get("/v1/audio/44540200-91eb-483d-9e99-38ce86a52fb6/")
assert resp.status_code == 200
parsed = resp.json()
assert parsed["thumbnail"] is None


def test_audio_search_without_thumb(api_client):
"""The first audio of this search should not have a thumbnail."""
resp = api_client.get("/v1/audio/?q=zaus")
assert resp.status_code == 200
parsed = resp.json()
assert parsed["results"][0]["thumbnail"] is None
99 changes: 45 additions & 54 deletions api/test/test_auth.py → api/test/integration/test_auth.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
import time
import uuid
from unittest.mock import patch

from django.urls import reverse
from django.utils.http import urlencode

import pytest
from oauth2_provider.models import AccessToken
Expand Down Expand Up @@ -38,13 +36,13 @@ def unreachable_oauth_cache(unreachable_django_cache, monkeypatch):

@pytest.mark.django_db
@pytest.fixture
def test_auth_tokens_registration(client):
def test_auth_tokens_registration(api_client):
data = {
"name": f"INTEGRATION TEST APPLICATION {uuid.uuid4()}",
"description": "A key for testing the OAuth2 registration process.",
"email": "[email protected]",
}
res = client.post(
res = api_client.post(
"/v1/auth_tokens/register/",
data,
verify=False,
Expand All @@ -56,20 +54,19 @@ def test_auth_tokens_registration(client):

@pytest.mark.django_db
@pytest.fixture
def test_auth_token_exchange(client, test_auth_tokens_registration):
client_id = test_auth_tokens_registration["client_id"]
client_secret = test_auth_tokens_registration["client_secret"]
data = urlencode(
{
"client_id": client_id,
"client_secret": client_secret,
"grant_type": "client_credentials",
}
)
res = client.post(
def test_auth_token_exchange(api_client, test_auth_tokens_registration):
api_client_id = test_auth_tokens_registration["client_id"]
api_client_secret = test_auth_tokens_registration["client_secret"]
data = {
"client_id": api_client_id,
"client_secret": api_client_secret,
"grant_type": "client_credentials",
}

res = api_client.post(
"/v1/auth_tokens/token/",
data,
"application/x-www-form-urlencoded",
"multipart",
verify=False,
)
res_data = res.json()
Expand All @@ -78,20 +75,20 @@ def test_auth_token_exchange(client, test_auth_tokens_registration):


@pytest.mark.django_db
def test_auth_token_exchange_unsupported_method(client):
res = client.get(
def test_auth_token_exchange_unsupported_method(api_client):
res = api_client.get(
"/v1/auth_tokens/token/",
verify=False,
)
assert res.status_code == 405
assert res.json()["detail"] == 'Method "GET" not allowed.'


def _integration_verify_most_recent_token(client):
def _integration_verify_most_recent_token(api_client):
verify = OAuth2Verification.objects.last()
code = verify.code
path = reverse("verify-email", args=[code])
return client.get(path)
return api_client.get(path)


@pytest.mark.django_db
Expand All @@ -110,17 +107,17 @@ def _integration_verify_most_recent_token(client):
)
def test_auth_email_verification(
request,
client,
api_client,
is_cache_reachable,
cache_name,
rate_limit_model,
test_auth_token_exchange,
):
res = _integration_verify_most_recent_token(client)
res = _integration_verify_most_recent_token(api_client)
assert res.status_code == 200
test_auth_rate_limit_reporting(
request,
client,
api_client,
is_cache_reachable,
cache_name,
rate_limit_model,
Expand All @@ -137,7 +134,7 @@ def test_auth_email_verification(
@cache_availability_params
def test_auth_rate_limit_reporting(
request,
client,
api_client,
is_cache_reachable,
cache_name,
rate_limit_model,
Expand All @@ -153,7 +150,7 @@ def test_auth_rate_limit_reporting(
application = AccessToken.objects.get(token=token).application
application.rate_limit_model = rate_limit_model
application.save()
res = client.get("/v1/rate_limit/", HTTP_AUTHORIZATION=f"Bearer {token}")
res = api_client.get("/v1/rate_limit/", HTTP_AUTHORIZATION=f"Bearer {token}")
res_data = res.json()
if is_cache_reachable:
assert res.status_code == 200
Expand All @@ -176,14 +173,14 @@ def test_auth_rate_limit_reporting(
(True, False),
)
def test_auth_response_headers(
client, verified, test_auth_tokens_registration, test_auth_token_exchange
api_client, verified, test_auth_tokens_registration, test_auth_token_exchange
):
if verified:
_integration_verify_most_recent_token(client)
_integration_verify_most_recent_token(api_client)

token = test_auth_token_exchange["access_token"]

res = client.get("/v1/images/", HTTP_AUTHORIZATION=f"Bearer {token}")
res = api_client.get("/v1/images/", HTTP_AUTHORIZATION=f"Bearer {token}")

assert (
res.headers["x-ov-client-application-name"]
Expand All @@ -192,8 +189,8 @@ def test_auth_response_headers(
assert res.headers["x-ov-client-application-verified"] == str(verified)


def test_unauthed_response_headers(client):
res = client.get("/v1/images")
def test_unauthed_response_headers(api_client):
res = api_client.get("/v1/images")

assert "x-ov-client-application-name" not in res.headers
assert "x-ov-client-application-verified" not in res.headers
Expand All @@ -207,21 +204,16 @@ def test_unauthed_response_headers(client):
("asc", "2022-01-01"),
],
)
def test_sorting_authed(client, test_auth_token_exchange, sort_dir, exp_indexed_on):
def test_sorting_authed(api_client, test_auth_token_exchange, sort_dir, exp_indexed_on):
time.sleep(1)
token = test_auth_token_exchange["access_token"]
query_params = {
"unstable__sort_by": "indexed_on",
"unstable__sort_dir": sort_dir,
}
with patch(
"api.views.image_views.ImageViewSet.get_db_results"
) as mock_get_db_result:
mock_get_db_result.side_effect = lambda value: value

res = client.get(
"/v1/images/", query_params, HTTP_AUTHORIZATION=f"Bearer {token}"
)
res = api_client.get(
"/v1/images/", query_params, HTTP_AUTHORIZATION=f"Bearer {token}"
)
assert res.status_code == 200

res_data = res.json()
Expand All @@ -238,7 +230,7 @@ def test_sorting_authed(client, test_auth_token_exchange, sort_dir, exp_indexed_
],
)
def test_authority_authed(
client, test_auth_token_exchange, authority_boost, exp_source
api_client, test_auth_token_exchange, authority_boost, exp_source
):
time.sleep(1)
token = test_auth_token_exchange["access_token"]
Expand All @@ -247,14 +239,9 @@ def test_authority_authed(
"unstable__authority": "true",
"unstable__authority_boost": authority_boost,
}
with patch(
"api.views.image_views.ImageViewSet.get_db_results"
) as mock_get_db_result:
mock_get_db_result.side_effect = lambda value: value

res = client.get(
"/v1/images/", query_params, HTTP_AUTHORIZATION=f"Bearer {token}"
)
res = api_client.get(
"/v1/images/", query_params, HTTP_AUTHORIZATION=f"Bearer {token}"
)
assert res.status_code == 200

res_data = res.json()
Expand All @@ -263,23 +250,27 @@ def test_authority_authed(


@pytest.mark.django_db
def test_page_size_limit_unauthed(client):
def test_page_size_limit_unauthed(api_client):
query_params = {"page_size": 20}
res = client.get("/v1/images/", query_params)
res = api_client.get("/v1/images/", query_params)
assert res.status_code == 200
query_params["page_size"] = 21
res = client.get("/v1/images/", query_params)
res = api_client.get("/v1/images/", query_params)
assert res.status_code == 401


@pytest.mark.django_db
def test_page_size_limit_authed(client, test_auth_token_exchange):
def test_page_size_limit_authed(api_client, test_auth_token_exchange):
time.sleep(1)
token = test_auth_token_exchange["access_token"]
query_params = {"page_size": 21}
res = client.get("/v1/images/", query_params, HTTP_AUTHORIZATION=f"Bearer {token}")
res = api_client.get(
"/v1/images/", query_params, HTTP_AUTHORIZATION=f"Bearer {token}"
)
assert res.status_code == 200

query_params = {"page_size": 500}
res = client.get("/v1/images/", query_params, HTTP_AUTHORIZATION=f"Bearer {token}")
res = api_client.get(
"/v1/images/", query_params, HTTP_AUTHORIZATION=f"Bearer {token}"
)
assert res.status_code == 200
Loading

0 comments on commit 01cce2e

Please sign in to comment.