Data fixture annotation
A data fixture is a PHP script that sets data you want to reuse in your test. The script can be defined in a separate file or as a local test case method.
Use data fixtures to prepare a database for tests.
The Integration Testing Framework (ITF) reverts the database to its initial state automatically.
To set up a date fixture, use the @magentoDataFixture
annotation.
Format
@magentoDataFixture
takes an argument that points to the data fixture as a filename or local method.
1
2
3
/**
* @magentoDataFixture <script_filename>|<method_name>
*/
<script_filename>
is a filename of the PHP script.<method_name>
is a name of the method declared in the current class.
Principles
- Do not use a direct database connection in fixtures to avoid dependencies on the database structure and vendor.
- Use an application API to implement your data fixtures.
- A method that implements a data fixture must be declared as
public
andstatic
. - Fixtures declared at a test level have a higher priority then fixtures declared at a test case level.
- Test case fixtures are applied to each test in the test case, unless a test has its own fixtures declared.
- Annotation declaration at a test case level does not affect tests that have their own annotation declarations.
Usage
As was mentioned above, there are two ways to declare fixtures:
- as a PHP script file that is used by other tests and test cases.
- as a local method that is used by other tests in the test cases.
Fixture as a separate file
Define the fixture in a separate file when you want to reuse it in different test cases. To declare the fixture, use the following conventions for a path
- Relative to
dev/tests/integration/<test suite directory>
- With forward slashes
/
- No leading slash
Example:
Magento/Cms/_files/pages.php
The ITF includes the declared PHP script to your test and executes it during test run.
The following example demonstrates a simple implementation of a Cms module page test from the Magento codebase.
Data fixture to test a Cms module page (dev/tests/integration/testsuite/Magento/Cms/_files/pages.php
):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<?php
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
/** @var $page \Magento\Cms\Model\Page */
$page = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->create('Magento\Cms\Model\Page');
$page->setTitle('Cms Page 100')
->setIdentifier('page100')
->setStores([0])
->setIsActive(1)
->setContent('<h1>Cms Page 100 Title</h1>')
->setPageLayout('1column')
->save();
$page = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->create('Magento\Cms\Model\Page');
$page->setTitle('Cms Page Design Blank')
->setIdentifier('page_design_blank')
->setStores([0])
->setIsActive(1)
->setContent('<h1>Cms Page Design Blank Title</h1>')
->setPageLayout('1column')
->setCustomTheme('Magento/blank')
->save();
Test case that uses the above data fixture (dev/tests/integration/testsuite/Magento/Cms/Block/PageTest.php
):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
<?php
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
namespace Magento\Cms\Block;
class PageTest extends \PHPUnit_Framework_TestCase
{
/**
* @magentoAppIsolation enabled
* @magentoDataFixture Magento/Cms/_files/pages.php
*/
public function testGetPage()
{
$page = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->get('Magento\Cms\Model\Page');
$page->load('page100', 'identifier');
$layout = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->get(
'Magento\Framework\View\LayoutInterface'
);
$pageBlock = $layout->createBlock('Magento\Cms\Block\Page');
$pageBlock->setData('page', $page);
$pageBlock->toHtml();
$this->assertEquals($page, $pageBlock->getPage());
}
}
Fixture as a method
The following is an example of the testCreatePageWithSameModuleName()
test method that uses data from the cmsPageWithSystemRouteFixture()
data fixture.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
<?php
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
/**
* Test class for \Magento\Cms\Controller\Page.
*/
namespace Magento\Cms\Controller;
class PageTest extends \Magento\TestFramework\TestCase\AbstractController
{
public function testViewAction()
{
$this->dispatch('/enable-cookies');
$this->assertContains('What are Cookies?', $this->getResponse()->getBody());
}
public function testViewRedirectWithTrailingSlash()
{
$this->dispatch('/enable-cookies/');
$code = $this->getResponse()->getStatusCode();
$location = $this->getResponse()->getHeader('Location')->getFieldValue();
$this->assertEquals(301, $code, 'Invalid response code');
$this->assertStringEndsWith('/enable-cookies', $location, 'Invalid location header');
}
/**
* Test \Magento\Cms\Block\Page::_addBreadcrumbs
*/
public function testAddBreadcrumbs()
{
$this->dispatch('/enable-cookies');
$layout = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->get(
'Magento\Framework\View\LayoutInterface'
);
$breadcrumbsBlock = $layout->getBlock('breadcrumbs');
$this->assertContains($breadcrumbsBlock->toHtml(), $this->getResponse()->getBody());
}
/**
* @magentoDataFixture cmsPageWithSystemRouteFixture
*/
public function testCreatePageWithSameModuleName()
{
$this->dispatch('/shipping');
$content = $this->getResponse()->getBody();
$this->assertContains('Shipping Test Page', $content);
}
public static function cmsPageWithSystemRouteFixture()
{
/** @var $page \Magento\Cms\Model\Page */
$page = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->create('Magento\Cms\Model\Page');
$page->setTitle('Test title')
->setIdentifier('shipping')
->setStores([0])
->setIsActive(1)
->setContent('<h1>Shipping Test Page</h1>')
->setPageLayout('1column')
->save();
}
}
Test case and test method scopes
The @magentoDataFixture
can be specified for a particular test or for an entire test case.
The basic rules for fixture annotation at different levels are:
@magentoDataFixture
at a test case level makes the framework to apply the declared fixtures to each test in the test case. When the final test is complete, all class-level fixtures are reverted.@magentoDataFixture
for a particular test signals the framework to revert the fixtures declared on a test case level and applies the fixtures declared at a test method level instead. When the test is complete, the ITF reverts the applied fixtures.
The integration testing framework interacts with a database to revert the applied fixtures.
Fixture rollback
A fixture that contain database transactions only are reverted automatically. Otherwise, when a fixture creates files or performs any actions other than database transaction, provide the corresponding rollback logic. Rollbacks are run after reverting all the fixtures related to database transactions.
A fixture rollback must be of the same format as the corresponding fixture: a script or a method:
- A rollback script must be named according to the corresponding fixture suffixed with
_rollback
and stored in the same directory. - Rollback methods must be of the same class as the corresponding fixture and suffixed with
Rollback
.
Examples:
Fixture/Rollback | Fixture name | Rollback name |
---|---|---|
Script | Magento/Catalog/_files/categories.php |
Magento/Catalog/_files/categories_rollback.php |
Method | \Magento\Catalog\Model\ProductTest::prepareProduct |
\Magento\Catalog\Model\ProductTest::prepareProductRollback |
Restrictions
Do not rely on and do not modify an application state from within a fixture, because application isolation annotation can reset the application state at any moment.