fix: run the tests in python 3.12 and 3.13 and remove snapshottest dependency (#1572)

* actually run the tests in python 3.12 and 3.13

* remove snapshottest from the example tests

so that the tests pass in 3.12 and 3.13 again

* remove the section about snapshot testing from the testing docs

because the snapshottest package doesn't work on Python 3.12 and above

* fix assertion for badly formed JSON input on Python 3.13

* fix deprecation warning about datetime.utcfromtimestamp()
This commit is contained in:
Florian Zimmermann 2024-08-08 11:49:26 +02:00 committed by GitHub
parent dc3b2e49c1
commit 48678afba4
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
15 changed files with 344 additions and 445 deletions

View File

@ -69,43 +69,3 @@ You can also add extra keyword arguments to the ``execute`` method, such as
'hey': 'hello Peter!'
}
}
Snapshot testing
~~~~~~~~~~~~~~~~
As our APIs evolve, we need to know when our changes introduce any breaking changes that might break
some of the clients of our GraphQL app.
However, writing tests and replicating the same response we expect from our GraphQL application can be a
tedious and repetitive task, and sometimes it's easier to skip this process.
Because of that, we recommend the usage of `SnapshotTest <https://github.com/syrusakbary/snapshottest/>`_.
SnapshotTest lets us write all these tests in a breeze, as it automatically creates the ``snapshots`` for us
the first time the test are executed.
Here is a simple example on how our tests will look if we use ``pytest``:
.. code:: python
def test_hey(snapshot):
client = Client(my_schema)
# This will create a snapshot dir and a snapshot file
# the first time the test is executed, with the response
# of the execution.
snapshot.assert_match(client.execute('''{ hey }'''))
If we are using ``unittest``:
.. code:: python
from snapshottest import TestCase
class APITestCase(TestCase):
def test_api_me(self):
"""Testing the API for /me"""
client = Client(my_schema)
self.assertMatchSnapshot(client.execute('''{ hey }'''))

View File

@ -1,98 +0,0 @@
# -*- coding: utf-8 -*-
# snapshottest: v1 - https://goo.gl/zC4yUc
from snapshottest import Snapshot
snapshots = Snapshot()
snapshots["test_hero_name_query 1"] = {"data": {"hero": {"name": "R2-D2"}}}
snapshots["test_hero_name_and_friends_query 1"] = {
"data": {
"hero": {
"id": "2001",
"name": "R2-D2",
"friends": [
{"name": "Luke Skywalker"},
{"name": "Han Solo"},
{"name": "Leia Organa"},
],
}
}
}
snapshots["test_nested_query 1"] = {
"data": {
"hero": {
"name": "R2-D2",
"friends": [
{
"name": "Luke Skywalker",
"appearsIn": ["NEWHOPE", "EMPIRE", "JEDI"],
"friends": [
{"name": "Han Solo"},
{"name": "Leia Organa"},
{"name": "C-3PO"},
{"name": "R2-D2"},
],
},
{
"name": "Han Solo",
"appearsIn": ["NEWHOPE", "EMPIRE", "JEDI"],
"friends": [
{"name": "Luke Skywalker"},
{"name": "Leia Organa"},
{"name": "R2-D2"},
],
},
{
"name": "Leia Organa",
"appearsIn": ["NEWHOPE", "EMPIRE", "JEDI"],
"friends": [
{"name": "Luke Skywalker"},
{"name": "Han Solo"},
{"name": "C-3PO"},
{"name": "R2-D2"},
],
},
],
}
}
}
snapshots["test_fetch_luke_query 1"] = {"data": {"human": {"name": "Luke Skywalker"}}}
snapshots["test_fetch_some_id_query 1"] = {
"data": {"human": {"name": "Luke Skywalker"}}
}
snapshots["test_fetch_some_id_query2 1"] = {"data": {"human": {"name": "Han Solo"}}}
snapshots["test_invalid_id_query 1"] = {"data": {"human": None}}
snapshots["test_fetch_luke_aliased 1"] = {"data": {"luke": {"name": "Luke Skywalker"}}}
snapshots["test_fetch_luke_and_leia_aliased 1"] = {
"data": {"luke": {"name": "Luke Skywalker"}, "leia": {"name": "Leia Organa"}}
}
snapshots["test_duplicate_fields 1"] = {
"data": {
"luke": {"name": "Luke Skywalker", "homePlanet": "Tatooine"},
"leia": {"name": "Leia Organa", "homePlanet": "Alderaan"},
}
}
snapshots["test_use_fragment 1"] = {
"data": {
"luke": {"name": "Luke Skywalker", "homePlanet": "Tatooine"},
"leia": {"name": "Leia Organa", "homePlanet": "Alderaan"},
}
}
snapshots["test_check_type_of_r2 1"] = {
"data": {"hero": {"__typename": "Droid", "name": "R2-D2"}}
}
snapshots["test_check_type_of_luke 1"] = {
"data": {"hero": {"__typename": "Human", "name": "Luke Skywalker"}}
}

