Quickstart

A simple example

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:

  • toaster and toasts are the fixture keys.
  • fields is provided as argument when instantiating the class: Toaster(**fields).
  • model is the path to the model that we defined.
  • !rel lets you create relationships by pointing to another fixture key.

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!

Using charlatan in test cases

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'])

Using fixtures

There are multiple ways to require and use fixtures.

For each tests, in setUp and tearDown

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"))

For a single test

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")

Getting a fixture without saving it

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()

Overriding fixture fields

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"})

What happens when you install a fixture

Here’s the general process:

  1. The fixture is instantiated: Model(**fields).
  2. If there’s any post creation hook, they are run (see Dependencies for more information).
  3. The fixture is then saved. If it’s a sqlalchemy model, charlatan will detect it, add it to the session and commit it (db_session.add(instance); db_session.commit()). If it’s not a sqlalchemy model, charlatan will try to call a save method on the instance. If there’s no such method, charlatan will do nothing.

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.