zenstruck / foundry

A model factory library for creating expressive, auto-completable, on-demand dev/test fixtures with Symfony and Doctrine.
https://symfony.com/bundles/ZenstruckFoundryBundle/current/index.html
MIT License
634 stars 69 forks source link

Behat Integration #235

Open kbond opened 2 years ago

kbond commented 2 years ago

Based on discussion in #234 and looking at https://github.com/dmaicher/doctrine-test-bundle/pull/128. I'm thinking we could provide 2 contexts/extensions (not sure what would be appropriate):

  1. ResetDatabaseContext/Extension: similar to the ResetDatabase PHPUnit trait
  2. FactoriesContext/Extension: similar to the Factories PHPUnit trait

@wouterj, wdyt?

wouterj commented 2 years ago

I would create only one extension, which can do either of this behavior based on configuration. That's more idiomatic Behat.

As said in https://github.com/zenstruck/foundry/issues/234#issuecomment-1006502314 , it might also be worth to investigate if not using the foundry bundles can work with Behat (and setting up Foundry in the Behat extension). Given Behat separates the tests from your application container, it doesn't make much sense to have foundry registered in the test env of the app.

kbond commented 2 years ago

Would that mean you couldn't use stories/factories with services injected or is there an avenue to support this?

mpdude commented 1 year ago

When using the https://github.com/FriendsOfBehat/SymfonyExtension Behat extension, your Behat context classes can be autowired in the Symfony container. A fresh instance of the container can be constructor-injected into context classes.

That being said, I think with a context class like the following is all you'd need (needs to be listed in behat.yml).

<?php

namespace Zenstruck\Foundry\Test\Behat;

use Behat\Behat\Context\Context;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Zenstruck\Foundry\ChainManagerRegistry;
use Zenstruck\Foundry\Factory;
use Zenstruck\Foundry\Test\LazyManagerRegistry;
use Zenstruck\Foundry\Test\TestState;

class FoundryContext implements Context
{
    private ContainerInterface $container;

    public function __construct(ContainerInterface $container)
    {
        $this->container = $container;
    }

    /**
     * @BeforeScenario
     */
    public function setUpFactories(): void
    {
        TestState::bootFromContainer($this->container);
        Factory::configuration()->setManagerRegistry(
            new LazyManagerRegistry(function (): ChainManagerRegistry {
                return TestState::initializeChainManagerRegistry($this->container);
            })
        );
    }

    /**
     * @AfterScenario
     */
    public function tearDownFactories(): void
    {
        TestState::shutdownFoundry();
    }
}

This code is almost 100% copied from Factories trait (https://github.com/zenstruck/foundry/blob/1.x/src/Test/Factories.php).

The only thing I am unsure about is why Factories performs a kernel shutdown... is that necessary?

kbond commented 1 year ago

Thanks, I think we should indeed add this context.

The only thing I am unsure about is why Factories performs a kernel shutdown... is that necessary?

This is required so the start of your test doesn't have the kernel booted (which causes an error if trying to create a client). I don't know this is an issue with Behat so we probably don't have to shutdown the kernel.

mpdude commented 1 year ago

The kernel passed into contexts by the aforementioned extension is already booted for reasons, so this should be fine.

Does it make sense to provide such a context in this repo here, since that might either introduce unwarranted Composer dependency declarations and/or leave us with no good rules in suggests or conflicts?

kbond commented 1 year ago

Does it make sense to provide such a context in this repo here

I think so, it would be a dev dep so as long as there are no conflicts, I'm fine adding here. What would be the requirement? Just friends-of-behat/symfony-extension?

kbond commented 1 year ago

Started a draft PR (#378). I'm going to need some help there...