Skip to content

Commit

Permalink
Replace mocks with vcr casettes for testing
Browse files Browse the repository at this point in the history
  • Loading branch information
pi-sigma committed Jul 29, 2024
1 parent c9ad920 commit b4de020
Show file tree
Hide file tree
Showing 8 changed files with 824 additions and 98 deletions.
608 changes: 608 additions & 0 deletions fixtures/cassettes/forms.yaml

Large diffs are not rendered by default.

126 changes: 126 additions & 0 deletions fixtures/cassettes/invalid.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
interactions:
- request:
body: null
headers:
Accept:
- '*/*'
Accept-Encoding:
- gzip, deflate
Connection:
- keep-alive
User-Agent:
- python-requests/2.32.3
method: GET
uri: https://open-forms.test.maykin.opengem.nl/api/v2/public/forms
response:
body:
string: '{"type":"https://open-forms.test.maykin.opengem.nl/fouten/AuthenticationFailed/","code":"authentication_failed","title":"Ongeldige
authenticatiegegevens.","status":401,"detail":"Ongeldige token.","instance":"urn:uuid:36d7c1d6-7ca9-4780-a38a-0eab4b420b0c"}'
headers:
Allow:
- GET, HEAD, OPTIONS
Cache-Control:
- max-age=0, no-cache, no-store, must-revalidate, private
Connection:
- keep-alive
Content-Language:
- nl
Content-Length:
- '255'
Content-Type:
- application/json
Cross-Origin-Opener-Policy:
- same-origin
Date:
- Thu, 25 Jul 2024 15:14:44 GMT
Expires:
- Thu, 25 Jul 2024 15:14:44 GMT
Pragma:
- no-cache
Referrer-Policy:
- same-origin
Set-Cookie:
- csrftoken=Xhb4tpwoBaR28U9sfZQeuWyJBNOchZND; expires=Thu, 24 Jul 2025 15:14:44
GMT; Max-Age=31449600; Path=/; SameSite=None; Secure
- openforms_sessionid=xdvobged1qd5ugph7n7eq8bws408zioq; expires=Thu, 25 Jul
2024 15:19:44 GMT; HttpOnly; Max-Age=300; Path=/; SameSite=None; Secure
Strict-Transport-Security:
- max-age=63072000
Vary:
- Cookie, Origin, Accept-Language
WWW-Authenticate:
- Token
X-CSRFToken:
- yjZUSvrMevpC5Lv2uZXfsnNABMz1JYg1lq0ObKN0Fv6u3vukzODjM9b92pd3QNTu
X-Content-Type-Options:
- nosniff
X-Frame-Options:
- DENY
X-Session-Expires-In:
- '300'
status:
code: 401
message: Unauthorized
- request:
body: null
headers:
Accept:
- '*/*'
Accept-Encoding:
- gzip, deflate
Connection:
- keep-alive
User-Agent:
- python-requests/2.32.3
method: GET
uri: https://open-forms.test.maykin.opengem.nl/api/v2/forms/9c65ab49-2635-4c8d-ac22-aaca67044a6c
response:
body:
string: '{"type":"https://open-forms.test.maykin.opengem.nl/fouten/AuthenticationFailed/","code":"authentication_failed","title":"Ongeldige
authenticatiegegevens.","status":401,"detail":"Ongeldige token.","instance":"urn:uuid:d88e38cd-610d-4127-b516-346f7cf42d68"}'
headers:
Allow:
- GET, PUT, PATCH, DELETE, HEAD, OPTIONS
Cache-Control:
- max-age=0, no-cache, no-store, must-revalidate, private
Connection:
- keep-alive
Content-Language:
- nl
Content-Length:
- '255'
Content-Type:
- application/json
Cross-Origin-Opener-Policy:
- same-origin
Date:
- Thu, 25 Jul 2024 15:14:45 GMT
Expires:
- Thu, 25 Jul 2024 15:14:45 GMT
Pragma:
- no-cache
Referrer-Policy:
- same-origin
Set-Cookie:
- csrftoken=fssc6e9RxjWYWKFrPFsysEWMn2B0mVIn; expires=Thu, 24 Jul 2025 15:14:45
GMT; Max-Age=31449600; Path=/; SameSite=None; Secure
- openforms_sessionid=pcq36jjqocc3hf14in5xl878idlwahz4; expires=Thu, 25 Jul
2024 15:19:45 GMT; HttpOnly; Max-Age=300; Path=/; SameSite=None; Secure
Strict-Transport-Security:
- max-age=63072000
Vary:
- Cookie, Origin, Accept-Language
WWW-Authenticate:
- Token
X-CSRFToken:
- U9b9A6hsLxMPNMSk7GopmhqeCRWVWJa7Zrtbwag98GyDzmnBMbGNELcQPJnL8uIk
X-Content-Type-Options:
- nosniff
X-Frame-Options:
- DENY
X-Session-Expires-In:
- '300'
status:
code: 401
message: Unauthorized
version: 1
27 changes: 17 additions & 10 deletions setup.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -34,14 +34,18 @@ install_requires =
django-solo
requests
tests_require =
requests-mock
pytest
pytest-django
tox
isort
black
flake8
isort
pytest
pytest-django
python-decouple
pyyaml
requests
requests-mock
time-machine
tox
vcrpy

[options.packages.find]
include =
Expand All @@ -50,14 +54,17 @@ include =

[options.extras_require]
tests =
requests-mock
pytest
pytest-django
tox
isort
black
flake8
isort
pytest
pytest-django
python-decouple
pyyaml
requests-mock
time-machine
tox
vcrpy
pep8 = flake8
coverage = pytest-cov
docs =
Expand Down
17 changes: 17 additions & 0 deletions tests/conftest.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import pytest
from decouple import config

