Generating fixture data with Python's fixture module
flask, nose, python, sqlalchemy
Solution
An option would be to use factory_boy to create your test data.
Assuming that you keep and update accordingly a list of roles (that will be used later on) like this one:
roles = [ROLE_ENGINEER, ROLE_ADMIN, ROLE_MANAGER, ...]
Let's create a factory for the `Employee` table:
import factory
from somewhere.in.the.app import roles
class EmployeeFactory(factory.alchemy.SQLAlchemyModelFactory):
class Meta:
model = Employee
sqlalchemy_session = session
username = factory.Sequence(lambda n: u'User %d' % n)
# Other attributes
...
# Now the role choice
role = factory.fuzzy.FuzzyChoice(roles)
The `FuzzyChoice` method takes a list of choices and makes a random choice from this list. Now this will be able to create any amount of `Employee` objects on demand.
Using the factory:
from factory.location import EmployeeFactory
def test_only_admin_can_see_this_page():
EmployeeFactory.create_batch(size=100)
for employee in session.query(Employee).all():
login(employee)
with self.app.test_request_context('/'):
response = self.test_client.get(ADMIN_PAGE)
if employee.role == ROLE_ADMIN
eq_(200, response.status_code)
else:
eq_(401, response.status_code)
logout(employee)
Breakdown:
- `EmployeeFactory.create_batch(size=100)` Creates 100 `Employee` objects in the test session.
- We can access those objects from the factory `session`.
More information about using factory_boy with SQLAlchemy: https://factoryboy.readthedocs.io/en/latest/orms.html?highlight=sqlalchemy#sqlalchemy. Be careful with session management especially: https://factoryboy.readthedocs.io/en/latest/orms.html?highlight=sqlalchemy#managing-sessions
Problem
I'm working with the fixture module for the first time, trying to get a better set of fixture data so I can make our functional tests more complete. I'm finding the fixture module a bit clunky, and I'm hoping there's a better way to do what I'm doing. This is a Flask/SQLAlchemy app in Python 2.7, and we're using nose as a test runner. So I have a set of employees. Employees have roles. There are a few pages with rather complex permissions, and I'd like to make sure those are tested. I created a DataSet that has each type of role (there are about 15 roles in our app): ``` class EmployeeData(DataSet): class Meta: storable = Employee class engineer: username = "engineer" role = ROLE_ENGINEER class manager: username = "manager" role = ROLE_MANAGER class admin: username = "admin" role = ROLE_ADMIN ``` and what I'd like to do is write a functional test that checks only the right people can access a page. (The actual permissions are way more complicated, I just wanted a toy example to show you.) Something like this: ``` def test_only_admin_can_see_this_page(): for employee in Employee.query.all(): login(employee) with self.app.test_request_context('/'): response = self.test_client.get(ADMIN_PAGE) if employee.role == ROLE_ADMIN eq_(200, response.status_code) else: eq_(401, response.status_code) logout(employee) ``` Is there a way to generate the fixture data so my devs don't have to remember to add a line to the fixtures every time we add a role? We have the canonical list of all roles as configuration elsewhere in the app, so I have that. I'm not wedded to any of this or the fixture module, so I'm happy to hear suggestions!