Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/phpunit.yml
Original file line number Diff line number Diff line change
Expand Up @@ -202,7 +202,7 @@ jobs:
strategy:
fail-fast: false
matrix:
php: [ 8.1, 8.2, 8.3, 8.4 ]
php: [ 8.2, 8.3, 8.4 ]
steps:
- name: Checkout code
uses: actions/checkout@v3
Expand Down
2 changes: 1 addition & 1 deletion UPGRADE-2.7.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ return RectorConfig::configure()
'src',
'tests'
])
->withSets([FoundrySetList::REMOVE_PROXIES])
->withSets([FoundrySetList::FOUNDRY_2_7])
;
```

Expand Down
53 changes: 53 additions & 0 deletions UPGRADE-2.8.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
# Migration guide from Foundry 2.7 to 2.8

The main feature of Foundry 2.8 is the deprecation of the `Factories` trait, in favor of the [PHPUnit extension](https://symfony.com/bundles/ZenstruckFoundryBundle/current/index.html#phpunit-extension)
shipped by Foundry. It was necessary to remember to add the trait in every test class. And in some cases, Foundry could
still work even if the trait wasn’t added to the test, which could lead to subtle bugs. Now, Foundry is globally enabled
once for all.

The trait will be removed in Foundry 3.0, and the extension will be mandatory.

> [!WARNING]
> The PHPUnit extension mechanism was introduced in PHPUnit 10. This means that Foundry 3 won't be compatible
> with PHPUnit 9 anymore (but Foundry 2 will remain compatible with PHPUnit 9).
## How to

> [!IMPORTANT]
> If you're still not using PHPUnit 10 or grater, there is nothing to do (yet!)
Enable Foundry's [PHPUnit extension](https://symfony.com/bundles/ZenstruckFoundryBundle/current/index.html#phpunit-extension)
in your `phpunit.xml` file:

```xml
<phpunit>
<extensions>
<bootstrap class="Zenstruck\Foundry\PHPUnit\FoundryExtension"/>
</extensions>
</phpunit>
```

And then, remove all the `use Factories;` statements from your factories.

## Rector rules

A Rector set is available to automatically remove the usage of the trait in all your tests.

First, you'll need to install `rector/rector`:
```shell
composer require --dev rector/rector
```

Then, create a `rector.php` file:

```php
<?php

use Rector\Config\RectorConfig;
use Zenstruck\Foundry\Utils\Rector\FoundrySetList;

