Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

LazyFixture ignores Subfactory attribute assignment #40

Open
dada-engineer opened this issue Apr 26, 2017 · 2 comments
Open

LazyFixture ignores Subfactory attribute assignment #40

dada-engineer opened this issue Apr 26, 2017 · 2 comments

Comments

@dada-engineer
Copy link

dada-engineer commented Apr 26, 2017

I am using pytest-factoryboy to test some of my django Code.

When using A model 'MainModel' with a ForeignKey to another Model 'OneOnly' I create a Factory for both like the following.

models.py:

from django.db import models


class OnlyOne(models.Model):
    name = models.CharField(max_length=16)


class MainModel(models.Model):
    name = models.CharField(max_length=16)
    one = models.ForeignKey(OnlyOne)

factories.py

import factory
import factory.fuzzy

from bug.models import MainModel
from bug.models import OnlyOne


class OnlyOneFactory(factory.DjangoModelFactory):
    class Meta(object):
        model = OnlyOne

    name = factory.Sequence(lambda n: 'OnlyOne {}'.format(n))


class MainModelFactory(factory.DjangoModelFactory):
    class Meta(object):
        model = MainModel

    name = factory.Sequence(lambda n: 'MainModel {}'.format(n))
    one = factory.SubFactory(OnlyOneFactory, name='Initial Name')

So I want the Subfactory to set OnlyOnes' name always to Initial Name. As of the documentation this is how to do it (see example here ):
one = factory.SubFactory(OnlyOneFactory, name='Initial Name')

Now I have written some basic tests to test that the name of OnlyOne is set correctly. And it is if I use the factory build and/or create method, but however not if I use the LazyFixture.

test_factories.py:

"""Test the factories."""
import pytest


@pytest.mark.django_db
def test_main_model_factory__create(main_model_factory):
    """Test if the MainModelFactory.create() works properly."""
    main_model = main_model_factory.create()
    assert main_model.one.name == 'Initial Name'


@pytest.mark.django_db
def test_main_model_factory__build(main_model_factory):
    """Test if the MainModelFactory.build() works properly."""
    main_model = main_model_factory.build()
    assert main_model.one.name == 'Initial Name'


@pytest.mark.django_db
def test_main_model_fixture(main_model):
    """Test if the MainModelFactory shortcut works properly."""
    assert main_model.one.name == 'Initial Name'

Test output is the following:

pytest
=========================================================== test session starts ============================================================
platform linux2 -- Python 2.7.12+, pytest-3.0.3, py-1.4.31, pluggy-0.4.0
django settings: factoryboy_subfactory_attribute_bug.settings (from ini file)
rootdir: /home/daniel/workspace/private/factoryboy_subfactory_attribute_bug/factoryboy_subfactory_attribute_bug, inifile: pytest.ini
plugins: bdd-2.18.0, factoryboy-1.1.6, django-2.9.1, timeout-1.0.0, blockage-0.2.0, cov-2.4.0
collected 3 items 

bug/tests/test_factories.py ..F

================================================================= FAILURES =================================================================
_________________________________________________________ test_main_model_fixture __________________________________________________________

main_model = <MainModel: MainModel object>

    @pytest.mark.django_db
    def test_main_model_fixture(main_model):
        """Test if the MainModelFactory shortcut works properly."""
>       assert main_model.one.name == 'Initial Name'
E       assert 'OnlyOne 2' == 'Initial Name'
E         - OnlyOne 2
E         + Initial Name

bug/tests/test_factories.py:22: AssertionError
==================================================== 1 failed, 2 passed in 0.32 seconds ====================================================

The question now is should it set the name as expected or am I misunderstanding the functionality of the LazyFixture used?

I am attaching a sample.tar.gz with a working django app to simulate this.
sample.tar.gz

  1. Unpack and cd to folder
  2. virtualenv env -p python3
  3. pip install django python-factoryboy pytest
  4. run pytest

Thanks for the help.

Edit: If you need any further information please feel free to ask. Sorry if something is missing I am new to submitting Issues on an open source project.

@dada-engineer
Copy link
Author

For now a workaround is to overwrite the _create method of my factory so it sets the attribute like:

@classmethod
    def _create(cls, model_class, *args, **kwargs):
        obj = super(ArticleFactory, cls)._create(model_class, *args, **kwargs)
        obj.one.name = 'Initial Name'
        obj.one.save()
        return obj

But another database access with the save operation is basically not what we want, is it?

@chkdmin
Copy link

chkdmin commented May 18, 2017

+1

_create method override is so bothersome things

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants