Skip to content

feature: allow to use Factory::create() and factory service in data providers #648

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
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
1 change: 1 addition & 0 deletions .env
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,5 @@ DATABASE_URL="mysql://root:[email protected]:3307/foundry_test?serverVersion=5.7.42
MONGO_URL="mongodb://127.0.0.1:27018/dbName?compressors=disabled&gssapiServiceName=mongodb"
DATABASE_RESET_MODE="schema"
USE_DAMA_DOCTRINE_TEST_BUNDLE="0"
USE_FOUNDRY_PHPUNIT_EXTENSION="0"
PHPUNIT_VERSION="9"
25 changes: 23 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ on:

jobs:
tests:
name: P:${{ matrix.php }}, S:${{ matrix.symfony }}, D:${{ matrix.database }}, PU:${{ matrix.phpunit }}${{ matrix.deps == 'lowest' && ' (lowest)' || '' }}${{ matrix.use-dama == 1 && contains(matrix.database, 'sql') && ' (dama)' || '' }}${{ !contains(matrix.database, 'sql') && '' || matrix.use-migrate == 1 && ' (migrate)' || ' (schema)' }}
name: P:${{ matrix.php }}, S:${{ matrix.symfony }}, D:${{ matrix.database }}, PU:${{ matrix.phpunit }}${{ matrix.deps == 'lowest' && ' (lowest)' || '' }}${{ matrix.use-dama == 1 && contains(matrix.database, 'sql') && ' (dama)' || '' }}${{ !contains(matrix.database, 'sql') && '' || matrix.use-migrate == 1 && ' (migrate)' || ' (schema)' }}${{ matrix.use-phpunit-extension == 1 && ' (phpunit extension)' || '' }}
runs-on: ubuntu-latest
strategy:
fail-fast: false
Expand All @@ -19,6 +19,7 @@ jobs:
database: [ mysql, mongo ]
use-dama: [ 1 ]
use-migrate: [ 0 ]
use-phpunit-extension: [ 0 ]
phpunit: [ 9 ]
exclude:
- php: 8.1
Expand All @@ -32,74 +33,93 @@ jobs:
database: none
use-dama: 1
use-migrate: 0
use-phpunit-extension: 0
phpunit: 9
- php: 8.3
deps: highest
symfony: '*'
database: mysql|mongo
use-dama: 1
use-migrate: 0
use-phpunit-extension: 0
phpunit: 9
- php: 8.3
deps: highest
symfony: '*'
database: pgsql|mongo
use-dama: 1
use-migrate: 0
use-phpunit-extension: 0
phpunit: 9
- php: 8.3
deps: highest
symfony: '*'
database: pgsql
use-dama: 0
use-migrate: 0
use-phpunit-extension: 0
phpunit: 9
- php: 8.3
deps: highest
symfony: '*'
database: sqlite
use-dama: 0
use-migrate: 0
use-phpunit-extension: 0
phpunit: 9
- php: 8.3
deps: lowest
symfony: '*'
database: sqlite
use-dama: 0
use-migrate: 0
use-phpunit-extension: 0
phpunit: 9
- php: 8.3
deps: lowest
symfony: '*'
database: mysql
use-dama: 1
use-migrate: 0
use-phpunit-extension: 0
phpunit: 9
- php: 8.3
deps: highest
symfony: '*'
database: mysql
use-dama: 1
use-migrate: 1
use-phpunit-extension: 0
phpunit: 9
- php: 8.3
deps: highest
symfony: '*'
database: mysql|mongo
use-dama: 1
use-migrate: 0
use-phpunit-extension: 0
phpunit: 10
- php: 8.3
deps: highest
symfony: '*'
database: mysql|mongo
use-dama: 1
use-migrate: 0
use-phpunit-extension: 0
phpunit: 11
- php: 8.3
deps: highest
symfony: '*'
database: mysql|mongo
use-dama: 1
use-migrate: 0
use-phpunit-extension: 1
phpunit: 11
env:
DATABASE_URL: ${{ contains(matrix.database, 'mysql') && 'mysql://root:root@localhost:3306/foundry?serverVersion=5.7.42' || contains(matrix.database, 'pgsql') && 'postgresql://root:root@localhost:5432/foundry?serverVersion=15' || contains(matrix.database, 'sqlite') && 'sqlite:///%kernel.project_dir%/var/data.db' || '' }}
MONGO_URL: ${{ contains(matrix.database, 'mongo') && 'mongodb://127.0.0.1:27017/dbName?compressors=disabled&gssapiServiceName=mongodb' || '' }}
USE_DAMA_DOCTRINE_TEST_BUNDLE: ${{ matrix.use-dama == 1 && contains(matrix.database, 'sql') && 1 || 0 }}
USE_FOUNDRY_PHPUNIT_EXTENSION: ${{ matrix.use-phpunit-extension }}
PHPUNIT_VERSION: ${{ matrix.phpunit }}
services:
postgres:
Expand Down Expand Up @@ -155,7 +175,8 @@ jobs:
DATABASE_URL: postgresql://root:root@localhost:5432/foundry?serverVersion=15
MONGO_URL: mongodb://127.0.0.1:27017/dbName?compressors=disabled&gssapiServiceName=mongodb
USE_DAMA_DOCTRINE_TEST_BUNDLE: 1
PHPUNIT_VERSION: 9
USE_FOUNDRY_PHPUNIT_EXTENSION: 1
PHPUNIT_VERSION: 11
services:
mongo:
image: mongo:4
Expand Down
4 changes: 4 additions & 0 deletions phpstan.neon
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@ parameters:
- identifier: missingType.iterableValue
path: tests/