View File

@ -8,19 +8,19 @@ setup()
client = Client(schema)
def test_hero_name_query(snapshot):
query = """
def test_hero_name_query():
result = client.execute("""
query HeroNameQuery {
hero {
name
}
}
"""
snapshot.assert_match(client.execute(query))
""")
assert result == {"data": {"hero": {"name": "R2-D2"}}}
def test_hero_name_and_friends_query(snapshot):
query = """
def test_hero_name_and_friends_query():
result = client.execute("""
query HeroNameAndFriendsQuery {
hero {
id
@ -30,12 +30,24 @@ def test_hero_name_and_friends_query(snapshot):
}
}
}
"""
snapshot.assert_match(client.execute(query))
""")
assert result == {
"data": {
"hero": {
"id": "2001",
"name": "R2-D2",
"friends": [
{"name": "Luke Skywalker"},
{"name": "Han Solo"},
{"name": "Leia Organa"},
],
}
}
}
def test_nested_query(snapshot):
query = """
def test_nested_query():
result = client.execute("""
query NestedQuery {
hero {
name
@ -48,70 +60,113 @@ def test_nested_query(snapshot):
}
}
}
"""
snapshot.assert_match(client.execute(query))
""")
assert result == {
"data": {
"hero": {
"name": "R2-D2",
"friends": [
{
"name": "Luke Skywalker",
"appearsIn": ["NEWHOPE", "EMPIRE", "JEDI"],
"friends": [
{"name": "Han Solo"},
{"name": "Leia Organa"},
{"name": "C-3PO"},
{"name": "R2-D2"},
],
},
{
"name": "Han Solo",
"appearsIn": ["NEWHOPE", "EMPIRE", "JEDI"],
"friends": [
{"name": "Luke Skywalker"},
{"name": "Leia Organa"},
{"name": "R2-D2"},
],
},
{
"name": "Leia Organa",
"appearsIn": ["NEWHOPE", "EMPIRE", "JEDI"],
"friends": [
{"name": "Luke Skywalker"},
{"name": "Han Solo"},
{"name": "C-3PO"},
{"name": "R2-D2"},
],
},
],
}
}
}
def test_fetch_luke_query(snapshot):
query = """
def test_fetch_luke_query():
result = client.execute("""
query FetchLukeQuery {
human(id: "1000") {
name
}
}
"""
snapshot.assert_match(client.execute(query))
""")
assert result == {"data": {"human": {"name": "Luke Skywalker"}}}
def test_fetch_some_id_query(snapshot):
query = """
def test_fetch_some_id_query():
result = client.execute(
"""
query FetchSomeIDQuery($someId: String!) {
human(id: $someId) {
name
}
}
"""
params = {"someId": "1000"}
snapshot.assert_match(client.execute(query, variables=params))
""",
variables={"someId": "1000"},
)
assert result == {"data": {"human": {"name": "Luke Skywalker"}}}
def test_fetch_some_id_query2(snapshot):
query = """
def test_fetch_some_id_query2():
result = client.execute(
"""
query FetchSomeIDQuery($someId: String!) {
human(id: $someId) {
name
}
}
"""
params = {"someId": "1002"}
snapshot.assert_match(client.execute(query, variables=params))
""",
variables={"someId": "1002"},
)
assert result == {"data": {"human": {"name": "Han Solo"}}}
def test_invalid_id_query(snapshot):
query = """
def test_invalid_id_query():
result = client.execute(
"""
query humanQuery($id: String!) {
human(id: $id) {
name
}
}
"""
params = {"id": "not a valid id"}
snapshot.assert_match(client.execute(query, variables=params))
""",
variables={"id": "not a valid id"},
)
assert result == {"data": {"human": None}}
def test_fetch_luke_aliased(snapshot):
query = """
def test_fetch_luke_aliased():
result = client.execute("""
query FetchLukeAliased {
luke: human(id: "1000") {
name
}
}
"""
snapshot.assert_match(client.execute(query))
""")
assert result == {"data": {"luke": {"name": "Luke Skywalker"}}}
def test_fetch_luke_and_leia_aliased(snapshot):
query = """
def test_fetch_luke_and_leia_aliased():
result = client.execute("""
query FetchLukeAndLeiaAliased {
luke: human(id: "1000") {
name
@ -120,12 +175,14 @@ def test_fetch_luke_and_leia_aliased(snapshot):
name
}
}
"""
snapshot.assert_match(client.execute(query))
""")
assert result == {
"data": {"luke": {"name": "Luke Skywalker"}, "leia": {"name": "Leia Organa"}}
}
def test_duplicate_fields(snapshot):
query = """
def test_duplicate_fields():
result = client.execute("""
query DuplicateFields {
luke: human(id: "1000") {
name
@ -136,12 +193,17 @@ def test_duplicate_fields(snapshot):
homePlanet
}
}
"""
snapshot.assert_match(client.execute(query))
""")
assert result == {
"data": {
"luke": {"name": "Luke Skywalker", "homePlanet": "Tatooine"},
"leia": {"name": "Leia Organa", "homePlanet": "Alderaan"},
}
}
def test_use_fragment(snapshot):
query = """
def test_use_fragment():
result = client.execute("""
query UseFragment {
luke: human(id: "1000") {
...HumanFragment
@ -154,29 +216,36 @@ def test_use_fragment(snapshot):
name
homePlanet
}
"""
snapshot.assert_match(client.execute(query))
""")
assert result == {
"data": {
"luke": {"name": "Luke Skywalker", "homePlanet": "Tatooine"},
"leia": {"name": "Leia Organa", "homePlanet": "Alderaan"},
}
}
def test_check_type_of_r2(snapshot):
query = """
def test_check_type_of_r2():
result = client.execute("""
query CheckTypeOfR2 {
hero {
__typename
name
}
}
"""
snapshot.assert_match(client.execute(query))
""")
assert result == {"data": {"hero": {"__typename": "Droid", "name": "R2-D2"}}}
def test_check_type_of_luke(snapshot):
query = """
def test_check_type_of_luke():
result = client.execute("""
query CheckTypeOfLuke {
hero(episode: EMPIRE) {
__typename
name
}
}
"""
snapshot.assert_match(client.execute(query))
""")
assert result == {
"data": {"hero": {"__typename": "Human", "name": "Luke Skywalker"}}
}

