Data Fixtures
PHP Data Fixtures
// dev/tests/integration/fixtures/customer.php
<?php
return [
'customer' => [
'email' => 'fixture@example.com',
'firstname' => 'Fixture',
'lastname' => 'Customer',
'group_id' => 1,
'default_billing' => 1,
'default_shipping' => 1,
],
'address' => [
'firstname' => 'Fixture',
'lastname' => 'Customer',
'street' => ['123 Fixture St'],
'city' => 'Fixture City',
'region_id' => 12,
'postcode' => '12345',
'country_id' => 'US',
'telephone' => '555-123-4567',
],
];
JSON Data Fixtures
// dev/tests/integration/fixtures/product.json
[
{
"sku": "FIXTURE-001",
"name": "Fixture Product",
"price": 49.99,
"status": 1,
"visibility": 4,
"type_id": "simple",
"attribute_set_id": 4,
"stock_data": {
"qty": 100,
"is_in_stock": 1
}
}
]
Loading Fixtures in Tests
class CustomerTest extends TestCase
{
/**
* @magentoDataFixture customer.php
*/
public function testCustomerCreation()
{
$customer = Bootstrap::getObjectManager()->create(
\Magento\Customer\Model\Customer::class
);
$this->assertEquals('fixture@example.com', $customer->getEmail());
}
}
Key Points
- Fixtures provide consistent test data
- Use minimal data for each test
- Load only required fixtures
- Clean up fixtures after tests
Fixture Configuration
Fixture Config Files
// dev/tests/integration/fixtures/config.php
<?php
return [
'web/secure/base_url' => 'https://magento.test/',
'web/unsecure/base_url' => 'http://magento.test/',
'general/locale/code' => 'en_US',
'general/locale/timezone' => 'America/Chicago',
'catalog/price/scope' => 0, // Global
];
Module-Specific Fixtures
<!-- app/code/Vendor/Module/etc/fixtures.xml -->
<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
<fixture name="vendor_product">
<class>Vendor\Module\Test\Fixture\ProductFixture</class>
</fixture>
</config>
Custom Fixture Classes
namespace Vendor\Module\Test\Fixture;
use Magento\TestFramework\Fixture\FixtureInterface;
class ProductFixture implements FixtureInterface
{
private $objectManager;
public function __construct($objectManager)
{
$this->objectManager = $objectManager;
}
public function load()
{
$product = $this->objectManager->create(
\Magento\Catalog\Model\Product::class
);
$product->setData([
'sku' => 'FIXTURE-PRODUCT-001',
'name' => 'Fixture Product',
'price' => 29.99,
'status' => 1,
'visibility' => 4,
'type_id' => 'simple',
'attribute_set_id' => 4,
]);
$product->save();
return $product;
}
}
Key Points
- Configuration fixtures set system values
- Module fixtures are reusable across tests
- Custom fixtures implement FixtureInterface
- Fixtures can depend on other fixtures
Test Data Generation
Faker for Test Data
use Faker\Factory;
class TestDataGenerator
{
private $faker;
public function __construct()
{
$this->faker = Factory::create();
}
public function generateCustomer(): array
{
return [
'email' => $this->faker->unique()->safeEmail(),
'firstname' => $this->faker->firstName(),
'lastname' => $this->faker->lastName(),
'telephone' => $this->faker->phoneNumber(),
'street' => [$this->faker->streetAddress()],
'city' => $this->faker->city(),
'postcode' => $this->faker->postcode(),
'country_id' => 'US',
'region_id' => $this->faker->numberBetween(1, 50),
];
}
public function generateProduct(): array
{
return [
'sku' => $this->faker->unique()->bothify('TEST-####'),
'name' => $this->faker->words(3, true),
'price' => $this->faker->randomFloat(2, 10, 1000),
'description' => $this->faker->paragraph(),
'status' => 1,
'visibility' => 4,
'type_id' => 'simple',
];
}
}
Magento Test Data
use Magento\TestFramework\Helper\DataFixture\DefaultFixture;
class ProductWithDefaults
{
public function getData(): array
{
return [
'sku' => DefaultFixture::getSku(),
'name' => DefaultFixture::getProductName(),
'price' => DefaultFixture::getPrice(),
'status' => DefaultFixture::PRODUCT_STATUS_ENABLED,
'visibility' => DefaultFixture::PRODUCT_VISIBILITY_BOTH,
];
}
}
Key Points
- Use Faker for random but realistic data
- Ensure data uniqueness for constraints
- Generate data appropriate for field types
- Consider performance for large datasets
Fixture Cleanup
Automatic Cleanup
// Using @magentoDbIsolation
class IsolatedTest extends TestCase
{
/**
* @magentoDbIsolation enabled
*/
public function testDataCleanup()
{
// Changes are automatically rolled back
$product = $this->createProduct();
$this->assertNotEmpty($product->getId());
}
}
Manual Cleanup
class ManualCleanupTest extends TestCase
{
private $createdIds = [];
protected function tearDown(): void
{
$connection = Bootstrap::getObjectManager()->get(
\Magento\Framework\App\ResourceConnection::class
)->getConnection();
foreach ($this->createdIds as $id) {
$connection->delete('catalog_product_entity', ['entity_id = ?' => $id]);
}
}
private function createProduct(): int
{
$product = $this->objectManager->create(
\Magento\Catalog\Model\Product::class
);
$product->setData([
'sku' => 'TEST-' . uniqid(),
'name' => 'Test Product',
'price' => 99.99,
'status' => 1,
'visibility' => 4,
'type_id' => 'simple',
'attribute_set_id' => 4,
]);
$product->save();
$this->createdIds[] = $product->getId();
return $product->getId();
}
}
Cleanup Scripts
#!/bin/bash
# cleanup-fixtures.sh
mysql -u root -e "
DELETE FROM catalog_product_entity WHERE sku LIKE 'TEST-%';
DELETE FROM customer_entity WHERE email LIKE '%@test.example';
DELETE FROM sales_order WHERE increment_id LIKE '10000000%';
"
Key Points
- Use transactions for automatic cleanup
- Track created entities for manual cleanup
- Clean up in tearDown() method
- Consider foreign key constraints
Practice Problems
0 / 1 solved
Create Fixture Suite
Create a complete fixture suite for testing a product catalog including products, categories, and inventory.
Solution
// category.php
<?php
return [
'category' => [
'name' => 'Test Category',
'is_active' => 1,
'path' => '1/2/3',
'level' => 2,
'position' => 1,
],
];
// product.json
[
{
"sku": "FIXTURE-PRODUCT-001",
"name": "Fixture Product",
"price": 49.99,
"status": 1,
"visibility": 4,
"type_id": "simple",
"attribute_set_id": 4,
"category_ids": [3]
}
]
// In test:
/**
* @magentoDataFixture category.php
* @magentoDataFixture product.json
*/
public function testProductInCategory()
{
// Test product is in category
} Quiz
1. What is the purpose of test fixtures?
2. How do fixtures clean up automatically?
3. What is Faker used for?
4. Where are module fixtures defined?
Flashcards
Question
Fixture purpose?
Click to reveal answer
Answer
Provide consistent, reusable test data
Question
Automatic cleanup method?
Click to reveal answer
Answer
@magentoDbIsolation with transactions
Question
Faker library use?
Click to reveal answer
Answer
Generate random but realistic test data
Question
Module fixture location?
Click to reveal answer
Answer
etc/fixtures.xml
Revision Notes
Key Takeaways
- 1. Fixtures provide consistent test data
- 2. Use @magentoDbIsolation for automatic cleanup
- 3. Faker generates realistic random data
- 4. Keep fixtures minimal and focused
Interview Tips
- • Explain fixture vs mock differences
- • Discuss cleanup strategies
- • Know how to generate test data
Cheat Sheet
Test Fixtures
- Format: PHP, JSON
- Load: @magentoDataFixture
- Cleanup: @magentoDbIsolation
- Generate: Faker library
- Location: dev/tests/integration/fixtures/