Make tests order independent (#932)

* Reset the global registry after each test (teardown)

* Create a settings fixtures that returns graphene_settings and resets
  the graphene_settings after use (teardown)

* Convert test_mutation tests from unittests.TestCase to pytest

* Convert test_mutation PetType to a pet_type fixtures that reregisters
  the type
This commit is contained in:
Jean-Louis Fuchs 2020-04-20 14:23:20 +02:00 committed by GitHub
parent dc5c971498
commit b9f0e4f9ae
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 259 additions and 284 deletions

View File

@ -0,0 +1,18 @@
import pytest
from graphene_django.settings import graphene_settings as gsettings
from .registry import reset_global_registry
@pytest.fixture(autouse=True)
def reset_registry_fixture(db):
yield None
reset_global_registry()
@pytest.fixture()
def graphene_settings():
settings = dict(gsettings.__dict__)
yield gsettings
gsettings.__dict__ = settings

View File

@ -1,5 +1,3 @@
import pytest
import graphene
from graphene.relay import Node
from graphene_django import DjangoConnectionField, DjangoObjectType
@ -13,11 +11,6 @@ class context(object):
pass
# from examples.starwars_django.models import Character
pytestmark = pytest.mark.django_db
def test_should_query_field():
r1 = Reporter(last_name="ABA")
r1.save()

View File

@ -35,9 +35,6 @@ else:
)
)
pytestmark.append(pytest.mark.django_db)
if DJANGO_FILTER_INSTALLED:
class ArticleNode(DjangoObjectType):

View File

