Skip to content

Commit 0973020

Browse files
committed
test: Add custom scalar strategies to corpus test
This way it is possible to test them all without skipping
1 parent 05b2320 commit 0973020

File tree

2 files changed

+54
-28
lines changed

2 files changed

+54
-28
lines changed

src/hypothesis_graphql/_strategies/strategy.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919

2020
BY_NAME = operator.attrgetter("name")
2121
EMPTY_LISTS_STRATEGY = st.builds(list)
22+
BUILT_IN_SCALAR_TYPE_NAMES = {"Int", "Float", "String", "ID", "Boolean"}
2223

2324

2425
def instance_cache(key_func: Callable) -> Callable:
@@ -106,7 +107,7 @@ def can_generate_field(self, field: graphql.GraphQLInputField) -> bool:
106107
# Can generate any non-scalar
107108
not isinstance(type_, graphql.GraphQLScalarType)
108109
# Default scalars
109-
or type_.name in {"Int", "Float", "String", "ID", "Boolean"}
110+
or type_.name in BUILT_IN_SCALAR_TYPE_NAMES
110111
# User-provided scalars
111112
or type_.name in self.custom_scalars
112113
)

test/test_corpus.py

Lines changed: 52 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,62 +1,87 @@
11
import json
2+
import pathlib
23

4+
import attr
5+
import graphql
36
import pytest
47
from hypothesis import HealthCheck, Phase, Verbosity, given, settings
58
from hypothesis import strategies as st
69

10+
from hypothesis_graphql import nodes
711
from hypothesis_graphql import strategies as gql_st
12+
from hypothesis_graphql._strategies.strategy import BUILT_IN_SCALAR_TYPE_NAMES
13+
from hypothesis_graphql.cache import cached_build_schema
814

9-
with open("test/corpus-api-guru-catalog.json") as fd:
15+
HERE = pathlib.Path(__file__).parent
16+
17+
with open(HERE / "corpus-api-guru-catalog.json") as fd:
1018
schemas = json.load(fd)
1119

1220
INVALID_SCHEMAS = {
1321
# Error: The directive '@deprecated' can only be used once at this location
1422
"Gitlab",
1523
}
16-
SCHEMAS_WITH_CUSTOM_SCALARS = {
17-
"MongoDB Northwind demo",
18-
"Bitquery",
19-
"MusicBrainz",
20-
"Spacex Land",
21-
"TravelgateX",
22-
"HIVDB",
23-
"Contentful",
24-
"Universe",
25-
}
24+
25+
26+
@attr.s(slots=True)
27+
class Schema:
28+
raw = attr.ib()
29+
custom_scalars = attr.ib()
30+
31+
32+
PLACEHOLDER_STRATEGY = st.just("placeholder").map(nodes.String)
33+
34+
35+
@pytest.fixture
36+
def schema(request):
37+
raw_schema = schemas[request.param]
38+
parsed = cached_build_schema(raw_schema)
39+
custom_scalars = {}
40+
# Put placeholders for every custom scalar. Their value is pretty much irrelevant here, it is more important to
41+
# test query generation, therefore a placeholder will allow these tests to run on schemas that contain custom
42+
# scalars
43+
for name, type_ in parsed.type_map.items():
44+
if name not in BUILT_IN_SCALAR_TYPE_NAMES and isinstance(type_, graphql.GraphQLScalarType):
45+
custom_scalars[name] = PLACEHOLDER_STRATEGY
46+
return Schema(raw_schema, custom_scalars or None)
2647

2748

2849
def get_names(corpus, predicate=None):
2950
for name in sorted(corpus):
3051
if name in INVALID_SCHEMAS or (predicate and not predicate(name)):
3152
continue
32-
if name in SCHEMAS_WITH_CUSTOM_SCALARS:
33-
yield pytest.param(name, marks=pytest.mark.xfail(reason="Custom scalars are not supported"))
34-
else:
35-
yield name
53+
yield name
3654

3755

3856
CORPUS_SETTINGS = {
39-
"suppress_health_check": [HealthCheck.too_slow, HealthCheck.data_too_large, HealthCheck.filter_too_much],
57+
"suppress_health_check": [
58+
HealthCheck.too_slow,
59+
HealthCheck.data_too_large,
60+
HealthCheck.filter_too_much,
61+
HealthCheck.function_scoped_fixture,
62+
],
4063
"phases": [Phase.generate],
4164
"verbosity": Verbosity.quiet,
4265
"deadline": None,
43-
"max_examples": 5,
66+
"max_examples": 10,
4467
}
4568

4669

47-
@pytest.mark.parametrize("name", get_names(schemas))
70+
@pytest.mark.parametrize("schema", get_names(schemas), indirect=["schema"])
4871
@settings(**CORPUS_SETTINGS)
4972
@given(data=st.data())
50-
def test_corpus(data, name, validate_operation):
51-
schema = schemas[name]
52-
query = data.draw(gql_st.queries(schema))
53-
validate_operation(schema, query)
73+
def test_corpus(data, schema: Schema, validate_operation):
74+
query = data.draw(gql_st.queries(schema.raw, custom_scalars=schema.custom_scalars))
75+
validate_operation(schema.raw, query)
5476

5577

56-
@pytest.mark.parametrize("name", get_names(schemas, lambda name: "type Mutation" in schemas[name]))
78+
@pytest.mark.parametrize(
79+
"schema",
80+
get_names(schemas, lambda name: "type Mutation {" in schemas[name] and name != "HIVDB"),
81+
indirect=["schema"],
82+
)
5783
@settings(**CORPUS_SETTINGS)
5884
@given(data=st.data())
59-
def test_corpus_mutations(data, name, validate_operation):
60-
schema = schemas[name]
61-
mutation = data.draw(gql_st.mutations(schema))
62-
validate_operation(schema, mutation)
85+
def test_corpus_mutations(data, schema: Schema, validate_operation):
86+
mutation = data.draw(gql_st.mutations(schema.raw, custom_scalars=schema.custom_scalars))
87+
validate_operation(schema.raw, mutation)

0 commit comments

Comments
 (0)