Using Fixtures

Fixtures establish data that’s predictable in each test run for making assertions.

They can be defined in the fixturesMethod defined in the codeception.yml file. You can read more in the Yii2 docs (opens new window) about fixture classes and data and how these can be used for testing.

To setup fixtures Create a folder called fixtures in your tests folder. In this folder we will put our fixture classes and fixture data.

# Craft-Specific Data

Regular fixtures will suffice for traditional database rows. Because Craft utilizes complex linked data structures, it introduces some of its own fixtures for an improved testing experience.

# Element Fixtures

Craft’s powerful element types are a key selling point for developers, but their under-the-hood complexity can be a challenge for testing. For this reason, Craft’s test suite provides support for setting up various element types.

Craft’s element fixtures are based on the robuust (opens new window) team’s Fixtures plugin (opens new window).

# Working with your own custom element type?

You can extend craft\test\fixtures\elements\ElementFixture (opens new window) for your own testing and to offer other developers the ability to use your element type as a fixture testing their code.

# Asset Fixtures

You can add Asset fixtures by extending craft\test\fixtures\elements\AssetFixture (opens new window).

The fixture data file could look like this:

<?php

return [
    [
        'tempFilePath' => 'path/to/_craft/storage/runtime/temp/product.jpg',
        'filename' => 'product.jpg',
        'volumeId' => $this->volumeIds['products'],
        'folderId' => $this->folderIds['clothes'],
    ],
];

product.jpg should live alongside other testing assets in tests/_craft/assets.

This will upload and link product.jpg as an Asset.

AssetFixture will define $this->volumeIds and $this->folderIds with their handles as key.

The primary keys are: volumeId, folderId, filename and title.

The AssetFixture class will automatically copy your assets into the tests/_craft/storage/runtime/temp folder. Please ensure the tempFilePath points to a filename this directory.

# Category Fixtures

You can add Category fixtures by extending craft\test\fixtures\elements\CategoryFixture (opens new window).

The fixture data file could look like this:

<?php

return [
    [
        'groupId' => $this->groupIds['categories'],
        'title' => 'Category',
    ],
];

CategoryFixture will define $this->groupIds with all category group handles as key.

The primary keys are: siteId, groupId and title.

# Entry Fixtures

You can add Entry fixtures by extending craft\test\fixtures\elements\EntryFixture (opens new window).

The fixture data file could look like this:

<?php

return [
    [
        'sectionId' => $this->sectionIds['home'],
        'typeId' => $this->typeIds['home']['home'],
        'title' => 'Home',
    ],
];

EntryFixture will define $this->sectionIds with all section handles as key. It will also define $this->typeIds with all section handles as the first key and the entry type handles as the second key.

The primary keys are: siteId, sectionId, typeId and title.

# Global Set Fixture

You can add global set fixtures by extending craft\test\fixtures\elements\GlobalSetFixture (opens new window).

The fixture data file could look like this:

<?php

return [
    [
        'handle' => 'aHandle',
    ],
];

The primary keys are: handle.

By default, a global set doesn’t get its own database row. If you need it to, you can set $useActiveRecord to true.

# Tag Fixtures

You can add Tag fixtures by extending craft\test\fixtures\elements\TagFixture (opens new window).

The fixture data file could look like this:

<?php

return [
    [
        'groupId' => $this->groupIds['tags'],
        'title' => 'Tag',
    ],
];

TagFixture will define $this->groupIds with all tag group handles as key.

The primary keys are: siteId, groupId and title.

# User Fixtures

You can add User fixtures by extending craft\test\fixtures\elements\UserFixture (opens new window).

The fixture data file could look like this:

<?php

return [
    [
        'username' => 'User',
        'email' => 'me@domain.tld',
    ],
];

The primary keys are: siteId, username and email.

# Element Fixture Field Layout & Content

If you pass a fieldLayoutType into any class that extends the base ElementFixture class, Craft will automatically try to find the associated field layout and link it to the new Element you’re creating.

If you want to set custom field values you can simply include those into your fixture data file, prefixing the custom field handle with field:.

Here’s an example of a fixture data file that creates an entry with a title and custom fields:

<?php
return [
    [
        // Standard `craft\elements\Entry` fields.
        'authorId' => '1',
        'sectionId' => '1000',
        'typeId' => '1000',
        'title' => 'Theories of matrix',

        // Set a field layout
        'fieldLayoutType' => 'field_layout_with_matrix_and_normal_fields',

        // Set custom field values
        'field:myPlainTextFieldHandle' => 'value of text field',
        'field:myOtherPlainTextFieldHandle' => 'another value',

        // Set custom Matrix field values
        'field:matrixFirst' => [
            'new1' => [
                'type' => 'myBlockType',
                'fields:mySubfield' => 'Some text'
            ],
            'new2' => [
                'type' => 'myBlockType',
                'fields:mySubfield' => 'Some text'
            ],
        ],
    ]
];

# Field Layout Fixtures

Field Layouts are another Craft-specific concept. They consist of:

  • the layouts themselves
  • Tabs
  • Fields

These are linked to one another and would be difficult to manage in a test environment with ordinary fixtures. Craft provides a special FieldLayoutFixture (opens new window) class that provides all the required support for field layouts along with their tabs and the underlying fields—this includes creating the fields in the {{%content}} table.

To use this, first create an ordinary fixture class extending craft\test\fixtures\FieldLayoutFixture (opens new window).

Then, add the public $dataFile = 'path/to/datafile/ property that points to a datafile containing at least the following keys (including the nested position).

<?php
use craft\fields\Matrix;
use craft\fields\PlainText;

return [
    [
        'type' => 'craft\test\Craft', // Required - can be set to whatever you want.
        'tabs' => [ // Required - Value can be set to an empty array[]
            [
                'name' => 'My First Tab', // Required
                'fields' => [ // Required - Value can be set to an empty array[]
                    [
                        'layout-link' => [ // Required
                            'required' => true // Required
                        ],
                        'field' => [
                            'name' => 'Test field', // Required
                            'handle' => 'myTestField', // Required
                            'fieldType' => PlainText::class, // Required
                        ]
                    ],
                    // Matrix fields are supported in the following config:
                    [
                        'layout-link' => [
                            'required' => false
                        ],
                        'field' => [
                            'name' => 'Matrix Field',
                            'handle' => 'myMatrixField',
                            'fieldType' => Matrix::class,
                            'blockTypes' => [
                                'new1' => [
                                    'name' => 'A Block',
                                    'handle' => 'myMatrixBlock',
                                    'fields' => [
                                        'new1' => [
                                            'type' => PlainText::class,
                                            'name' => 'First Subfield',
                                            'handle' => 'myBlockField',
                                            'instructions' => '',
                                            'required' => false,
                                            'typesettings' => [
                                                'multiline' => ''
                                            ]
                                        ]
                                    ]
                                ],
                                'new2' => [
                                    'name' => 'Another Block',
                                    'handle' => 'myOtherMatrixBlock',
                                    'fields' => [
                                        'new1' => [
                                            'type' => PlainText::class,
                                            'name' => 'Another Subfield',
                                            'handle' => 'myOtherBlockField',
                                            'instructions' => '',
                                            'required' => false,
                                            'typesettings' => [
                                                'multiline' => ''
                                            ]
                                        ]
                                    ]
                                ]
                            ]
                        ]
                    ],
                ]
            ]
        ]
    ]
];

The value part of the key-value pairs can be set to whatever is required for your project. It’s crucial that the array keys are set with any string value. You can add your own parameters to the array value of the field key, as long as they correspond to public properties in the class defined in the fieldType key.