basic tests with new factories

This commit is contained in:
smilerz
2021-12-08 09:01:20 -06:00
parent b5bf0a4584
commit 8f0c5e21ad
9 changed files with 555 additions and 287 deletions

View File

@@ -67,6 +67,9 @@ class TreeManager(MP_NodeManager):
except self.model.DoesNotExist:
with scopes_disabled():
try:
defaults = kwargs.pop('defaults', None)
if defaults:
kwargs = {**kwargs, **defaults}
# ManyToMany fields can't be set this way, so pop them out to save for later
fields = [field.name for field in self.model._meta.get_fields() if issubclass(type(field), ManyToManyField)]
many_to_many = {field: kwargs.pop(field) for field in list(kwargs) if field in fields}

View File

@@ -179,7 +179,6 @@ class UserPreferenceSerializer(serializers.ModelSerializer):
'comments', 'shopping_auto_sync', 'mealplan_autoadd_shopping', 'food_ignore_default', 'default_delay',
'mealplan_autoinclude_related', 'mealplan_autoexclude_onhand', 'shopping_share', 'shopping_recent_days', 'csv_delim', 'csv_prefix'
)
# read_only_fields = ['user'] # making user read_only removes it from validated_data, moved read_only attribute to serializer
class UserFileSerializer(serializers.ModelSerializer):

View File