@ -1,16 +1,25 @@
import pytest
from django import forms
from django.test import TestCase
from django.core.exceptions import ValidationError
from py.test import raises
from graphene import ObjectType, Schema, String, Field
from graphene import Field, ObjectType, Schema, String
from graphene_django import DjangoObjectType
from graphene_django.tests.models import Film, Pet
from graphene_django.tests.models import Pet
from ...settings import graphene_settings
from ..mutation import DjangoFormMutation, DjangoModelFormMutation
@pytest.fixture()
def pet_type():
class PetType(DjangoObjectType):
class Meta:
model = Pet
fields = "__all__"
return PetType
class MyForm(forms.Form):
text = forms.CharField()
@ -36,18 +45,6 @@ class PetForm(forms.ModelForm):
return age
class PetType(DjangoObjectType):
class Meta:
model = Pet
fields = "__all__"
class FilmType(DjangoObjectType):
class Meta:
model = Film
fields = "__all__"
def test_needs_form_class():
with raises(Exception) as exc:
@ -73,7 +70,7 @@ def test_has_input_fields():
assert "text" in MyMutation.Input._meta.fields
def test_mutation_error_camelcased():
def test_mutation_error_camelcased(pet_type, graphene_settings):
class ExtraPetForm(PetForm):
test_field = forms.CharField(required=True)
@ -86,234 +83,237 @@ def test_mutation_error_camelcased():
graphene_settings.CAMELCASE_ERRORS = True
result = PetMutation.mutate_and_get_payload(None, None)
assert {f.field for f in result.errors} == {"name", "age", "testField"}
graphene_settings.CAMELCASE_ERRORS = False
class MockQuery(ObjectType):
a = String()
class FormMutationTests(TestCase):
def test_form_invalid_form(self):
class MyMutation(DjangoFormMutation):
class Meta:
form_class = MyForm
def test_form_invalid_form():
class MyMutation(DjangoFormMutation):
class Meta:
form_class = MyForm
class Mutation(ObjectType):
my_mutation = MyMutation.Field()
class Mutation(ObjectType):
my_mutation = MyMutation.Field()
schema = Schema(query=MockQuery, mutation=Mutation)
schema = Schema(query=MockQuery, mutation=Mutation)
result = schema.execute(
""" mutation MyMutation {
myMutation(input: { text: "INVALID_INPUT" }) {
errors {
field
messages
}
text
result = schema.execute(
""" mutation MyMutation {
myMutation(input: { text: "INVALID_INPUT" }) {
errors {
field
messages
}
text
}
}
"""
)
assert result.errors is None
assert result.data["myMutation"]["errors"] == [
{"field": "text", "messages": ["Invalid input"]}
]
def test_form_valid_input():
class MyMutation(DjangoFormMutation):
class Meta:
form_class = MyForm
class Mutation(ObjectType):
my_mutation = MyMutation.Field()
schema = Schema(query=MockQuery, mutation=Mutation)
result = schema.execute(
""" mutation MyMutation {
myMutation(input: { text: "VALID_INPUT" }) {
errors {
field
messages
}
text
}
}
"""
)
assert result.errors is None
assert result.data["myMutation"]["errors"] == []
assert result.data["myMutation"]["text"] == "VALID_INPUT"
def test_default_meta_fields(pet_type):
class PetMutation(DjangoModelFormMutation):
class Meta:
form_class = PetForm
assert PetMutation._meta.model is Pet
assert PetMutation._meta.return_field_name == "pet"
assert "pet" in PetMutation._meta.fields
def test_default_input_meta_fields(pet_type):
class PetMutation(DjangoModelFormMutation):
class Meta:
form_class = PetForm
assert PetMutation._meta.model is Pet
assert PetMutation._meta.return_field_name == "pet"
assert "name" in PetMutation.Input._meta.fields
assert "client_mutation_id" in PetMutation.Input._meta.fields
assert "id" in PetMutation.Input._meta.fields
def test_exclude_fields_input_meta_fields(pet_type):
class PetMutation(DjangoModelFormMutation):
class Meta:
form_class = PetForm
exclude_fields = ["id"]
assert PetMutation._meta.model is Pet
assert PetMutation._meta.return_field_name == "pet"
assert "name" in PetMutation.Input._meta.fields
assert "age" in PetMutation.Input._meta.fields
assert "client_mutation_id" in PetMutation.Input._meta.fields
assert "id" not in PetMutation.Input._meta.fields
def test_custom_return_field_name(pet_type):
class PetMutation(DjangoModelFormMutation):
class Meta:
form_class = PetForm
model = Pet
return_field_name = "animal"
assert PetMutation._meta.model is Pet
assert PetMutation._meta.return_field_name == "animal"
assert "animal" in PetMutation._meta.fields
def test_model_form_mutation_mutate_existing(pet_type):
class PetMutation(DjangoModelFormMutation):
pet = Field(pet_type)
class Meta:
form_class = PetForm
class Mutation(ObjectType):
pet_mutation = PetMutation.Field()
schema = Schema(query=MockQuery, mutation=Mutation)
pet = Pet.objects.create(name="Axel", age=10)
result = schema.execute(
""" mutation PetMutation($pk: ID!) {
petMutation(input: { id: $pk, name: "Mia", age: 10 }) {
pet {
name
age
}
}
"""
)
}
""",
variable_values={"pk": pet.pk},
)
self.assertIs(result.errors, None)
self.assertEqual(
result.data["myMutation"]["errors"],
[{"field": "text", "messages": ["Invalid input"]}],
)
assert result.errors is None
assert result.data["petMutation"]["pet"] == {"name": "Mia", "age": 10}
def test_form_valid_input(self):
class MyMutation(DjangoFormMutation):
class Meta:
form_class = MyForm
assert Pet.objects.count() == 1
pet.refresh_from_db()
assert pet.name == "Mia"
class Mutation(ObjectType):
my_mutation = MyMutation.Field()
schema = Schema(query=MockQuery, mutation=Mutation)
def test_model_form_mutation_creates_new(pet_type):
class PetMutation(DjangoModelFormMutation):
pet = Field(pet_type)
result = schema.execute(
""" mutation MyMutation {
myMutation(input: { text: "VALID_INPUT" }) {
errors {
field
messages
}
text
class Meta:
form_class = PetForm
class Mutation(ObjectType):
pet_mutation = PetMutation.Field()
schema = Schema(query=MockQuery, mutation=Mutation)
result = schema.execute(
""" mutation PetMutation {
petMutation(input: { name: "Mia", age: 10 }) {
pet {
name
age
}
errors {
field
messages
}
}
"""
)
}
"""
)
assert result.errors is None
assert result.data["petMutation"]["pet"] == {"name": "Mia", "age": 10}
self.assertIs(result.errors, None)
self.assertEqual(result.data["myMutation"]["errors"], [])
self.assertEqual(result.data["myMutation"]["text"], "VALID_INPUT")
assert Pet.objects.count() == 1
pet = Pet.objects.get()
assert pet.name == "Mia"
assert pet.age == 10
class ModelFormMutationTests(TestCase):
def test_default_meta_fields(self):
class PetMutation(DjangoModelFormMutation):
class Meta:
form_class = PetForm
def test_model_form_mutation_invalid_input(pet_type):
class PetMutation(DjangoModelFormMutation):
pet = Field(pet_type)
self.assertEqual(PetMutation._meta.model, Pet)
self.assertEqual(PetMutation._meta.return_field_name, "pet")
self.assertIn("pet", PetMutation._meta.fields)
class Meta:
form_class = PetForm
def test_default_input_meta_fields(self):
class PetMutation(DjangoModelFormMutation):
class Meta:
form_class = PetForm
class Mutation(ObjectType):
pet_mutation = PetMutation.Field()
self.assertEqual(PetMutation._meta.model, Pet)
self.assertEqual(PetMutation._meta.return_field_name, "pet")
self.assertIn("name", PetMutation.Input._meta.fields)
self.assertIn("client_mutation_id", PetMutation.Input._meta.fields)
self.assertIn("id", PetMutation.Input._meta.fields)
schema = Schema(query=MockQuery, mutation=Mutation)
def test_exclude_fields_input_meta_fields(self):
class PetMutation(DjangoModelFormMutation):
class Meta:
form_class = PetForm
exclude_fields = ["id"]
self.assertEqual(PetMutation._meta.model, Pet)
self.assertEqual(PetMutation._meta.return_field_name, "pet")
self.assertIn("name", PetMutation.Input._meta.fields)
self.assertIn("age", PetMutation.Input._meta.fields)
self.assertIn("client_mutation_id", PetMutation.Input._meta.fields)
self.assertNotIn("id", PetMutation.Input._meta.fields)
def test_custom_return_field_name(self):
class PetMutation(DjangoModelFormMutation):
class Meta:
form_class = PetForm
model = Pet
return_field_name = "animal"
self.assertEqual(PetMutation._meta.model, Pet)
self.assertEqual(PetMutation._meta.return_field_name, "animal")
self.assertIn("animal", PetMutation._meta.fields)
def test_model_form_mutation_mutate_existing(self):
class PetMutation(DjangoModelFormMutation):
pet = Field(PetType)
class Meta:
form_class = PetForm
class Mutation(ObjectType):
pet_mutation = PetMutation.Field()
schema = Schema(query=MockQuery, mutation=Mutation)
pet = Pet.objects.create(name="Axel", age=10)
result = schema.execute(
""" mutation PetMutation($pk: ID!) {
petMutation(input: { id: $pk, name: "Mia", age: 10 }) {
pet {
name
age
}
result = schema.execute(
""" mutation PetMutation {
petMutation(input: { name: "Mia", age: 99 }) {
pet {
name
age
}
errors {
field
messages
}
}
""",
variable_values={"pk": pet.pk},
)
}
"""
)
assert result.errors is None
assert result.data["petMutation"]["pet"] is None
assert result.data["petMutation"]["errors"] == [
{"field": "age", "messages": ["Too old"]}
]
self.assertIs(result.errors, None)
self.assertEqual(result.data["petMutation"]["pet"], {"name": "Mia", "age": 10})
assert Pet.objects.count() == 0
self.assertEqual(Pet.objects.count(), 1)
pet.refresh_from_db()
self.assertEqual(pet.name, "Mia")
def test_model_form_mutation_creates_new(self):
class PetMutation(DjangoModelFormMutation):
pet = Field(PetType)
def test_model_form_mutation_mutate_invalid_form(pet_type):
class PetMutation(DjangoModelFormMutation):
class Meta:
form_class = PetForm
class Meta:
form_class = PetForm
result = PetMutation.mutate_and_get_payload(None, None)
class Mutation(ObjectType):
pet_mutation = PetMutation.Field()
# A pet was not created
Pet.objects.count() == 0
schema = Schema(query=MockQuery, mutation=Mutation)
result = schema.execute(
""" mutation PetMutation {
petMutation(input: { name: "Mia", age: 10 }) {
pet {
name
age
}
errors {
field
messages
}
}
}
"""
)
self.assertIs(result.errors, None)
self.assertEqual(result.data["petMutation"]["pet"], {"name": "Mia", "age": 10})
self.assertEqual(Pet.objects.count(), 1)
pet = Pet.objects.get()
self.assertEqual(pet.name, "Mia")
self.assertEqual(pet.age, 10)
def test_model_form_mutation_invalid_input(self):
class PetMutation(DjangoModelFormMutation):
pet = Field(PetType)
class Meta:
form_class = PetForm
class Mutation(ObjectType):
pet_mutation = PetMutation.Field()
schema = Schema(query=MockQuery, mutation=Mutation)
result = schema.execute(
""" mutation PetMutation {
petMutation(input: { name: "Mia", age: 99 }) {
pet {
name
age
}
errors {
field
messages
}
}
}
"""
)
self.assertIs(result.errors, None)
self.assertEqual(result.data["petMutation"]["pet"], None)
self.assertEqual(
result.data["petMutation"]["errors"],
[{"field": "age", "messages": ["Too old"],}],
)
self.assertEqual(Pet.objects.count(), 0)
def test_model_form_mutation_mutate_invalid_form(self):
class PetMutation(DjangoModelFormMutation):
class Meta:
form_class = PetForm
result = PetMutation.mutate_and_get_payload(None, None)
# A pet was not created
self.assertEqual(Pet.objects.count(), 0)
fields_w_error = [e.field for e in result.errors]
self.assertEqual(len(result.errors), 2)
self.assertIn("name", fields_w_error)
self.assertEqual(result.errors[0].messages, ["This field is required."])
self.assertIn("age", fields_w_error)
self.assertEqual(result.errors[1].messages, ["This field is required."])
fields_w_error = [e.field for e in result.errors]
assert len(result.errors) == 2
assert result.errors[0].messages == ["This field is required."]
assert result.errors[1].messages == ["This field is required."]
assert "age" in fields_w_error
assert "name" in fields_w_error

View File

@ -1,14 +1,11 @@
import graphene
import pytest
from django.db import models
from graphene import Schema
from rest_framework import serializers
import graphene
from graphene import Schema
from graphene_django import DjangoObjectType
from graphene_django.rest_framework.mutation import SerializerMutation
pytestmark = pytest.mark.django_db
class MyFakeChildModel(models.Model):
name = models.CharField(max_length=50)

View File

@ -1,14 +1,13 @@
import datetime
from py.test import mark, raises
from py.test import raises
from rest_framework import serializers
from graphene import Field, ResolveInfo
from graphene.types.inputobjecttype import InputObjectType
from ...settings import graphene_settings
from ...types import DjangoObjectType
from ..models import MyFakeModel, MyFakeModelWithPassword, MyFakeModelWithDate
from ..models import MyFakeModel, MyFakeModelWithDate, MyFakeModelWithPassword
from ..mutation import SerializerMutation
@ -99,7 +98,6 @@ def test_exclude_fields():
assert "created" not in MyMutation.Input._meta.fields
@mark.django_db
def test_write_only_field():
class WriteOnlyFieldModelSerializer(serializers.ModelSerializer):
password = serializers.CharField(write_only=True)
@ -122,7 +120,6 @@ def test_write_only_field():
), "'password' is write_only field and shouldn't be visible"
@mark.django_db
def test_write_only_field_using_extra_kwargs():
class WriteOnlyFieldModelSerializer(serializers.ModelSerializer):
class Meta:
@ -144,7 +141,6 @@ def test_write_only_field_using_extra_kwargs():
), "'password' is write_only field and shouldn't be visible"
@mark.django_db
def test_read_only_fields():
class ReadOnlyFieldModelSerializer(serializers.ModelSerializer):
cool_name = serializers.CharField(read_only=True)
@ -194,7 +190,6 @@ def test_mutate_and_get_payload_success():
assert result.errors is None
@mark.django_db
def test_model_add_mutate_and_get_payload_success():
result = MyModelMutation.mutate_and_get_payload(
None, mock_info(), **{"cool_name": "Narf"}
@ -204,7 +199,6 @@ def test_model_add_mutate_and_get_payload_success():
assert isinstance(result.created, datetime.datetime)
@mark.django_db
def test_model_update_mutate_and_get_payload_success():
instance = MyFakeModel.objects.create(cool_name="Narf")
result = MyModelMutation.mutate_and_get_payload(
@ -214,7 +208,6 @@ def test_model_update_mutate_and_get_payload_success():
assert result.cool_name == "New Narf"
@mark.django_db
def test_model_partial_update_mutate_and_get_payload_success():
instance = MyFakeModel.objects.create(cool_name="Narf")
result = MyModelMutation.mutate_and_get_payload(
@ -224,7 +217,6 @@ def test_model_partial_update_mutate_and_get_payload_success():
assert result.cool_name == "Narf"
@mark.django_db
def test_model_invalid_update_mutate_and_get_payload_success():
class InvalidModelMutation(SerializerMutation):
class Meta:
@ -239,7 +231,6 @@ def test_model_invalid_update_mutate_and_get_payload_success():
assert '"id" required' in str(exc.value)
@mark.django_db
def test_perform_mutate_success():
class MyMethodMutation(SerializerMutation):
class Meta:
@ -272,11 +263,10 @@ def test_model_mutate_and_get_payload_error():
assert len(result.errors) > 0
def test_mutation_error_camelcased():
def test_mutation_error_camelcased(graphene_settings):
graphene_settings.CAMELCASE_ERRORS = True
result = MyModelMutation.mutate_and_get_payload(None, mock_info(), **{})
assert result.errors[0].field == "coolName"
graphene_settings.CAMELCASE_ERRORS = False
def test_invalid_serializer_operations():

View File

@ -8,7 +8,7 @@ from graphene import ObjectType, Schema, String
@patch("graphene_django.management.commands.graphql_schema.Command.save_json_file")
def test_generate_json_file_on_call_graphql_schema(savefile_mock, settings):
def test_generate_json_file_on_call_graphql_schema(savefile_mock):
out = StringIO()
management.call_command("graphql_schema", schema="", stdout=out)
assert "Successfully dumped GraphQL schema to schema.json" in out.getvalue()

View File

@ -1,16 +1,17 @@
import pytest
from collections import namedtuple
import pytest
from django.db import models
from django.utils.translation import ugettext_lazy as _
from graphene import NonNull
from py.test import raises
import graphene
from graphene import NonNull
from graphene.relay import ConnectionField, Node
from graphene.types.datetime import DateTime, Date, Time
from graphene.types.datetime import Date, DateTime, Time
from graphene.types.json import JSONString
from ..compat import JSONField, ArrayField, HStoreField, RangeField, MissingType
from ..compat import ArrayField, HStoreField, JSONField, MissingType, RangeField
from ..converter import (
convert_django_field,
convert_django_field_with_choices,
@ -18,10 +19,8 @@ from ..converter import (
)
from ..registry import Registry
from ..types import DjangoObjectType
from ..settings import graphene_settings
from .models import Article, Film, FilmDetails, Reporter
# from graphene.core.types.custom_scalars import DateTime, Time, JSONString
@ -333,7 +332,7 @@ def test_should_postgres_range_convert_list():
assert field.type.of_type.of_type == graphene.Int
def test_generate_enum_name():
def test_generate_enum_name(graphene_settings):
MockDjangoModelMeta = namedtuple("DjangoMeta", ["app_label", "object_name"])
graphene_settings.DJANGO_CHOICE_FIELD_ENUM_V3_NAMING = True
@ -351,5 +350,3 @@ def test_generate_enum_name():
generate_enum_name(model_meta, field)
== "SomeLongAppNameSomeObjectFizzBuzzChoices"
)
graphene_settings.DJANGO_CHOICE_FIELD_ENUM_V3_NAMING = False

View File

@ -10,7 +10,6 @@ from .models import Article as ArticleModel
from .models import Reporter as ReporterModel
@pytest.mark.django_db
class TestDjangoListField:
def test_only_django_object_types(self):
class TestType(ObjectType):

View File

@ -1,25 +1,20 @@
import base64
import datetime
import pytest
from django.db import models
from django.db.models import Q
from django.utils.functional import SimpleLazyObject
from graphql_relay import to_global_id
from py.test import raises
from django.db.models import Q
from graphql_relay import to_global_id
import graphene
from graphene.relay import Node
from ..utils import DJANGO_FILTER_INSTALLED
from ..compat import MissingType, JSONField
from ..compat import JSONField, MissingType
from ..fields import DjangoConnectionField
from ..types import DjangoObjectType
from ..settings import graphene_settings
from .models import Article, CNNReporter, Reporter, Film, FilmDetails
pytestmark = pytest.mark.django_db
from ..utils import DJANGO_FILTER_INSTALLED
from .models import Article, CNNReporter, Film, FilmDetails, Reporter
def test_should_query_only_fields():
@ -147,9 +142,6 @@ def test_should_query_postgres_fields():
def test_should_node():
# reset_global_registry()
# Node._meta.registry = get_global_registry()
class ReporterNode(DjangoObjectType):
class Meta:
model = Reporter
@ -588,7 +580,7 @@ def test_should_query_node_multiple_filtering():
assert result.data == expected
def test_should_enforce_first_or_last():
def test_should_enforce_first_or_last(graphene_settings):
graphene_settings.RELAY_CONNECTION_ENFORCE_FIRST_OR_LAST = True
class ReporterType(DjangoObjectType):
@ -627,7 +619,7 @@ def test_should_enforce_first_or_last():
assert result.data == expected
def test_should_error_if_first_is_greater_than_max():
def test_should_error_if_first_is_greater_than_max(graphene_settings):
graphene_settings.RELAY_CONNECTION_MAX_LIMIT = 100
class ReporterType(DjangoObjectType):
@ -667,10 +659,8 @@ def test_should_error_if_first_is_greater_than_max():
)
assert result.data == expected
graphene_settings.RELAY_CONNECTION_ENFORCE_FIRST_OR_LAST = False
def test_should_error_if_last_is_greater_than_max():
def test_should_error_if_last_is_greater_than_max(graphene_settings):
graphene_settings.RELAY_CONNECTION_MAX_LIMIT = 100
class ReporterType(DjangoObjectType):
@ -710,8 +700,6 @@ def test_should_error_if_last_is_greater_than_max():
)
assert result.data == expected
graphene_settings.RELAY_CONNECTION_ENFORCE_FIRST_OR_LAST = False
def test_should_query_promise_connectionfields():
from promise import Promise

View File

@ -9,14 +9,10 @@ from graphene import Connection, Field, Interface, ObjectType, Schema, String
from graphene.relay import Node
from .. import registry
from ..settings import graphene_settings
from ..types import DjangoObjectType, DjangoObjectTypeOptions
from ..converter import convert_choice_field_to_enum
from .models import Article as ArticleModel
from .models import Reporter as ReporterModel
registry.reset_global_registry()
class Reporter(DjangoObjectType):
"""Reporter description"""
@ -198,7 +194,6 @@ type RootQuery {
def with_local_registry(func):
def inner(*args, **kwargs):
old = registry.get_global_registry()
registry.reset_global_registry()
try:
retval = func(*args, **kwargs)
except Exception as e:
@ -499,7 +494,9 @@ class TestDjangoObjectType:
"""
)
def test_django_objecttype_convert_choices_enum_naming_collisions(self, PetModel):
def test_django_objecttype_convert_choices_enum_naming_collisions(
self, PetModel, graphene_settings
):
graphene_settings.DJANGO_CHOICE_FIELD_ENUM_V3_NAMING = True
class PetModelKind(DjangoObjectType):
@ -533,9 +530,10 @@ class TestDjangoObjectType:
}
"""
)
graphene_settings.DJANGO_CHOICE_FIELD_ENUM_V3_NAMING = False
def test_django_objecttype_choices_custom_enum_name(self, PetModel):
def test_django_objecttype_choices_custom_enum_name(
self, PetModel, graphene_settings
):
graphene_settings.DJANGO_CHOICE_FIELD_ENUM_CUSTOM_NAME = (
"graphene_django.tests.test_types.custom_enum_name"
)
@ -571,5 +569,3 @@ class TestDjangoObjectType:
}
"""
)
graphene_settings.DJANGO_CHOICE_FIELD_ENUM_CUSTOM_NAME = None