Skip to content

Commit

Permalink
Added OpenAPI validation to tests
Browse files Browse the repository at this point in the history
We now generate and validate OpenAPI descriptions in both
test_openapi and test_td
  • Loading branch information
rwb27 committed Jul 21, 2021
1 parent bfc6fc4 commit a100fa9
Show file tree
Hide file tree
Showing 2 changed files with 47 additions and 17 deletions.
21 changes: 17 additions & 4 deletions tests/test_openapi.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,26 @@
"""Test OpenAPI spec generation
This file tests the OpenAPI spec generated by LabThings.
NB in order to avoid duplicating the examples, OpenAPI spec validation is also
done in test_td.py.
"""

import pytest

from labthings import fields, schema
from labthings.actions.thread import ActionThread
from labthings.extensions import BaseExtension
from labthings.views import ActionView, PropertyView, EventView
from marshmallow import validate
from apispec.utils import validate_spec

def test_openapi(thing, action_view_cls):
action_view_cls.args = {"n": fields.Integer()}
thing.add_view(action_view_cls, "TestAction")
def test_openapi(thing):
"""Make an example Thing and check its openapi description validates"""
class TestAction(ActionView):
args = {"n": fields.Integer()}
def post(self):
return "POST"
thing.add_view(TestAction, "TestAction")

class TestProperty(PropertyView):
schema = {"count": fields.Integer()}
Expand All @@ -27,4 +39,5 @@ def post(self, args):
thing.add_view(TestFieldProperty, "TestFieldProperty")


thing.spec.to_yaml()
thing.spec.to_yaml()
validate_spec(thing.spec)
43 changes: 30 additions & 13 deletions tests/test_td.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,22 @@

from labthings import fields
from labthings.views import ActionView, PropertyView, View, op
from apispec.utils import validate_spec


@pytest.fixture
def thing_description(thing):
return thing.thing_description


def test_td_init(helpers, thing_description, app_ctx, schemas_path):
def test_td_init(helpers, thing, thing_description, app_ctx, schemas_path):
assert thing_description
helpers.validate_thing_description(thing_description, app_ctx, schemas_path)
validate_spec(thing.spec)


def test_td_add_link(helpers, thing_description, view_cls, app_ctx, schemas_path):
def test_td_add_link(helpers, thing, thing_description, view_cls, app_ctx, schemas_path):
thing.add_view(view_cls, "/test_view_cls")
thing_description.add_link(view_cls, "rel")
assert {
"rel": "rel",
Expand All @@ -24,9 +27,10 @@ def test_td_add_link(helpers, thing_description, view_cls, app_ctx, schemas_path
} in thing_description._links

helpers.validate_thing_description(thing_description, app_ctx, schemas_path)
validate_spec(thing.spec)


def test_td_add_link_options(thing_description, view_cls):
def test_td_add_link_options(thing, thing_description, view_cls):
thing_description.add_link(
view_cls, "rel", kwargs={"kwarg": "kvalue"}, params={"param": "pvalue"}
)
Expand All @@ -36,9 +40,10 @@ def test_td_add_link_options(thing_description, view_cls):
"params": {"param": "pvalue"},
"kwargs": {"kwarg": "kvalue"},
} in thing_description._links
validate_spec(thing.spec)


def test_td_links(thing_description, app_ctx, view_cls):
def test_td_links(thing, thing_description, app_ctx, view_cls):
thing_description.add_link(
view_cls, "rel", kwargs={"kwarg": "kvalue"}, params={"param": "pvalue"}
)
Expand All @@ -47,9 +52,10 @@ def test_td_links(thing_description, app_ctx, view_cls):
assert {"rel": "rel", "href": "", "kwarg": "kvalue"} in (
thing_description.links
)
validate_spec(thing.spec)


def test_td_action(helpers, app, thing_description, app_ctx, schemas_path):
def test_td_action(helpers, thing, app, thing_description, app_ctx, schemas_path):
class Index(ActionView):
def post(self):
return "POST"
Expand All @@ -62,9 +68,10 @@ def post(self):
with app_ctx.test_request_context():
assert "index" in thing_description.to_dict().get("actions")
helpers.validate_thing_description(thing_description, app_ctx, schemas_path)
validate_spec(thing.spec)


