-
Notifications
You must be signed in to change notification settings - Fork 7
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Using pytest move route test class to functions, where fixtures can b…
…e used to set variables (#330) Change pytest class to functions and use parameterize and fixture features of pytest to make the unit test more concise. Co-authored-by: Casper Welzel Andersen <[email protected]>
- Loading branch information
Showing
6 changed files
with
248 additions
and
193 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,119 +1,106 @@ | ||
import pytest | ||
|
||
from optimade.models import ( | ||
InfoResponse, | ||
EntryInfoResponse, | ||
BaseInfoAttributes, | ||
EntryInfoResource, | ||
) | ||
|
||
from ..utils import EndpointTests | ||
|
||
def test_info_endpoint_attributes(get_good_response, check_keys): | ||
"""Check known properties/attributes for successful response""" | ||
response = get_good_response("/info") | ||
|
||
class TestInfoEndpoint(EndpointTests): | ||
"""Tests for /info""" | ||
assert "data" in response | ||
assert response["data"]["type"] == "info" | ||
assert response["data"]["id"] == "/" | ||
assert "attributes" in response["data"] | ||
attributes = list(BaseInfoAttributes.schema()["properties"].keys()) | ||
check_keys(attributes, response["data"]["attributes"]) | ||
|
||
request_str = "/info" | ||
response_cls = InfoResponse | ||
|
||
def test_info_endpoint_attributes(self): | ||
"""Check known properties/attributes for successful response""" | ||
assert "data" in self.json_response | ||
assert self.json_response["data"]["type"] == "info" | ||
assert self.json_response["data"]["id"] == "/" | ||
assert "attributes" in self.json_response["data"] | ||
attributes = list(BaseInfoAttributes.schema()["properties"].keys()) | ||
self.check_keys(attributes, self.json_response["data"]["attributes"]) | ||
def test_info_structures_endpoint_data(get_good_response, check_keys): | ||
"""Check known properties/attributes for successful response""" | ||
response = get_good_response("/info/structures") | ||
|
||
assert "data" in response | ||
data = EntryInfoResource.schema()["required"] | ||
check_keys(data, response["data"]) | ||
|
||
class TestInfoStructuresEndpoint(EndpointTests): | ||
"""Tests for /info/structures""" | ||
|
||
request_str = "/info/structures" | ||
response_cls = EntryInfoResponse | ||
def test_info_structures_sortable(get_good_response): | ||
"""Check the sortable key is present for all properties""" | ||
response = get_good_response("/info/structures") | ||
|
||
def test_info_structures_endpoint_data(self): | ||
"""Check known properties/attributes for successful response""" | ||
assert "data" in self.json_response | ||
data = EntryInfoResource.schema()["required"] | ||
self.check_keys(data, self.json_response["data"]) | ||
for info_keys in response.get("data", {}).get("properties", {}).values(): | ||
assert "sortable" in info_keys | ||
|
||
def test_info_structures_sortable(self): | ||
"""Check the sortable key is present for all properties""" | ||
for info_keys in ( | ||
self.json_response.get("data", {}).get("properties", {}).values() | ||
): | ||
assert "sortable" in info_keys | ||
|
||
def test_sortable_values(self): | ||
"""Make sure certain properties are and are not sortable""" | ||
sortable = ["id", "nelements", "nsites"] | ||
non_sortable = ["species", "lattice_vectors", "dimension_types"] | ||
def test_sortable_values(get_good_response): | ||
"""Make sure certain properties are and are not sortable""" | ||
response = get_good_response("/info/structures") | ||
sortable = ["id", "nelements", "nsites"] | ||
non_sortable = ["species", "lattice_vectors", "dimension_types"] | ||
|
||
for field in sortable: | ||
sortable_info_value = ( | ||
self.json_response.get("data", {}) | ||
.get("properties", {}) | ||
.get(field, {}) | ||
.get("sortable", None) | ||
) | ||
assert sortable_info_value is not None | ||
assert sortable_info_value is True | ||
|
||
for field in non_sortable: | ||
sortable_info_value = ( | ||
self.json_response.get("data", {}) | ||
.get("properties", {}) | ||
.get(field, {}) | ||
.get("sortable", None) | ||
) | ||
assert sortable_info_value is not None | ||
assert sortable_info_value is False | ||
|
||
def test_info_structures_unit(self): | ||
"""Check the unit key is present for certain properties""" | ||
unit_fields = ["lattice_vectors", "cartesian_site_positions"] | ||
for field, info_keys in ( | ||
self.json_response.get("data", {}).get("properties", {}).items() | ||
): | ||
if field in unit_fields: | ||
assert "unit" in info_keys, f"Field: {field}" | ||
else: | ||
assert "unit" not in info_keys, f"Field: {field}" | ||
|
||
def test_provider_fields(self): | ||
"""Check the presence of AiiDA-specific fields""" | ||
from optimade.server.config import CONFIG | ||
|
||
provider_fields = CONFIG.provider_fields.get("structures", []) | ||
|
||
if not provider_fields: | ||
import warnings | ||
|
||
warnings.warn("No provider-specific fields found for 'structures'!") | ||
return | ||
|
||
for field in provider_fields: | ||
updated_field_name = f"_{CONFIG.provider.prefix}_{field}" | ||
assert updated_field_name in self.json_response.get("data", {}).get( | ||
"properties", {} | ||
) | ||
for field in sortable: | ||
sortable_info_value = ( | ||
response.get("data", {}) | ||
.get("properties", {}) | ||
.get(field, {}) | ||
.get("sortable", None) | ||
) | ||
assert sortable_info_value is not None | ||
assert sortable_info_value is True | ||
|
||
for static_key in ["description", "sortable"]: | ||
assert static_key in self.json_response.get("data", {}).get( | ||
"properties", {} | ||
).get(updated_field_name, {}) | ||
for field in non_sortable: | ||
sortable_info_value = ( | ||
response.get("data", {}) | ||
.get("properties", {}) | ||
.get(field, {}) | ||
.get("sortable", None) | ||
) | ||
assert sortable_info_value is not None | ||
assert sortable_info_value is False | ||
|
||
|
||
@pytest.mark.skip("References has not yet been implemented") | ||
class TestInfoReferencesEndpoint(EndpointTests): | ||
"""Tests for /info/references""" | ||
def test_info_structures_unit(get_good_response): | ||
"""Check the unit key is present for certain properties""" | ||
response = get_good_response("/info/structures") | ||
unit_fields = ["lattice_vectors", "cartesian_site_positions"] | ||
for field, info_keys in response.get("data", {}).get("properties", {}).items(): | ||
if field in unit_fields: | ||
assert "unit" in info_keys, f"Field: {field}" | ||
else: | ||
assert "unit" not in info_keys, f"Field: {field}" | ||
|
||
|
||
def test_provider_fields(get_good_response): | ||
"""Check the presence of AiiDA-specific fields""" | ||
from optimade.server.config import CONFIG | ||
|
||
response = get_good_response("/info/structures") | ||
provider_fields = CONFIG.provider_fields.get("structures", []) | ||
|
||
request_str = "/info/references" | ||
response_cls = EntryInfoResponse | ||
if not provider_fields: | ||
import warnings | ||
|
||
warnings.warn("No provider-specific fields found for 'structures'!") | ||
return | ||
|
||
for field in provider_fields: | ||
updated_field_name = f"_{CONFIG.provider.prefix}_{field}" | ||
assert updated_field_name in response.get("data", {}).get("properties", {}) | ||
|
||
for static_key in ["description", "sortable"]: | ||
assert static_key in response.get("data", {}).get("properties", {}).get( | ||
updated_field_name, {} | ||
) | ||
|
||
|
||
@pytest.mark.skip("References has not yet been implemented") | ||
def test_info_references_endpoint_data(get_good_response, check_keys): | ||
"""Check known properties/attributes for successful response""" | ||
response = get_good_response("/info/reference") | ||
|
||
def test_info_references_endpoint_data(self): | ||
"""Check known properties/attributes for successful response""" | ||
assert "data" in self.json_response | ||
data = EntryInfoResource.schema()["required"] | ||
self.check_keys(data, self.json_response["data"]) | ||
assert "data" in response | ||
data = EntryInfoResource.schema()["required"] | ||
check_keys(data, response["data"]) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,10 +1,5 @@ | ||
from optimade.models import LinksResponse | ||
def test_links(get_good_response): | ||
"""Check /links for successful response""" | ||
response = get_good_response("/links") | ||
|
||
from ..utils import EndpointTests | ||
|
||
|
||
class TestLinksEndpoint(EndpointTests): | ||
"""Tests for /links""" | ||
|
||
request_str = "/links" | ||
response_cls = LinksResponse | ||
assert "data" in response |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,73 @@ | ||
from optimade.models import ( | ||
InfoResponse, | ||
LinksResponse, | ||
EntryInfoResponse, | ||
ReferenceResponseMany, | ||
ReferenceResponseOne, | ||
StructureResponseMany, | ||
StructureResponseOne, | ||
) | ||
from optimade.models import ResponseMeta | ||
|
||
import pytest | ||
|
||
|
||
@pytest.mark.parametrize( | ||
"request_str, ResponseType", | ||
[ | ||
("/info", InfoResponse), | ||
("/info/structures", EntryInfoResponse), | ||
("/links", LinksResponse), | ||
("/structures", StructureResponseMany), | ||
("/structures/0", StructureResponseOne), | ||
pytest.param( | ||
"/references", | ||
ReferenceResponseMany, | ||
marks=pytest.mark.xfail(reason="References has not yet been implemented"), | ||
), | ||
pytest.param( | ||
"/references/dijkstra1968", | ||
ReferenceResponseOne, | ||
marks=pytest.mark.xfail(reason="References has not yet been implemented"), | ||
), | ||
pytest.param( | ||
"/references/dummy/20.19", | ||
ReferenceResponseOne, | ||
marks=pytest.mark.xfail(reason="References has not yet been implemented"), | ||
), | ||
], | ||
) | ||
def test_serialize_response(get_good_response, request_str, ResponseType): | ||
response = get_good_response(request_str) | ||
|
||
ResponseType(**response) | ||
|
||
|
||
@pytest.mark.parametrize( | ||
"request_str", | ||
[ | ||
"/info", | ||
"/info/structures", | ||
"/links", | ||
"/structures", | ||
"structures/0", | ||
pytest.param( | ||
"/references", | ||
marks=pytest.mark.xfail(reason="References has not yet been implemented"), | ||
), | ||
], | ||
) | ||
def test_meta_response(request_str, get_good_response, check_keys): | ||
"""Check `meta` property in response""" | ||
response = get_good_response(request_str) | ||
|
||
assert "meta" in response | ||
meta_required_keys = ResponseMeta.schema()["required"] | ||
meta_optional_keys = list( | ||
set(ResponseMeta.schema()["properties"].keys()) - set(meta_required_keys) | ||
) | ||
implemented_optional_keys = ["data_available", "implementation"] | ||
|
||
check_keys(meta_required_keys, response["meta"]) | ||
check_keys(implemented_optional_keys, meta_optional_keys) | ||
check_keys(implemented_optional_keys, response["meta"]) |
Oops, something went wrong.