View File

@ -1,24 +0,0 @@
# -*- coding: utf-8 -*-
# snapshottest: v1 - https://goo.gl/zC4yUc
from snapshottest import Snapshot
snapshots = Snapshot()
snapshots["test_correct_fetch_first_ship_rebels 1"] = {
"data": {
"rebels": {
"name": "Alliance to Restore the Republic",
"ships": {
"pageInfo": {
"startCursor": "YXJyYXljb25uZWN0aW9uOjA=",
"endCursor": "YXJyYXljb25uZWN0aW9uOjA=",
"hasNextPage": True,
"hasPreviousPage": False,
},
"edges": [
{"cursor": "YXJyYXljb25uZWN0aW9uOjA=", "node": {"name": "X-Wing"}}
],
},
}
}
}

View File

@ -1,26 +0,0 @@
# -*- coding: utf-8 -*-
# snapshottest: v1 - https://goo.gl/zC4yUc
from snapshottest import Snapshot
snapshots = Snapshot()
snapshots["test_mutations 1"] = {
"data": {
"introduceShip": {
"ship": {"id": "U2hpcDo5", "name": "Peter"},
"faction": {
"name": "Alliance to Restore the Republic",
"ships": {
"edges": [
{"node": {"id": "U2hpcDox", "name": "X-Wing"}},
{"node": {"id": "U2hpcDoy", "name": "Y-Wing"}},
{"node": {"id": "U2hpcDoz", "name": "A-Wing"}},
{"node": {"id": "U2hpcDo0", "name": "Millennium Falcon"}},
{"node": {"id": "U2hpcDo1", "name": "Home One"}},
{"node": {"id": "U2hpcDo5", "name": "Peter"}},
]
},
},
}
}
}

View File

