from charlatan import FixturesManager
charlatan only supports YAML at time of writing.
Fixtures are defined in a YAML file. Here is its general structure:
examples/fixtures.yaml
In this example:
toaster
,toast1
andtoast2
are the fixture keys.model
is where to get the model. Both relative and absolute addressing are supportedfields
are provided as argument when instantiating the class:Toaster(**fields)
.!rel
lets you create relationships by pointing to another fixture key.!now
lets you enter timestamps. It supports basic operations (adding/subtracting days, months, years). Note that!now
is evaluated when the fixture file is read, not when the test is run.
A fixture has an identifier (in the example above, toaster
is one of the fixture identifiers), as well as the following configuration:
fields
: a dictionary for which keys are attribute, and values are their valuesmodel
gives information about how to retrieve the modelpost_creation
lets you have some attribute values be assigned after instantiation.
Fixtures can inherit from other fixtures.
examples/fixtures_inheritance.yaml
>>> import pprint >>> from charlatan import FixturesManager >>> manager = FixturesManager() >>> manager.load("docs/examples/fixtures_inheritance.yaml") >>> manager.get_fixture("first") {'foo': 'bar'} >>> manager.get_fixture("second") {'foo': 'bar'} >>> pprint.pprint(manager.get_fixture("third")) {'foo': 'bar', 'toaster': 'toasted'} >>> fourth = manager.get_fixture("fourth") >>> fourth Counter({'foo': 'bar'}) >>> fourth.__class__.__name__ 'Counter' >>> fifth = manager.get_fixture("fifth") >>> fifth Counter({'toaster': 'toasted', 'foo': 'bar'}) >>> fifth.__class__.__name__ 'Counter'
0.2.4 Fixtures can now inherits from other fixtures.
If you don't specify the model, the content of fields
will be returned as is. This is useful if you want to enter a dictionary or a list directly.
examples/fixtures_dict.yaml
>>> manager = FixturesManager() >>> manager.load("docs/examples/fixtures_dict.yaml") >>> manager.get_fixture("fixture_name") {'foo': 'bar'} >>> manager.get_fixture("fixture_list") ['foo', 'bar']
0.2.4 Empty models are allowed so that dict ands lists can be used as fixtures.
You can also get a fixture directly from the database (it uses sqlalchemy
): in this case, you just need to specify the model
and an id
.
examples/fixtures_id.yaml
If a fixture depends on some side effect of another fixture, you can mark that dependency (and, necessarily, ordering) by using the depend_on
section.
examples/dependencies.yaml
0.2.7
Example:
user:
fields:
name: Michel Audiard
model: User
post_creation:
has_used_toaster: true
# Note that rel are allowed in post_creation
new_toaster: !rel blue_toaster
For a given fixture, post_creation
lets you change some attributes after instantiation. Here's the pseudo-code:
instance = ObjectClass(**fields)
for k, v in post_creation:
setattr(instance, k, v)
0.2.0 It is now possible to use rel
in post_creation.
Example:
examples/relationships.yaml
To link to another object defined in the configuration file, use !rel
. You can link to another objet (e.g. !rel toaster
) or to another object's attribute (e.g. !rel toaster.color
).
>>> manager = FixturesManager() >>> manager.load("docs/examples/relationships.yaml", ... models_package="charlatan.tests.fixtures.simple_models") >>> manager.get_fixture("user").toasters [<Toaster 'red'>] >>> manager.get_fixture("toaster_colors") {'color': 'red'}
You can also link to specific attributes of collection's item (see collection
for more information about collections).
examples/relationships.yaml
>>> manager.get_fixture("toaster_from_collection") <Toaster 'red'>
0.2.0 It is now possible to link to another object' attribute.
Charlatan also provides more efficient way to define variations of fixtures. The basic idea is to define the model and the default fields, then use the objects
key to define related fixtures. There's two ways to define those fixtures in the objects
key:
- Use a list. You will then be able to access those fixtures via their index, e.g.
toaster.0
for the first item. - Use a dict. The key will be the name of the fixture, the value a dict of fields. You can access them via their namespace: e.g.
toaster.blue
.
You can also install all of them by installing the name of the collection.
examples/collection.yaml
Here's how you would use this fixture file to access specific fixtures:
>>> manager = FixturesManager() >>> manager.load("docs/examples/collection.yaml") >>> manager.get_fixture("toasters.green") <Toaster 'green'> >>> manager.get_fixture("anonymous_toasters.0") <Toaster 'yellow'>
You can also access the whole collection:
>>> pprint.pprint(manager.get_fixture("toasters")) {'blue': <Toaster 'blue'>, 'green': <Toaster 'green'>} >>> manager.get_fixture("anonymous_toasters") [<Toaster 'yellow'>, <Toaster 'black'>]
Like any fixture, this collection can be linked to in a relationship using the !rel
keyword in an intuitive way.
examples/collection.yaml
>>> pprint.pprint(manager.get_fixture("collection")) {'things': {'blue': <Toaster 'blue'>, 'green': <Toaster 'green'>}} >>> user1 = manager.get_fixture("users.1") >>> user1.toasters [<Toaster 'blue'>, <Toaster 'green'>] >>> user2 = manager.get_fixture("users.2") >>> user2.toasters [<Toaster 'yellow'>, <Toaster 'black'>] >>> manager.get_fixture("users.3").toasters [<Toaster 'green'>] >>> manager.get_fixture("users.4").toasters [<Toaster 'yellow'>]
0.3.4 Access to unnamed fixture by using a .{index}
notation instead of _{index}
.
0.3.4 You can now have list of named fixtures.
0.2.8 It is now possible to retrieve lists of fixtures and link to them with !rel
Use !now
:
!now +1y
returns the current datetime plus one year!now +5m
returns the current datetime plus five months!now -10d
returns the current datetime minus ten days!now +15M
(note the case) returns the current datetime plus 15 minutes!now -30s
returns the current datetime minus 30 seconds
For Unix timestamps (seconds since the epoch) you can use !epoch_now
:
!epoch_now +1d
returns the current datetime plus one year in seconds since the epoch
All the same time deltas work.
0.2.9 It is now possible to use times in seconds since the epoch
0.3.5
In python 2 strings are not, by default, loaded as unicode. To load all the strings from the yaml files as unicode strings, pass the option unicode_output as True when you instantiate your fixture manager.