Document Actions

Oleg Pidsadnyi - Factory injection: Combining PyTest and FactoryBoy best practices in testing

Filed Under:

Oleg Pidsadnyi talks about Factory injection: Combining PyTest and FactoryBoy best practices in testing, at PyGrunn.

See the PyGrunn website for more info about this one-day Python conference in Groningen, The Netherlands.

For more information about this topic, you can read an article by Oleg titled Factory injection, combining pytest with factory_boy. [I steal code from there, that page is way better if you want the full story.]

What's wrong with testing? It is annoying. You have to setup everything to make it work. Hard to reuse. The tests are written as an afterthought and are usually not very good.

With Behavior Driven Development (BDD) style of tests, it can be this:

Scenario: Dark Helmet vs Lone Star v1

    Given I am your father's brother's nephew's cousin's former roommate

    When So what does that make us?

    Then Absolutely nothing

This is an example of a hard setup, especially the first step is hard to setup. You can split this up into multiple steps.

Gherkin's just-enough specification: specify only the facts that you need to observe.

Dependency injection can be statically declared in the code when you use pytest:

@pytest.fixture
def you(your_father):
        """You can't be created without your father."""
        ...

Parametrization works like this:

@pytest.mark.parametrize("book__price", [Amount("EUR", "15.20")])
@pytest.mark.parametrize(
        ("author__fee_percent", "expected_author_fee"),
        (
                (27, Amount("EUR", "4.104")),
                (12.5, Amount("EUR", "1.9")),
        ),
)
def test_unicode(book, expected_author_fee):
        """Test author fee calculation."""
        assert book.author_fee == expected_author_fee

Factory pattern. Declarative. Factories create objects. factory_boy does this for pytest.

How can you combine factories with dependency injection? Create the minimum number of objects needed in the hierarchy.

The right way to implement fixtures: don't. Let them be generated automatically. Otherwise you need to write more code and you know:

E = m c squared
Errors = more code squared

So: write factories to simplify your tests. Make this so you only need to specify what you are interested in testing. Stop writing test setup code.

Future:

  • auto-generated base factories for ORM models (alchemyboy)
  • standard BDD Given steps (Given model attr is X)

Documentation: http://pytest-factoryboy.readthedocs.io/

At PayLogic I started porting tests to this. It really saves a lot of code. My colleagues are using it too. Some like it. :-)

Make the factories easy for most of the cases, not necessarily for corner cases.

pytest can run unittest test cases and also nose test cases, it is quite universal.

Twitter: @olegpidsadnyi