pytest-dev / pytest-dev/pytest-factoryboy

LazyFixture ignores Subfactory attribute assignment

Open
#40 2 comments 3 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Python
Stars
400
Forks
44
Avg merge
6h 34m
Merged PRs (30d)
1

Description

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.

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by running pytest with the attached sample and compare the passing create/build tests with the failing main_model fixture in test_factories.py. Trace how the LazyFixture entry point handles the MainModelFactory subfactory assignment, then add a regression test that verifies the fixture preserves the configured 'Initial Name' value.

Written by the indexing model from the issue text.

Assessment

Tech stack
django, python
Domain
testing
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
48/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.