Skip to content
intermediate Phase 74 · Testing Advanced

Test Fixtures

45m
1 problems
Topic Progress 0%

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?

Question 1 options

2. How do fixtures clean up automatically?

Question 2 options

3. What is Faker used for?

Question 3 options

4. Where are module fixtures defined?

Question 4 options

Flashcards

Question

Fixture purpose?

Answer

Provide consistent, reusable test data

Question

Automatic cleanup method?

Answer

@magentoDbIsolation with transactions

Question

Faker library use?

Answer

Generate random but realistic test data

Question

Module fixture location?

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/