return RectorConfig::configure()
->withPaths(['tests'])
->withSets([FoundrySetList::FOUNDRY_2_8])
;
```
50 changes: 33 additions & 17 deletions docs/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -1621,28 +1621,46 @@ Let's look at an example:

.. _enable-foundry-in-your-testcase:

Enable Foundry in your TestCase
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Globally Enable Foundry In PHPUnit
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Add the ``Factories`` trait for tests using factories:
Add Foundry's `PHPUnit Extension`_ in your `phpunit.xml` file:

::
.. configuration-block::

use App\Factory\PostFactory;
use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;
use Zenstruck\Foundry\Test\Factories;
.. code-block:: xml
class MyTest extends WebTestCase
{
use Factories;
<phpunit>
<extensions>
<bootstrap class="Zenstruck\Foundry\PHPUnit\FoundryExtension"/>
</extensions>
</phpunit>
.. versionadded:: 2.8

public function test_1(): void
The ability to globally enable Foundry with PHPUnit extension was introduced in Foundry 2.8 and requires at least
PHPUnit 10.

.. note::

If you're still using PHPUnit 9, Foundry can be enabled by adding the trait ``Zenstruck\Foundry\Test\Factories``
in each test::

use App\Factory\PostFactory;
use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;
use Zenstruck\Foundry\Test\Factories;

class MyTest extends WebTestCase
{
$post = PostFactory::createOne();
use Factories;

// ...
public function test_something(): void
{
$post = PostFactory::createOne();

// ...
}
}
}

Database Reset
~~~~~~~~~~~~~~
Expand Down Expand Up @@ -1795,7 +1813,7 @@ Foundry provides a mechanism to automatically refresh inside a functional test t

class MyTest extends WebTestCase
{
use Factories, ResetDatabase;
use ResetDatabase;

public function test_with_autorefresh(): void
{
Expand Down Expand Up @@ -2393,8 +2411,6 @@ any bundle configuration you have will not be picked up.

class MyUnitTest extends TestCase
{
use Factories;

public function some_test(): void
{
$post = PostFactory::createOne();
Expand Down
4 changes: 0 additions & 4 deletions phpstan.neon
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,6 @@ parameters:
- identifier: missingType.iterableValue
path: tests/

# We support both PHPUnit versions (this method changed in PHPUnit 10)
- identifier: function.impossibleType
path: src/Test/Factories.php

# PHPStan does not understand PHP version checks
- message: '#Comparison operation "(<|>|<=|>=)" between int<80\d+, 80\d+> and 80\d+ is always (false|true).#'

Expand Down
3 changes: 2 additions & 1 deletion phpunit-deprecation-baseline.xml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@
Foundry now leverages the native PHP lazy system to auto-refresh objects (it can be enabled with "zenstruck_foundry.enable_auto_refresh_with_lazy_objects" configuration).
See https://github.com/zenstruck/foundry/blob/2.x/UPGRADE-2.7.md to upgrade.]]></issue>

<issue><![CDATA[Support for MySQL < 8 is deprecated and will be removed in DBAL 5 (AbstractMySQLDriver.php:75 called by AbstractDriverMiddleware.php:32, https://github.com/doctrine/dbal/pull/6343, package doctrine/dbal)]]></issue>
<issue><![CDATA[Since zenstruck/foundry 2.8: Trait Zenstruck\Foundry\Test\Factories is deprecated and will be removed in Foundry 3. See https://github.com/zenstruck/foundry/blob/2.x/UPGRADE-2.8.md to upgrade.]]></issue>
<issue><![CDATA[Since zenstruck/foundry 2.8: Not using Foundry's PHPUnit extension is deprecated and will throw an error in Foundry 3. See https://github.com/zenstruck/foundry/blob/2.x/UPGRADE-2.8.md to upgrade.]]></issue>
</line>
</file>
<file path="vendor/doctrine/deprecations/src/Deprecation.php">
Expand Down
10 changes: 9 additions & 1 deletion src/Configuration.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@
use Zenstruck\Foundry\InMemory\CannotEnableInMemory;
use Zenstruck\Foundry\InMemory\InMemoryRepositoryRegistry;
use Zenstruck\Foundry\Persistence\PersistenceManager;
use Zenstruck\Foundry\PHPUnit\FoundryExtension;
use Zenstruck\Foundry\Test\Factories;
use Zenstruck\Foundry\Persistence\Proxy\PersistedObjectsTracker;

/**
Expand Down Expand Up @@ -117,7 +119,9 @@ public static function instance(): self
throw new FoundryNotBooted();
}

FactoriesTraitNotUsed::throwIfComingFromKernelTestCaseWithoutFactoriesTrait();
if (!FoundryExtension::isEnabled()) {
FactoriesTraitNotUsed::throwIfComingFromKernelTestCaseWithoutFactoriesTrait();
}

return \is_callable(self::$instance) ? (self::$instance)() : self::$instance;
}
Expand All @@ -131,6 +135,10 @@ public static function isBooted(): bool
public static function boot(\Closure|self $configuration): void
{
self::$instance = $configuration;

if (FoundryExtension::shouldBeEnabled()) {
trigger_deprecation('zenstruck/foundry', '2.8', 'Not using Foundry\'s PHPUnit extension is deprecated and will throw an error in Foundry 3. See https://github.com/zenstruck/foundry/blob/2.x/UPGRADE-2.8.md to upgrade.');
}
}

/** @param \Closure():self|self $configuration */
Expand Down
8 changes: 7 additions & 1 deletion src/Exception/FoundryNotBooted.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,19 @@

namespace Zenstruck\Foundry\Exception;

use Zenstruck\Foundry\PHPUnit\FoundryExtension;

/**
* @author Kevin Bond <[email protected]>
*/
final class FoundryNotBooted extends \LogicException
{
public function __construct()
{
parent::__construct('Foundry is not yet booted. Ensure ZenstruckFoundryBundle is enabled. If in a test, ensure your TestCase has the Factories trait.');
$message = FoundryExtension::isEnabled()
? 'Foundry is not yet booted. Ensure ZenstruckFoundryBundle is enabled. If in a test, ensure Foundry\'s PHPUnit extension is enabled.'
: 'Foundry is not yet booted. Ensure ZenstruckFoundryBundle is enabled. If in a test, ensure your TestCase has the Factories trait.';

parent::__construct($message);
}
}
38 changes: 0 additions & 38 deletions src/PHPUnit/BootFoundryOnDataProviderMethodCalled.php

This file was deleted.

65 changes: 65 additions & 0 deletions src/PHPUnit/BootFoundryOnPreparationStarted.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
<?php

declare(strict_types=1);

/*
* This file is part of the zenstruck/foundry package.
*
* (c) Kevin Bond <[email protected]>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace Zenstruck\Foundry\PHPUnit;

use PHPUnit\Event;
use PHPUnit\Framework\TestCase;
use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase;
use Zenstruck\Foundry\Configuration;
use Zenstruck\Foundry\Test\UnitTestConfig;

/**
* @internal
* @author Nicolas PHILIPPE <[email protected]>
*/
final class BootFoundryOnPreparationStarted implements Event\Test\PreparationStartedSubscriber
{
public function notify(Event\Test\PreparationStarted $event): void
{
$test = $event->test();

if (!$test->isTestMethod()) {
return;
}
/** @var Event\Code\TestMethod $test */

$this->bootFoundry($test->className());
}

/**
* @param class-string $className
*/
private function bootFoundry(string $className): void
{
if (!\is_subclass_of($className, TestCase::class)) {
return;
}

// unit test
if (!\is_subclass_of($className, KernelTestCase::class)) {
Configuration::boot(UnitTestConfig::build());

return;
}

// integration test
Configuration::boot(static function() use ($className): Configuration {
if (!KernelTestCaseHelper::getContainerForTestClass($className)->has('.zenstruck_foundry.configuration')) {
throw new \LogicException('ZenstruckFoundryBundle is not enabled. Ensure it is added to your config/bundles.php.');
}

return KernelTestCaseHelper::getContainerForTestClass($className)->get('.zenstruck_foundry.configuration'); // @phpstan-ignore return.type
});
}
}
3 changes: 0 additions & 3 deletions src/PHPUnit/BuildStoryOnTestPrepared.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@
use PHPUnit\Event;
use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase;
use Zenstruck\Foundry\Attribute\WithStory;
use Zenstruck\Foundry\Exception\FactoriesTraitNotUsed;

/**
* @internal
Expand Down Expand Up @@ -47,8 +46,6 @@ public function notify(Event\Test\Prepared $event): void
throw new \InvalidArgumentException(\sprintf('The test class "%s" must extend "%s" to use the "%s" attribute.', $test->className(), KernelTestCase::class, WithStory::class));
}

FactoriesTraitNotUsed::throwIfClassDoesNotHaveFactoriesTrait($test->className());

foreach ($withStoryAttributes as $withStoryAttribute) {
$withStoryAttribute->newInstance()->story::load();
}
Expand Down
Loading