# We support both PHPUnit versions (this method changed in PHPUnit 10)
- message: '#Call to function method_exists\(\) with .* will always evaluate to false#'
path: src/Test/Factories.php

excludePaths:
- tests/Fixture/Maker/expected/can_create_factory_with_auto_activated_not_persisted_option.php
- tests/Fixture/Maker/expected/can_create_factory_interactively.php
Expand Down
52 changes: 24 additions & 28 deletions phpunit
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,7 @@ check_phpunit_version() {

REQUIRED_PHPUNIT_VERSION="${1?}"

if [[ "${INSTALLED_PHPUNIT_VERSION}" == *"dev"* ]] && [ "${REQUIRED_PHPUNIT_VERSION}" != "11.4" ]; then
echo 0;
elif [[ "${INSTALLED_PHPUNIT_VERSION}" == "${REQUIRED_PHPUNIT_VERSION}"* ]]; then
if [[ "${INSTALLED_PHPUNIT_VERSION}" == "${REQUIRED_PHPUNIT_VERSION}"* ]]; then
echo 1;
else
echo 0;
Expand All @@ -28,42 +26,34 @@ fi
### <<

### >> update PHPUnit if needed
if [[ " 9 10 11 11.4 " != *" ${PHPUNIT_VERSION-9} "* ]]; then
echo "❌ PHPUNIT_VERSION should be one of 9, 10, 11, 11.4";
if [[ " 9 10 11 " != *" ${PHPUNIT_VERSION-9} "* ]]; then
echo "❌ PHPUNIT_VERSION should be one of 9, 10, 11";
exit 1;
fi

SHOULD_UPDATE_PHPUNIT=$(check_phpunit_version "${PHPUNIT_VERSION}")

if [ "${SHOULD_UPDATE_PHPUNIT}" = "0" ]; then
echo "ℹ️ Upgrading PHPUnit to ${PHPUNIT_VERSION}"
if [ "${PHPUNIT_VERSION}" = "9" ]; then
composer update phpunit/phpunit:^9 -W --dev
else
if [ "${PHPUNIT_VERSION}" = "11.4" ]; then
composer update phpunit/phpunit:11.4.x-dev -W --dev
else
composer update "phpunit/phpunit:^${PHPUNIT_VERSION}" -W --dev
fi
fi
composer update "phpunit/phpunit:^${PHPUNIT_VERSION}" -W
fi
### <<

### >> guess extensions
EXTENSION=""
### >> actually execute PHPUnit with the right options
DAMA_EXTENSION="DAMA\DoctrineTestBundle\PHPUnit\PHPUnitExtension"
FOUNDRY_EXTENSION="Zenstruck\Foundry\PHPUnit\FoundryExtension"

if [ "${USE_DAMA_DOCTRINE_TEST_BUNDLE:-0}" = "1" ]; then
EXTENSION="DAMA\DoctrineTestBundle\PHPUnit\PHPUnitExtension"
if [ "${USE_FOUNDRY_PHPUNIT_EXTENSION:-0}" = "1" ] && [ "${PHPUNIT_VERSION}" != "11" ]; then
echo "❌ USE_FOUNDRY_PHPUNIT_EXTENSION could only be used with PHPUNIT_VERSION=11";
exit 1;
fi
### <<

### >> actually execute PHPUnit with the right options
case ${PHPUNIT_VERSION} in
"9")
if [ -z "${EXTENSION}" ]; then
vendor/bin/phpunit -c phpunit.xml.dist "$@"
if [ "${USE_DAMA_DOCTRINE_TEST_BUNDLE:-0}" = "1" ]; then
vendor/bin/phpunit -c phpunit.xml.dist --extensions "${DAMA_EXTENSION}" "$@"
else
vendor/bin/phpunit -c phpunit.xml.dist --extensions "${EXTENSION}" "$@"
vendor/bin/phpunit -c phpunit.xml.dist "$@"
fi
;;

Expand All @@ -72,12 +62,18 @@ case ${PHPUNIT_VERSION} in
vendor/bin/phpunit -c phpunit-10.xml.dist "$@"
;;

