Let’s say we have the following model:
class Toaster(object):
def __init__(self, color, slots, content):
self.color = color
self.slots = slots
self.content = content
Let’s define a very simple fixtures YAML file:
toaster: # The fixture's name
fields: # The fixture's content
color: red
slots: 5
content: !rel toasts # You can reference other fixtures
model: charlatan.tests.fixtures.simple_models:Toaster
toasts:
fields:
- "Toast 1"
- "Toast 2"
# No model is defined, so it defaults to what `fields` actually is, i.e.
# in our case, a list.
In this example:
You first need to load a fixtures file (do it once for the whole test suite) with charlatan.FixturesManager.load():
>>> import charlatan
>>> fixtures_manager = charlatan.FixturesManager()
>>> fixtures_manager.load("./docs/examples/simple_fixtures.yaml",
... models_package="toaster.models")
>>> toaster = fixtures_manager.install_fixture("toaster")
>>> toaster.color
'red'
>>> toaster.slots
5
>>> toaster.content
['Toast 1', 'Toast 2']
Voila!
Charlatan works best when used with unittest.TestCase. Your test class needs to inherits from charlatan.FixturesManagerMixin.
Charlatan uses an internal cache to store fixtures instance (in particular to create relationships). If you are resetting your database after each tests (using transactions or by manually truncating all tables), you need to clean the cache either in TestCase.setUp(), otherwise Charlatan will try accessing objects that are not anymore in the sqlalchemy session.
import unittest
import charlatan
fixtures_manager = charlatan.FixturesManager()
fixtures_manager.load("./docs/examples/simple_fixtures.yaml")
class TestToaster(unittest.TestCase, charlatan.FixturesManagerMixin):
def setUp(self):
# Attach the fixtures manager to the instance
self.fixtures_manager = fixtures_manager
# Cleanup the cache
self.init_fixtures()
def test_example(self):
"""Verify that we can get fixtures."""
toaster = self.install_fixture("toaster")
self.assertEqual(toaster.color, "red")
self.assertEqual(toaster.slots, 5)
self.assertEqual(toaster.content, ['Toast 1', 'Toast 2'])
There are multiple ways to require and use fixtures.
class MyTest(FixturesManagerMixin):
def setUp(self):
# This will create self.client and self.driver
self.install_fixtures(("client", "driver"))
def tearDown(self):
# This will delete self.client and self.driver
self.uninstall_fixtures(("client", "driver"))
class MyTest(FixturesMixin):
def test_toaster(self):
self.install_fixture("toaster")
# do things... and optionally uninstall it once you're done
self.uninstall_fixture("toaster")
If you want to have complete control over the fixture, you can also get it without saving it nor attaching it to the test class:
class MyTest(FixturesManagerMixin):
def test_toaster(self):
self.toaster = self.get_fixture("toaster")
self.toaster.brand = "Flying"
self.toaster.save()
You can override a fixture’s parameters when getting or installing it.
manager = FixturesManager()
manager.load("./examples/fixtures.yaml")
manager.get_fixture("toaster", attrs={"brand": "Flying"})
Here’s the general process:
Fixtures are then attached to your test class, you can access them as instance attributes:
class MyTest(FixturesManagerMixin):
fixtures = ("toaster", "toast1", "toast2")
def test_toaster(self):
self.toaster.toast(self.toast1, self.toast2)
Hooks are also supported.