from openformsclient.client import Client

API_ROOT = config("OFC_API_ROOT")
API_TOKEN = config("OFC_API_TOKEN")


@pytest.fixture
def client():
return Client(api_root=API_ROOT, api_token=API_TOKEN, client_timeout=2)


@pytest.fixture
def bogus_client():
return Client(api_root=API_ROOT, api_token="bogus", client_timeout=2)
Empty file added tests/data/__init__.py
Empty file.
6 changes: 6 additions & 0 deletions tests/data/forms.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
form1 = {
"uuid": "9c65ab49-2635-4c8d-ac22-aaca67044a6c",
"name": "Open Inwoner ZGW Dev",
"internalName": "",
"slug": "open-inwoner-zgw-dev",
}
134 changes: 48 additions & 86 deletions tests/test_client.py
Original file line number Diff line number Diff line change
@@ -1,91 +1,53 @@
from unittest.mock import patch

from django.test import TestCase

import requests_mock
import pytest
import vcr
from requests.exceptions import HTTPError

from openformsclient.client import Client

from .data.forms import form1

VCR_DEFAULTS = {
"record_mode": "none", # use new_episodes to record casettes
"filter_headers": ["authorization"],
}


def test_client_has_config(client):
bogus_client = Client("", "", "")

assert client.has_config()
assert not bogus_client.has_config()


@vcr.use_cassette("fixtures/cassettes/forms.yaml", **VCR_DEFAULTS)
def test_client_is_healthy(client):
health, msg = client.is_healthy()
assert health
assert msg == ""


@vcr.use_cassette("fixtures/cassettes/forms.yaml", **VCR_DEFAULTS)
def test_get_forms(client):
results = client.get_forms()["results"]

assert form1 in results


@vcr.use_cassette("fixtures/cassettes/invalid.yaml", **VCR_DEFAULTS)
def test_get_forms_unauthorized(bogus_client):
with pytest.raises(HTTPError):
bogus_client.get_forms()


@vcr.use_cassette("fixtures/cassettes/forms.yaml", **VCR_DEFAULTS)
def test_get_single_form(client):
result = client.get_form(uuid_or_slug=form1["uuid"])

assert result["uuid"] == form1["uuid"]
assert result["name"] == form1["name"]


@requests_mock.Mocker()
class ClientTests(TestCase):
def setUp(self):
self.api_root = "https://example.com/api/v2/"
self.api_token = "token"
self.client_timeout = 2
self.client = Client(self.api_root, self.api_token, self.client_timeout)

def test_has_config(self, m):
self.assertTrue(self.client.has_config())
self.assertFalse(Client("", "", "").has_config())

def test_is_healthy(self, m):
m.head(
f"{self.api_root}public/forms",
request_headers={"Authorization": f"Token {self.api_token}"},
)

health, msg = self.client.is_healthy()
self.assertTrue(health)
self.assertEqual(msg, "")

def test_is_healthy_invalid_response(self, m):
m.head(f"{self.api_root}public/forms", status_code=500) # Doesn't really matter
m.get(f"{self.api_root}public/forms", text="Woops")

health, msg = self.client.is_healthy()
self.assertFalse(health)
self.assertEqual(msg, "Server did not return a valid response (HTTP 500).")

def test_is_healthy_invalid_token(self, m):
m.head(f"{self.api_root}public/forms", status_code=401)
m.get(
f"{self.api_root}public/forms",
json={
"type": "https://example.com/fouten/AuthenticationFailed/",
"code": "authentication_failed",
"title": "Ongeldige authenticatiegegevens.",
"status": 401,
"detail": "Ongeldige token.",
"instance": "urn:uuid:8dddcb04-a412-451a-a7c5-f77d1aef36f5",
},
)

health, msg = self.client.is_healthy()
self.assertFalse(health)
self.assertEqual(msg, "Ongeldige token.")

def test_get_forms(self, m):
m.get(f"{self.api_root}public/forms", json=[])

result = self.client.get_forms()
self.assertListEqual(result, [])

def test_get_forms_with_error(self, m):
m.get(f"{self.api_root}public/forms", status_code=401)

with self.assertRaises(HTTPError):
self.client.get_forms()

def test_get_form(self, m):
m.get(f"{self.api_root}forms/myform", json={})

result = self.client.get_form("myform")
self.assertDictEqual(result, {})

def test_get_form_with_error(self, m):
m.get(f"{self.api_root}forms/myform", status_code=401)

with self.assertRaises(HTTPError):
self.client.get_form("myform")

def test_request_uses_configured_timeout(self, m):
with patch("openformsclient.client.requests.request") as mock_request:
self.client.get_form("myform")
mock_request.assert_called_with(
"get",
"https://example.com/api/v2/forms/myform",
headers={"Authorization": "Token token"},
timeout=2,
)
@vcr.use_cassette("fixtures/cassettes/invalid.yaml", **VCR_DEFAULTS)
def test_get_single_form_unauthorized(bogus_client):
with pytest.raises(HTTPError):
bogus_client.get_form(uuid_or_slug=form1["uuid"])
4 changes: 2 additions & 2 deletions tox.ini
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
[tox]
envlist =
py{37,38,39,310}-django{32}
py{38,39,310}-django{40}
py{39,310,311}-django{32}
py{39,310,311}-django{40}
isort
black
flake8
Expand Down

0 comments on commit b4de020

Please sign in to comment.