@ -1,114 +0,0 @@
# -*- coding: utf-8 -*-
# snapshottest: v1 - https://goo.gl/zC4yUc
from snapshottest import Snapshot
snapshots = Snapshot()
snapshots["test_correctly_fetches_id_name_rebels 1"] = {
"data": {
"rebels": {"id": "RmFjdGlvbjox", "name": "Alliance to Restore the Republic"}
}
}
snapshots["test_correctly_refetches_rebels 1"] = {
"data": {"node": {"id": "RmFjdGlvbjox", "name": "Alliance to Restore the Republic"}}
}
snapshots["test_correctly_fetches_id_name_empire 1"] = {
"data": {"empire": {"id": "RmFjdGlvbjoy", "name": "Galactic Empire"}}
}
snapshots["test_correctly_refetches_empire 1"] = {
"data": {"node": {"id": "RmFjdGlvbjoy", "name": "Galactic Empire"}}
}
snapshots["test_correctly_refetches_xwing 1"] = {
"data": {"node": {"id": "U2hpcDox", "name": "X-Wing"}}
}
snapshots["test_str_schema 1"] = '''type Query {
rebels: Faction
empire: Faction
node(
"""The ID of the object"""
id: ID!
): Node
}
"""A faction in the Star Wars saga"""
type Faction implements Node {
"""The ID of the object"""
id: ID!
"""The name of the faction."""
name: String
"""The ships used by the faction."""
ships(before: String, after: String, first: Int, last: Int): ShipConnection
}
"""An object with an ID"""
interface Node {
"""The ID of the object"""
id: ID!
}
type ShipConnection {
"""Pagination data for this connection."""
pageInfo: PageInfo!
"""Contains the nodes in this connection."""
edges: [ShipEdge]!
}
"""
The Relay compliant `PageInfo` type, containing data necessary to paginate this connection.
"""
type PageInfo {
"""When paginating forwards, are there more items?"""
hasNextPage: Boolean!
"""When paginating backwards, are there more items?"""
hasPreviousPage: Boolean!
"""When paginating backwards, the cursor to continue."""
startCursor: String
"""When paginating forwards, the cursor to continue."""
endCursor: String
}
"""A Relay edge containing a `Ship` and its cursor."""
type ShipEdge {
"""The item at the end of the edge"""
node: Ship
"""A cursor for use in pagination"""
cursor: String!
}
"""A ship in the Star Wars saga"""
type Ship implements Node {
"""The ID of the object"""
id: ID!
"""The name of the ship."""
name: String
}
type Mutation {
introduceShip(input: IntroduceShipInput!): IntroduceShipPayload
}
type IntroduceShipPayload {
ship: Ship
faction: Faction
clientMutationId: String
}
input IntroduceShipInput {
shipName: String!
factionId: String!
clientMutationId: String
}'''

View File

@ -8,26 +8,46 @@ setup()
client = Client(schema)
def test_correct_fetch_first_ship_rebels(snapshot):
query = """
query RebelsShipsQuery {
rebels {
name,
ships(first: 1) {
pageInfo {
startCursor
endCursor
hasNextPage
hasPreviousPage
}
edges {
cursor
node {
name
def test_correct_fetch_first_ship_rebels():
result = client.execute("""
query RebelsShipsQuery {
rebels {
name,
ships(first: 1) {
pageInfo {
startCursor
endCursor
hasNextPage
hasPreviousPage
}
edges {
cursor
node {
name
}
}
}
}
}
}
""")
assert result == {
"data": {
"rebels": {
"name": "Alliance to Restore the Republic",
"ships": {
"pageInfo": {
"startCursor": "YXJyYXljb25uZWN0aW9uOjA=",
"endCursor": "YXJyYXljb25uZWN0aW9uOjA=",
"hasNextPage": True,
"hasPreviousPage": False,
},
"edges": [
{
"cursor": "YXJyYXljb25uZWN0aW9uOjA=",
"node": {"name": "X-Wing"},
}
],
},
}
}
}
"""
snapshot.assert_match(client.execute(query))

View File

