tddwizard / magento2-fixtures
tddwizard/magento2-fixtures
Fixture library for Magento 2 integration tests
TddWizard Fixture library
Magento 2 Fixtures by Fabian Schmengler
What is it?
An alternative to the procedural script based fixtures in Magento 2 integration tests.
It aims to be:
- extensible
- expressive
- easy to use
Installation
Install it into your Magento 2 project with composer:
composer require --dev tddwizard/magento2-fixtures
Requirements
- Magento 2.3 or Magento 2.4
- PHP 7.3 or 7.4 (7.1 and 7.2 is allowed via composer for full Magento 2.3 compatibility but not tested anymore)
Usage examples:
Customer
If you need a customer without specific data, this is all:
protected function setUp(): void
{
$this->customerFixture = new CustomerFixture(
CustomerBuilder::aCustomer()->build()
);
}
protected function tearDown(): void
{
$this->customerFixture->rollback();
}
It uses default sample data and a random email address. If you need the ID or email address in the tests, the CustomerFixture gives you access:
$this->customerFixture->getId();
$this->customerFixture->getEmail();
You can configure the builder with attributes:
CustomerBuilder::aCustomer()
->withEmail('[email protected]')
->withCustomAttributes(
[
'my_custom_attribute' => 42
]
)
->build()
You can add addresses to the customer:
CustomerBuilder::aCustomer()
->withAddresses(
AddressBuilder::anAddress()->asDefaultBilling(),
AddressBuilder::anAddress()->asDefaultShipping(),
AddressBuilder::anAddress()
)
->build()
Or just one:
CustomerBuilder::aCustomer()
->withAddresses(
AddressBuilder::anAddress()->asDefaultBilling()->asDefaultShipping()
)
->build()
The CustomerFixture also has a shortcut to create a customer session:
$this->customerFixture->login();
Addresses
Similar to the customer builder you can also configure the address builder with custom attributes:
AddressBuilder::anAddress()
->withCountryId('DE')
->withCity('Aachen')
->withPostcode('52078')
->withCustomAttributes(
[
'my_custom_attribute' => 42
]
)
->asDefaultShipping()
Product
Product fixtures work similar as customer fixtures:
protected function setUp(): void
{
$this->productFixture = new ProductFixture(
ProductBuilder::aSimpleProduct()
->withPrice(10)
->withCustomAttributes(
[
'my_custom_attribute' => 42
]
)
->build()
);
}
protected function tearDown(): void
{
$this->productFixture->rollback();
}
The SKU is randomly generated and can be accessed through ProductFixture, just as the ID:
$this->productFixture->getSku();
$this->productFixture->getId();
Cart/Checkout
To create a quote, use the CartBuilder together with product fixtures:
$cart = CartBuilder::forCurrentSession()
->withSimpleProduct(
$productFixture1->getSku()
)
->withSimpleProduct(
$productFixture2->getSku(), 10 // optional qty parameter
)
->build()
$quote = $cart->getQuote();
Checkout is supported for logged in customers. To create an order, you can simulate the checkout as follows, given a customer fixture with default shipping and billing addresses and a product fixture:
$customerFixture = new CustomerFixture(CustomerBuilder::aCustomer()->withAddresses(
AddressBuilder::anAddress()->asDefaultBilling(),
AddressBuilder::anAddress()->asDefaultShipping()
)->build());
$customerFixture->login();
$checkout = CustomerCheckout::fromCart(
CartBuilder::forCurrentSession()
->withProductRequest(ProductBuilder::aVirtualProduct()->build()->getSku())
->build()
);
$order = $checkout->placeOrder();
It will try to select the default addresses and the first available shipping and payment methods.
You can also select them explicitly:
$order = $checkout
->withShippingMethodCode('freeshipping_freeshipping')
->withPaymentMethodCode('checkmo')
->withCustomerBillingAddressId($this->customerFixture->getOtherAddressId())
->withCustomerShippingAddressId($this->customerFixture->getOtherAddressId())
->placeOrder();
Order
The OrderBuilder is a shortcut for checkout simulation.
$order = OrderBuilder::anOrder()->build();
Logged-in customer, products, and cart item quantities will be
generated internally unless more control is desired:
$order = OrderBuilder::anOrder()
->withProducts(
// prepare catalog product fixtures
ProductBuilder::aSimpleProduct()->withSku('foo'),
ProductBuilder::aSimpleProduct()->withSku('bar')
)->withCart(
// define cart item quantities
CartBuilder::forCurrentSession()->withSimpleProduct('foo', 2)->withSimpleProduct('bar', 3)
)->build();
Shipment
Orders can be fully or partially shipped, optionally with tracks.
$order = OrderBuilder::anOrder()->build();
// ship everything
$shipment = ShipmentBuilder::forOrder($order)->build();
// ship only given order items, add tracks
$shipment = ShipmentBuilder::forOrder($order)
->withItem($fooItemId, $fooQtyToShip)
->withItem($barItemId, $barQtyToShip)
->withTrackingNumbers('123-FOO', '456-BAR')
->build();
Invoice
Orders can be fully or partially invoiced.
$order = OrderBuilder::anOrder()->build();
// invoice everything
$invoice = InvoiceBuilder::forOrder($order)->build();
// invoice only given order items
$invoice = InvoiceBuilder::forOrder($order)
->withItem($fooItemId, $fooQtyToInvoice)
->withItem($barItemId, $barQtyToInvoice)
->build();
Credit Memo
Credit memos can be created for either all or some of the items ordered.
An invoice to refund will be created internally.
$order = OrderBuilder::anOrder()->build();
// refund everything
$creditmemo = CreditmemoBuilder::forOrder($order)->build();
// refund only given order items
$creditmemo = CreditmemoBuilder::forOrder($order)
->withItem($fooItemId, $fooQtyToRefund)
->withItem($barItemId, $barQtyToRefund)
->build();
Fixture pools
To manage multiple fixtures, fixture pools have been introduced for all entities:
Usage demonstrated with the ProductFixturePool:
protected function setUp()
{
$this->productFixtures = new ProductFixturePool;
}
protected function tearDown()
{
$this->productFixtures->rollback();
}
public function testSomethingWithMultipleProducts()
{
$this->productFixtures->add(ProductBuilder::aSimpleProduct()->build());
$this->productFixtures->add(ProductBuilder::aSimpleProduct()->build(), 'foo');
$this->productFixtures->add(ProductBuilder::aSimpleProduct()->build());
$this->productFixtures->get(); // returns ProductFixture object for last added product
$this->productFixtures->get('foo'); // returns ProductFixture object for product added with specific key 'foo'
$this->productFixtures->get(0); // returns ProductFixture object for first product added without specific key (numeric array index)
}
Config Fixtures
With the config fixture you can set a configuration value globally, i.e. it will ensure that it is not only set in the default scope but also in all store scopes:
ConfigFixture::setGlobal('general/store_information/name', 'Ye Olde Wizard Shop');
It uses MutableScopeConfigInterface, so the configuration is not persisted in the database. Use @magentoAppIsolation enabled in your test to make sure that changes are reverted in subsequent tests.
You can also set configuration values explicitly for stores with ConfigFixture::setForStore()
Credits
License
The MIT License (MIT). Please see License File for more information.
No changelog yet
The vendor hasn't published a changelog. Tagged releases appear in the Versions tab.
| Version | Stability | QA Status | Compatibility | Released |
|---|---|---|---|---|
| 1.2.0 | stable | Fail | Magento 2.4.7-2.4.9 Details | 2025-10-24 09:33:50 |
| 1.1.2 | stable | Not tested | Not yet tested Details | 2022-05-24 15:35:13 |
| 1.1.1 | stable | Not tested | Not yet tested Details | 2022-04-28 07:29:11 |
| 1.1.0 | stable | Not tested | Not yet tested Details | 2021-05-05 06:37:45 |
| 1.1.0-rc1 | RC | Not tested | Not yet tested Details | 2021-02-18 09:55:31 |
| 1.0.0 | stable | Not tested | Not yet tested Details | 2020-10-03 19:50:59 |
| 0.12.1 | stable | Not tested | Not yet tested Details | 2020-09-03 16:21:39 |
| 0.12.0 | stable | Not tested | Not yet tested Details | 2020-08-27 15:27:04 |
| 0.11.0 | stable | Not tested | Not yet tested Details | 2020-07-28 14:43:43 |
| 0.10.0 | stable | Not tested | Not yet tested Details | 2020-05-08 21:27:51 |
| 0.9.0 | stable | Not tested | Not yet tested Details | 2020-04-07 18:29:47 |
| 0.8.0 | stable | Not tested | Not yet tested Details | 2019-03-01 23:15:23 |
| 0.7.0 | stable | Not tested | Not yet tested Details | 2018-11-22 11:37:07 |
| 0.6.0 | stable | Not tested | Not yet tested Details | 2018-11-15 21:07:56 |
| 0.5.0 | stable | Not tested | Not yet tested Details | 2018-10-16 16:59:28 |
| 0.4.0 | stable | Not tested | Not yet tested Details | 2018-09-27 07:53:55 |
| 0.3.1 | stable | Not tested | Not yet tested Details | 2018-01-11 13:13:54 |
| 0.3.0 | stable | Not tested | Not yet tested Details | 2017-12-14 14:55:56 |
| 0.2.0 | stable | Not tested | Not yet tested Details | 2017-12-14 11:08:55 |
| 0.1.1 | stable | Not tested | Not yet tested Details | 2017-10-05 18:01:55 |
| 0.1.0 | stable | Not tested | Not yet tested Details | 2017-08-05 23:05:02 |
Requires 13
| Package | Constraint |
|---|---|
| php | ^7.1|^8.0 |
| magento/framework | ^102.0|^103.0 |
| magento/zendframework1 | ^1.14 |
| magento/module-catalog | ^103.0|^104.0 |
| magento/module-catalog-inventory | ^100.3 |
| magento/module-checkout | ^100.3 |
| magento/module-customer | ^102.0|^103.0 |
| magento/module-directory | ^100.3 |
| magento/module-indexer | ^100.3 |
| magento/module-payment | ^100.3 |
| magento/module-quote | ^101.1 |
| magento/module-sales | ^102.0|^103.0 |
| fakerphp/faker | ^1.9.1 |
Requires-dev 7
| Package | Constraint |
|---|---|
| ext-json | * |
| magento/module-store | ^101.0 |
| phpunit/phpunit | ^6.0|^9.0 |
| pds/skeleton | ^1.0 |
| phpro/grumphp | ^0.19.0 |
| phpstan/phpstan | ^0.12.0 |
| squizlabs/php_codesniffer | ^3.3.1 |
Compatibility
Each Magento release line is installed on its supported PHP versions, then the module is built (DI compilation + static-content deploy) and its unit and integration suites are run. The matrix shows the lines and PHP versions the module is confirmed to install and run on. Code-quality results further down (phpstan, phpcs, …) are reported separately and never affect compatibility.
Code Quality
Advisory checks against the module's source. Static analysis runs once across the whole module; PHPStan re-runs per Magento + PHP version because resolvable symbols differ between releases. These NEVER affect the Compatibility badge. A phpcs finding can't make a module incompatible.
Static analysis
Coding standards (phpcs), mess detection (phpmd), copy-pasted code (cpd), PHP cross-version compatibility, composer.json validity. Each runs once for the whole module.
PHPStan
Type-checks the module's PHP against a real Magento install at the configured gate level. Re-runs per Magento and PHP version because resolvable symbols differ between releases.
Tests
Unit and integration suites, run for each applicable Magento and PHP version. A test failure speaks to the module's behaviour, not its compatibility with a Magento line, so it is reported here separately and never reddens the compatibility matrix.
Unit tests
| Magento | PHP 8.2 | PHP 8.3 | PHP 8.4 | PHP 8.5 |
|---|---|---|---|---|
| 2.4.7 | N/A | N/A | ||
| 2.4.8 | N/A | N/A | ||
| 2.4.9 | N/A | N/A |
Integration tests
| Magento | PHP 8.2 | PHP 8.3 | PHP 8.4 | PHP 8.5 |
|---|---|---|---|---|
| 2.4.7 | N/A | N/A | ||
| 2.4.8 | N/A | N/A | ||
| 2.4.9 | N/A | N/A |
Security
Security checks run directly against the module: an audit of its declared dependencies for known vulnerabilities (composer audit) and a scan of its source for malware and web-shell signatures. Each runs once. A malware detection fails the version outright.
Turn an existing module into recurring revenue.
If you already maintain a Magento 2 module on GitHub or GitLab, listing it on Packagento takes about five minutes. We mirror your tags, handle distribution signing, and route paid licenses through Stripe Connect, so you can keep shipping the way you already do.