It’s tedious to generate test fixtures by hand, to allow faster iteration, we can employ factory_boy to generate these fixtures automatically for our Python project. What even better is, factory_boy
has builtin support for well known ORM libraries, such as SQLALchemy and Django.
Suppose we are building a service that records famous quotes. In this service, we define a Quote
model for quote entries like this:
# in app.py
db = SQLAlchemy()
class Quote(db.Model):
id = db.Column(db.Integer, primary_key=True)
author = db.Column(db.String(100), nullable=False)
message = db.Column(db.Text)
Then in the test side (for common testing setup, see Flask database test setup with py.test), we can define a factory for this model:
# in test/factory.py
import factory
from app import db, Quote
class QuoteFactory(factory.alchemy.SQLAlchemyModelFactory):
class Meta:
model = Quote
sqlalchemy_session = db.session
author = factory.Faker('name')
message = factory.Faker('text')
Now, we can consume this factory in various places:
(venv) $ flask shell
App: app [production]
...
>>> from app import Quote
>>> from test.factory import QuoteFactory
>>> quote = QuoteFactory.build()
>>> assert isinstance(quote, Quote)
>>> print(quote.author)
Thomas Miller
>>> print(quote.message)
Doctor game enough with.
Responsibility yourself themselves information. Single support east.
Operation night line parent take act new. She race activity. Air in fish prevent behind.
During the test, we can use XXXFactory.create
to create an instance and add it to current test db session:
def test_create_one_quote(db):
quote = QuoteFactory.create()
db.session.commit()
assert quote.id is not None
assert quote.author
assert quote.message
We can also override the value for one or multiple fields, by specifying the field name in create call:
def test_create_many_quotes(db):
expected_author = 'Louis Armstrong'
quotes = QuoteFactory.create_batch(100, author=expected_author)
db.session.commit()
for quote in quotes:
assert quote.id is not None
assert quote.author == expected_author
assert quote.message
With the help of factory_boy
, we can generate a large collection of test fixtures without much effort.
A full example of code can be check out from the GitHub repo.