@ -8,26 +8,45 @@ setup()
client = Client(schema)
def test_mutations(snapshot):
query = """
mutation MyMutation {
introduceShip(input:{clientMutationId:"abc", shipName: "Peter", factionId: "1"}) {
ship {
id
name
}
faction {
name
ships {
edges {
node {
id
name
def test_mutations():
result = client.execute("""
mutation MyMutation {
introduceShip(input:{clientMutationId:"abc", shipName: "Peter", factionId: "1"}) {
ship {
id
name
}
faction {
name
ships {
edges {
node {
id
name
}
}
}
}
}
}
}
""")
assert result == {
"data": {
"introduceShip": {
"ship": {"id": "U2hpcDo5", "name": "Peter"},
"faction": {
"name": "Alliance to Restore the Republic",
"ships": {
"edges": [
{"node": {"id": "U2hpcDox", "name": "X-Wing"}},
{"node": {"id": "U2hpcDoy", "name": "Y-Wing"}},
{"node": {"id": "U2hpcDoz", "name": "A-Wing"}},
{"node": {"id": "U2hpcDo0", "name": "Millennium Falcon"}},
{"node": {"id": "U2hpcDo1", "name": "Home One"}},
{"node": {"id": "U2hpcDo5", "name": "Peter"}},
]
},
},
}
}
}
"""
snapshot.assert_match(client.execute(query))

View File

@ -1,3 +1,5 @@
import textwrap
from graphene.test import Client
from ..data import setup
@ -8,24 +10,115 @@ setup()
client = Client(schema)
def test_str_schema(snapshot):
snapshot.assert_match(str(schema).strip())
def test_str_schema():
assert str(schema).strip() == textwrap.dedent(
'''\
type Query {
rebels: Faction
empire: Faction
node(
"""The ID of the object"""
id: ID!
): Node
}
"""A faction in the Star Wars saga"""
type Faction implements Node {
"""The ID of the object"""
id: ID!
"""The name of the faction."""
name: String
"""The ships used by the faction."""
ships(before: String, after: String, first: Int, last: Int): ShipConnection
}
"""An object with an ID"""
interface Node {
"""The ID of the object"""
id: ID!
}
type ShipConnection {
"""Pagination data for this connection."""
pageInfo: PageInfo!
"""Contains the nodes in this connection."""
edges: [ShipEdge]!
}
"""
The Relay compliant `PageInfo` type, containing data necessary to paginate this connection.
"""
type PageInfo {
"""When paginating forwards, are there more items?"""
hasNextPage: Boolean!
"""When paginating backwards, are there more items?"""
hasPreviousPage: Boolean!
"""When paginating backwards, the cursor to continue."""
startCursor: String
"""When paginating forwards, the cursor to continue."""
endCursor: String
}
"""A Relay edge containing a `Ship` and its cursor."""
type ShipEdge {
"""The item at the end of the edge"""
node: Ship
"""A cursor for use in pagination"""
cursor: String!
}
"""A ship in the Star Wars saga"""
type Ship implements Node {
"""The ID of the object"""
id: ID!
"""The name of the ship."""
name: String
}
type Mutation {
introduceShip(input: IntroduceShipInput!): IntroduceShipPayload
}
type IntroduceShipPayload {
ship: Ship
faction: Faction
clientMutationId: String
}
input IntroduceShipInput {
shipName: String!
factionId: String!
clientMutationId: String
}'''
)
def test_correctly_fetches_id_name_rebels(snapshot):
query = """
def test_correctly_fetches_id_name_rebels():
result = client.execute("""
query RebelsQuery {
rebels {
id
name
}
}
"""
snapshot.assert_match(client.execute(query))
""")
assert result == {
"data": {
"rebels": {"id": "RmFjdGlvbjox", "name": "Alliance to Restore the Republic"}
}
}
def test_correctly_refetches_rebels(snapshot):
query = """
def test_correctly_refetches_rebels():
result = client.execute("""
query RebelsRefetchQuery {
node(id: "RmFjdGlvbjox") {
id
@ -34,24 +127,30 @@ def test_correctly_refetches_rebels(snapshot):
}
}
}
"""
snapshot.assert_match(client.execute(query))
""")
assert result == {
"data": {
"node": {"id": "RmFjdGlvbjox", "name": "Alliance to Restore the Republic"}
}
}
def test_correctly_fetches_id_name_empire(snapshot):
query = """
def test_correctly_fetches_id_name_empire():
result = client.execute("""
query EmpireQuery {
empire {
id
name
}
}
"""
snapshot.assert_match(client.execute(query))
""")
assert result == {
"data": {"empire": {"id": "RmFjdGlvbjoy", "name": "Galactic Empire"}}
}
def test_correctly_refetches_empire(snapshot):
query = """
def test_correctly_refetches_empire():
result = client.execute("""
query EmpireRefetchQuery {
node(id: "RmFjdGlvbjoy") {
id
@ -60,12 +159,14 @@ def test_correctly_refetches_empire(snapshot):
}
}
}
"""
snapshot.assert_match(client.execute(query))
""")
assert result == {
"data": {"node": {"id": "RmFjdGlvbjoy", "name": "Galactic Empire"}}
}
def test_correctly_refetches_xwing(snapshot):
query = """
def test_correctly_refetches_xwing():
result = client.execute("""
query XWingRefetchQuery {
node(id: "U2hpcDox") {
id
@ -74,5 +175,5 @@ def test_correctly_refetches_xwing(snapshot):
}
}
}
"""
snapshot.assert_match(client.execute(query))
""")
assert result == {"data": {"node": {"id": "U2hpcDox", "name": "X-Wing"}}}