def test_td_action_with_schema(helpers, app, thing_description, app_ctx, schemas_path):
def test_td_action_with_schema(helpers, thing, app, thing_description, app_ctx, schemas_path):
class Index(ActionView):
args = {"integer": fields.Int()}
semtype = "ToggleAction"
Expand All @@ -80,9 +87,11 @@ def post(self):
with app_ctx.test_request_context():
assert "index" in thing_description.to_dict().get("actions")
helpers.validate_thing_description(thing_description, app_ctx, schemas_path)

validate_spec(thing.spec)


def test_td_property(helpers, app, thing_description, app_ctx, schemas_path):
def test_td_property(helpers, app, thing, thing_description, app_ctx, schemas_path):
class Index(PropertyView):
def get(self):
return "GET"
Expand All @@ -95,10 +104,11 @@ def get(self):
with app_ctx.test_request_context():
assert "index" in thing_description.to_dict().get("properties")
helpers.validate_thing_description(thing_description, app_ctx, schemas_path)
validate_spec(thing.spec)


def test_td_property_with_schema(
helpers, app, thing_description, app_ctx, schemas_path
helpers, app, thing, thing_description, app_ctx, schemas_path
):
class Index(PropertyView):
schema = fields.Int(required=True)
Expand All @@ -114,10 +124,11 @@ def get(self):
with app_ctx.test_request_context():
assert "index" in thing_description.to_dict().get("properties")
helpers.validate_thing_description(thing_description, app_ctx, schemas_path)
validate_spec(thing.spec)


def test_td_property_with_url_param(
helpers, app, thing_description, app_ctx, schemas_path
helpers, app, thing, thing_description, app_ctx, schemas_path
):
class Index(PropertyView):
def get(self):
Expand All @@ -131,9 +142,10 @@ def get(self):
with app_ctx.test_request_context():
assert "index" in thing_description.to_dict().get("properties")
helpers.validate_thing_description(thing_description, app_ctx, schemas_path)
validate_spec(thing.spec)


def test_td_property_write_only(helpers, app, thing_description, app_ctx, schemas_path):
def test_td_property_write_only(helpers, app, thing, thing_description, app_ctx, schemas_path):
class Index(PropertyView):
schema = fields.Int()

Expand All @@ -148,10 +160,12 @@ def put(self):
with app_ctx.test_request_context():
assert "index" in thing_description.to_dict().get("properties")
helpers.validate_thing_description(thing_description, app_ctx, schemas_path)

validate_spec(thing.spec)


def test_td_property_post_to_write(
helpers, app, thing_description, app_ctx, schemas_path
helpers, app, thing, thing_description, app_ctx, schemas_path
):
class Index(PropertyView):
@op.writeproperty
Expand All @@ -177,10 +191,11 @@ def post(self):
== "POST"
)
helpers.validate_thing_description(thing_description, app_ctx, schemas_path)
validate_spec(thing.spec)


def test_td_property_different_content_type(
helpers, app, thing_description, app_ctx, schemas_path
helpers, app, thing, thing_description, app_ctx, schemas_path
):
class Index(PropertyView):
content_type = "text/plain; charset=us-ascii"
Expand All @@ -198,10 +213,11 @@ def put(self):
for form in thing_description.to_dict()["properties"]["index"]["forms"]:
assert form["contentType"] == "text/plain; charset=us-ascii"
helpers.validate_thing_description(thing_description, app_ctx, schemas_path)
validate_spec(thing.spec)


def test_td_action_different_response_type(
helpers, app, thing_description, app_ctx, schemas_path
helpers, app, thing, thing_description, app_ctx, schemas_path
):
class Index(ActionView):
schema = fields.Int()
Expand All @@ -220,3 +236,4 @@ def post(self):
for form in thing_description.to_dict()["actions"]["index"]["forms"]:
assert form["response"]["contentType"] == "text/plain; charset=us-ascii"
helpers.validate_thing_description(thing_description, app_ctx, schemas_path)
validate_spec(thing.spec)

0 comments on commit a100fa9

Please sign in to comment.