@@ -1,5 +1,6 @@
import json
import factory
import pytest
from django.contrib import auth
from django.forms import model_to_dict
@@ -13,15 +14,14 @@ from cookbook.tests.factories import FoodFactory, ShoppingListEntryFactory
LIST_URL = 'api:shoppinglistentry-list'
DETAIL_URL = 'api:shoppinglistentry-detail'
# register(FoodFactory, 'food_1', space=LazyFixture('space_1'))
# register(FoodFactory, 'food_2', space=LazyFixture('space_1'))
# register(ShoppingListEntryFactory, 'sle_1', space=LazyFixture('space_1'), food=LazyFixture('food_1'))
# register(ShoppingListEntryFactory, 'sle_2', space=LazyFixture('space_1'), food=LazyFixture('food_2'))
register(ShoppingListEntryFactory, 'sle_1', space=LazyFixture('space_1'))
register(ShoppingListEntryFactory, 'sle_2', space=LazyFixture('space_1'))
@pytest.fixture
def sle(space_1, u1_s1):
user = auth.get_user(u1_s1)
return ShoppingListEntryFactory.create_batch(10, space=space_1, created_by=user)
@pytest.mark.parametrize("arg", [
@ pytest.mark.parametrize("arg", [
['a_u', 403],
['g1_s1', 200],
['u1_s1', 200],
@@ -32,29 +32,28 @@ def test_list_permission(arg, request):
assert c.get(reverse(LIST_URL)).status_code == arg[1]
def test_list_space(sle_1, u1_s1, u1_s2, space_2):
assert json.loads(u1_s1.get(reverse(LIST_URL)).content)['count'] == 2
assert json.loads(u1_s2.get(reverse(LIST_URL)).content)['count'] == 0
def test_list_space(sle, u1_s1, u1_s2, space_2):
assert len(json.loads(u1_s1.get(reverse(LIST_URL)).content)) == 10
assert len(json.loads(u1_s2.get(reverse(LIST_URL)).content)) == 0
with scopes_disabled():
e = ShoppingListEntry.objects.first()
e.space = space_2
e.save()
assert json.loads(u1_s1.get(reverse(LIST_URL)).content)['count'] == 1
assert json.loads(u1_s2.get(reverse(LIST_URL)).content)['count'] == 0
assert len(json.loads(u1_s1.get(reverse(LIST_URL)).content)) == 9
assert len(json.loads(u1_s2.get(reverse(LIST_URL)).content)) == 0
def test_get_detail(u1_s1, sle_1):
# r = u1_s1.get(reverse(
# DETAIL_URL,
# args={sle_1.id}
# ))
# assert json.loads(r.content)['id'] == sle_1.id
pass
def test_get_detail(u1_s1, sle):
r = u1_s1.get(reverse(
DETAIL_URL,
args={sle[0].id}
))
assert json.loads(r.content)['id'] == sle[0].id
@pytest.mark.parametrize("arg", [
@ pytest.mark.parametrize("arg", [
['a_u', 403],
['g1_s1', 404],
['u1_s1', 200],
@@ -63,20 +62,21 @@ def test_get_detail(u1_s1, sle_1):
['u1_s2', 404],
['a1_s2', 404],
])
def test_update(arg, request, sle_1):
def test_update(arg, request, sle):
c = request.getfixturevalue(arg[0])
new_val = float(sle[0].amount + 1)
r = c.patch(
reverse(
DETAIL_URL,
args={sle_1.id}
args={sle[0].id}
),
{'amount': 2},
{'amount': new_val},
content_type='application/json'
)
assert r.status_code == arg[1]
if r.status_code == 200:
response = json.loads(r.content)
assert response['amount'] == 2
assert response['amount'] == new_val
@pytest.mark.parametrize("arg", [
@@ -85,25 +85,25 @@ def test_update(arg, request, sle_1):
['u1_s1', 201],
['a1_s1', 201],
])
def test_add(arg, request, sle_1):
def test_add(arg, request, sle):
c = request.getfixturevalue(arg[0])
r = c.post(
reverse(LIST_URL),
{'food': model_to_dict(sle_1.food), 'amount': 1},
{'food': model_to_dict(sle[0].food), 'amount': 1},
content_type='application/json'
)
response = json.loads(r.content)
print(r.content)
assert r.status_code == arg[1]
if r.status_code == 201:
assert response['food']['id'] == sle_1.food.pk
assert response['food']['id'] == sle[0].food.pk
def test_delete(u1_s1, u1_s2, sle_1):
def test_delete(u1_s1, u1_s2, sle):
r = u1_s2.delete(
reverse(
DETAIL_URL,
args={sle_1.id}
args={sle[0].id}
)
)
assert r.status_code == 404
@@ -111,7 +111,7 @@ def test_delete(u1_s1, u1_s2, sle_1):
r = u1_s1.delete(
reverse(
DETAIL_URL,
args={sle_1.id}
args={sle[0].id}
)
)

View File

@@ -7,14 +7,14 @@ import pytest
from django.contrib import auth
from django.contrib.auth.models import Group, User
from django_scopes import scopes_disabled
from pytest_factoryboy import register
from pytest_factoryboy import LazyFixture, register
from cookbook.models import Food, Ingredient, Recipe, Space, Step, Unit
from cookbook.tests.factories import SpaceFactory
from cookbook.tests.factories import FoodFactory, SpaceFactory, UserFactory
register(SpaceFactory, 'space_1')
register(SpaceFactory, 'space_2')
# register(FoodFactory, space=LazyFixture('space_2'))
# TODO refactor user fixtures https://stackoverflow.com/questions/40966571/how-to-create-a-field-with-a-list-of-instances-in-factory-boy
# hack from https://github.com/raphaelm/django-scopes to disable scopes for all fixtures
@@ -184,25 +184,17 @@ def create_user(client, space, **kwargs):
c = copy.deepcopy(client)
with scopes_disabled():
group = kwargs.pop('group', None)
username = kwargs.pop('username', uuid.uuid4())
user = UserFactory(space=space, groups=group)
user = User.objects.create(username=username, **kwargs)
if group:
user.groups.add(Group.objects.get(name=group))
user.userpreference.space = space
user.userpreference.save()
c.force_login(user)
return c
# anonymous user
@pytest.fixture()
def a_u(client):
return copy.deepcopy(client)
# users without any group
@pytest.fixture()
def ng1_s1(client, space_1):
return create_user(client, space_1)

View File

@@ -4,9 +4,10 @@ from decimal import Decimal
import factory
import pytest
from django.contrib import auth
from django.contrib.auth.models import User
from django.contrib.auth.models import Group, User
from django_scopes import scopes_disabled
from faker import Factory as FakerFactory
from pytest_factoryboy import register
# this code will run immediately prior to creating the model object useful when you want a reverse relationship
# log = factory.RelatedFactory(
@@ -31,6 +32,7 @@ def pytest_fixture_setup(fixturedef, request):
yield
@register
class SpaceFactory(factory.django.DjangoModelFactory):
"""Space factory."""
name = factory.LazyAttribute(lambda x: faker.word())
@@ -44,18 +46,41 @@ class SpaceFactory(factory.django.DjangoModelFactory):
model = 'cookbook.Space'
@register
class UserFactory(factory.django.DjangoModelFactory):
"""User factory."""
username = factory.LazyAttribute(lambda x: faker.word())
username = factory.LazyAttribute(lambda x: faker.simple_profile()['username'])
first_name = factory.LazyAttribute(lambda x: faker.first_name())
last_name = factory.LazyAttribute(lambda x: faker.last_name())
email = factory.LazyAttribute(lambda x: faker.email())
space = factory.SubFactory(SpaceFactory)
@factory.post_generation
def groups(self, create, extracted, **kwargs):
if not create:
return
if extracted:
self.groups.add(Group.objects.get(name=extracted))
@factory.post_generation
def userpreference(self, create, extracted, **kwargs):
if not create:
return
if extracted:
# TODO this doesn't work and needs saved
for prefs in extracted:
self.userpreference[prefs] = prefs
self.userpreference.space = self.space
self.userpreference.save()
class Meta:
model = User
@register
class SupermarketCategoryFactory(factory.django.DjangoModelFactory):
"""SupermarketCategory factory."""
name = factory.LazyAttribute(lambda x: faker.word())
@@ -64,9 +89,11 @@ class SupermarketCategoryFactory(factory.django.DjangoModelFactory):
class Meta:
model = 'cookbook.SupermarketCategory'
django_get_or_create = ('name', 'space',)
# @factory.django.mute_signals(post_save)
@register
class FoodFactory(factory.django.DjangoModelFactory):
"""Food factory."""
name = factory.LazyAttribute(lambda x: faker.sentence(nb_words=3))
@@ -89,8 +116,10 @@ class FoodFactory(factory.django.DjangoModelFactory):
class Meta:
model = 'cookbook.Food'
django_get_or_create = ('name', 'space',)
@register
class UnitFactory(factory.django.DjangoModelFactory):
"""Unit factory."""
name = factory.LazyAttribute(lambda x: faker.word())
@@ -99,8 +128,10 @@ class UnitFactory(factory.django.DjangoModelFactory):
class Meta:
model = 'cookbook.Unit'
django_get_or_create = ('name', 'space',)
@register
class KeywordFactory(factory.django.DjangoModelFactory):
"""Keyword factory."""
name = factory.LazyAttribute(lambda x: faker.sentence(nb_words=3))
@@ -110,8 +141,10 @@ class KeywordFactory(factory.django.DjangoModelFactory):
class Meta:
model = 'cookbook.Keyword'
django_get_or_create = ('name', 'space',)
@register
class IngredientFactory(factory.django.DjangoModelFactory):
"""Ingredient factory."""
food = factory.SubFactory(FoodFactory, space=factory.SelfAttribute('..space'))
@@ -124,6 +157,7 @@ class IngredientFactory(factory.django.DjangoModelFactory):
model = 'cookbook.Ingredient'
@register
class MealTypeFactory(factory.django.DjangoModelFactory):
name = factory.LazyAttribute(lambda x: faker.sentence(nb_words=5))
order = 0
@@ -137,6 +171,7 @@ class MealTypeFactory(factory.django.DjangoModelFactory):
model = 'cookbook.MealType'
@register
class MealPlanFactory(factory.django.DjangoModelFactory):
recipe = factory.Maybe(
factory.LazyAttribute(lambda x: x.has_recipe),
@@ -158,6 +193,7 @@ class MealPlanFactory(factory.django.DjangoModelFactory):
model = 'cookbook.MealPlan'
@register
class ShoppingListRecipeFactory(factory.django.DjangoModelFactory):
name = factory.LazyAttribute(lambda x: faker.sentence(nb_words=5))
recipe = factory.Maybe(
@@ -175,6 +211,7 @@ class ShoppingListRecipeFactory(factory.django.DjangoModelFactory):
model = 'cookbook.ShoppingListRecipe'
@register
class ShoppingListEntryFactory(factory.django.DjangoModelFactory):
"""ShoppingListEntry factory."""
@@ -184,16 +221,16 @@ class ShoppingListEntryFactory(factory.django.DjangoModelFactory):
no_declaration=None
)
food = factory.SubFactory(FoodFactory, space=factory.SelfAttribute('..space'))
# unit = factory.SubFactory(UnitFactory, space=factory.SelfAttribute('..space'))
unit = factory.SubFactory(UnitFactory, space=factory.SelfAttribute('..space'))
# # ingredient = factory.SubFactory(IngredientFactory)
amount = factory.LazyAttribute(lambda x: Decimal(faker.random_int(min=1, max=10))/100)
order = 0
amount = factory.LazyAttribute(lambda x: Decimal(faker.random_int(min=1, max=100))/10)
order = factory.Sequence(int)
checked = False
created_by = factory.SubFactory(UserFactory, space=factory.SelfAttribute('..space'))
created_at = factory.LazyAttribute(lambda x: faker.past_date())
completed_at = None
delay_until = None
space = factory.SubFactory('cookbook.tests.factories.SpaceFactory')
space = factory.SubFactory(SpaceFactory)
class Params:
has_mealplan = False
@@ -202,6 +239,7 @@ class ShoppingListEntryFactory(factory.django.DjangoModelFactory):
model = 'cookbook.ShoppingListEntry'
@register
class StepFactory(factory.django.DjangoModelFactory):
name = factory.LazyAttribute(lambda x: faker.sentence(nb_words=5))
# type = models.CharField(
@@ -229,6 +267,7 @@ class StepFactory(factory.django.DjangoModelFactory):
model = 'cookbook.Step'
@register
class RecipeFactory(factory.django.DjangoModelFactory):
name = factory.LazyAttribute(lambda x: faker.sentence(nb_words=7))
description = factory.LazyAttribute(lambda x: faker.sentence(nb_words=10))