View File

@ -1,6 +1,6 @@
# https://github.com/graphql-python/graphene/issues/1293
import datetime
from datetime import datetime, timezone
import graphene
from graphql.utilities import print_schema
@ -9,11 +9,11 @@ from graphql.utilities import print_schema
class Filters(graphene.InputObjectType):
datetime_after = graphene.DateTime(
required=False,
default_value=datetime.datetime.utcfromtimestamp(1434549820776 / 1000),
default_value=datetime.fromtimestamp(1434549820.776, timezone.utc),
)
datetime_before = graphene.DateTime(
required=False,
default_value=datetime.datetime.utcfromtimestamp(1444549820776 / 1000),
default_value=datetime.fromtimestamp(1444549820.776, timezone.utc),
)

View File

@ -51,35 +51,30 @@ def test_jsonstring_invalid_query():
Test that if an invalid type is provided we get an error
"""
result = schema.execute("{ json(input: 1) }")
assert result.errors
assert len(result.errors) == 1
assert result.errors[0].message == "Expected value of type 'JSONString', found 1."
assert result.errors == [
{"message": "Expected value of type 'JSONString', found 1."},
]
result = schema.execute("{ json(input: {}) }")
assert result.errors
assert len(result.errors) == 1
assert result.errors[0].message == "Expected value of type 'JSONString', found {}."
assert result.errors == [
{"message": "Expected value of type 'JSONString', found {}."},
]
result = schema.execute('{ json(input: "a") }')
assert result.errors
assert len(result.errors) == 1
assert result.errors[0].message == (
"Expected value of type 'JSONString', found \"a\"; "
"Badly formed JSONString: Expecting value: line 1 column 1 (char 0)"
)
assert result.errors == [
{
"message": "Expected value of type 'JSONString', found \"a\"; "
"Badly formed JSONString: Expecting value: line 1 column 1 (char 0)",
},
]
result = schema.execute("""{ json(input: "{\\'key\\': 0}") }""")
assert result.errors
assert len(result.errors) == 1
assert (
result.errors[0].message
== "Syntax Error: Invalid character escape sequence: '\\''."
)
assert result.errors == [
{"message": "Syntax Error: Invalid character escape sequence: '\\''."},
]
result = schema.execute("""{ json(input: "{\\"key\\": 0,}") }""")
assert result.errors
assert len(result.errors) == 1
assert result.errors[0].message == (
'Expected value of type \'JSONString\', found "{\\"key\\": 0,}"; '
"Badly formed JSONString: Expecting property name enclosed in double quotes: line 1 column 11 (char 10)"
assert result.errors[0].message.startswith(
'Expected value of type \'JSONString\', found "{\\"key\\": 0,}"; Badly formed JSONString:'
)

View File

@ -50,7 +50,6 @@ tests_require = [
"pytest-cov>=5,<6",
"pytest-mock>=3,<4",
"pytest-asyncio>=0.16,<2",
"snapshottest>=0.6,<1",
"coveralls>=3.3,<5",
]

View File

@ -5,10 +5,8 @@ skipsdist = true
[testenv]
deps =
.[test]
setenv =
PYTHONPATH = .:{envdir}
commands =
py{38,39,310,311,12,13}: pytest --cov=graphene graphene --cov-report=term --cov-report=xml examples {posargs}
pytest --cov=graphene graphene --cov-report=term --cov-report=xml examples {posargs}
[testenv:pre-commit]
basepython = python3.10