"11"|"11.4")
if [ -z "${EXTENSION}" ]; then
vendor/bin/phpunit -c phpunit-10.xml.dist "$@"
else
vendor/bin/phpunit -c phpunit-10.xml.dist --extension "${EXTENSION}" "$@"
"11")
PHPUNIT_EXEC="vendor/bin/phpunit -c phpunit-10.xml.dist $@"
if [ "${USE_DAMA_DOCTRINE_TEST_BUNDLE:-0}" = "1" ]; then
PHPUNIT_EXEC="${PHPUNIT_EXEC} --extension "${DAMA_EXTENSION}""
fi

if [ "${USE_FOUNDRY_PHPUNIT_EXTENSION:-0}" = "1" ]; then
PHPUNIT_EXEC="${PHPUNIT_EXEC} --extension "${FOUNDRY_EXTENSION}""
fi

echo $PHPUNIT_EXEC
$PHPUNIT_EXEC
;;
esac
### <<
2 changes: 1 addition & 1 deletion phpunit-10.xml.dist
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- https://phpunit.de/manual/current/en/appendixes.configuration.html -->
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/10.5/phpunit.xsd"
xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/11.4/phpunit.xsd"
bootstrap="tests/bootstrap.php"
colors="true"
failOnRisky="true"
Expand Down
2 changes: 1 addition & 1 deletion phpunit.xml.dist
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

<!-- https://phpunit.de/manual/current/en/appendixes.configuration.html -->
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="vendor/phpunit/phpunit/phpunit.xsd"
xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/9.6/phpunit.xsd"
bootstrap="tests/bootstrap.php"
colors="true"
failOnRisky="true"
Expand Down
18 changes: 17 additions & 1 deletion src/Configuration.php
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,11 @@ final class Configuration
*/
public $instantiator;

/**
* This property is only filled if the PHPUnit extension is used!
*/
private bool $bootedForDataProvider = false;

/** @var \Closure():self|self|null */
private static \Closure|self|null $instance = null;

Expand Down Expand Up @@ -69,10 +74,15 @@ public function assertPersistanceEnabled(): void
}
}

public function inADataProvider(): bool
{
return $this->bootedForDataProvider;
}

public static function instance(): self
{
if (!self::$instance) {
throw new FoundryNotBooted('Foundry is not yet booted. Ensure ZenstruckFoundryBundle is enabled. If in a test, ensure your TestCase has the Factories trait.');
throw new FoundryNotBooted();
}

return \is_callable(self::$instance) ? (self::$instance)() : self::$instance;
Expand All @@ -88,6 +98,12 @@ public static function boot(\Closure|self $configuration): void
self::$instance = $configuration;
}

public static function bootForDataProvider(\Closure|self $configuration): void
{
self::$instance = \is_callable($configuration) ? ($configuration)() : $configuration;
self::$instance->bootedForDataProvider = true;
}

public static function shutdown(): void
{
StoryRegistry::reset();
Expand Down
4 changes: 4 additions & 0 deletions src/Exception/FoundryNotBooted.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,8 @@
*/
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.');
}
}
30 changes: 30 additions & 0 deletions src/PHPUnit/BootFoundryOnDataProviderMethodCalled.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
<?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;

/**
* @internal
* @author Nicolas PHILIPPE <[email protected]>
*/
final class BootFoundryOnDataProviderMethodCalled implements Event\Test\DataProviderMethodCalledSubscriber
{
public function notify(Event\Test\DataProviderMethodCalled $event): void
{
if (method_exists($event->testMethod()->className(), '_bootForDataProvider')) {
call_user_func([$event->testMethod()->className(), '_bootForDataProvider']);
}
}
}
50 changes: 50 additions & 0 deletions src/PHPUnit/FoundryExtension.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
<?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\Metadata\Version\ConstraintRequirement;
use PHPUnit\Runner;
use PHPUnit\TextUI;
use Zenstruck\Foundry\Configuration;

/**
* @internal
* @author Nicolas PHILIPPE <[email protected]>
*/
final class FoundryExtension implements Runner\Extension\Extension
{
public const MIN_PHPUNIT_VERSION = '11.4';

public function bootstrap(
TextUI\Configuration\Configuration $configuration,
Runner\Extension\Facade $facade,
Runner\Extension\ParameterCollection $parameters,
): void {
if (!ConstraintRequirement::from(self::MIN_PHPUNIT_VERSION)->isSatisfiedBy(Runner\Version::id())) {
throw new \LogicException(
\sprintf('Your PHPUnit version (%s) is not compatible with the minimum version (%s) needed to use this extension.', Runner\Version::id(), self::MIN_PHPUNIT_VERSION)
);
}

// shutdown Foundry if for some reason it has been booted before
if (Configuration::isBooted()) {
Configuration::shutdown();
}

$facade->registerSubscribers(
new BootFoundryOnDataProviderMethodCalled(),
new ShutdownFoundryOnDataProviderMethodFinished(),
);
}
}
Loading
Loading