Besoin d'un expert pour vous aider dans votre projet de développement Symfony ou PHP ? Demandez-nous un devis dès maintenant


Boostez vos tests Symfony avec Zenstruck Foundry

· Silas Joisten · Temps de lecture: 3 minutes
Toy factory production line

Zenstruck Foundry a révolutionné notre manière d’écrire des tests dans Symfony. Dans cet article, vous apprendrez comment des fabriques expressives, des données de test isolées et une expérience développeur plus fluide nous ont permis d’optimiser nos flux de tests et d’améliorer la productivité.

Qu’est-ce que Zenstruck Foundry ?

Zenstruck Foundry est une bibliothèque très utile conçue pour simplifier la création de données de test dans les applications Symfony. Au cœur de Foundry, on retrouve des factories expressives et auto-complétées pour les entités Doctrine, permettant aux développeurs de générer rapidement des données avec un minimum de code répétitif (boilerplate).

Avec le support de Faker, une intégration complète avec Doctrine ORM/ODM, et des fonctionnalités comme les stories, Foundry améliore considérablement la productivité des développeurs et la fiabilité des tests.

Créer une factory pour une entité Doctrine

Imaginons que nous ayons une entité User :

namespace App\Entity;

use Doctrine\ORM\Mapping as ORM;

#[ORM\Entity]
class User
{
    #[ORM\Id]
    #[ORM\GeneratedValue]
    #[ORM\Column(type: 'integer')]
    private ?int $id = null;

    #[ORM\Column(type: 'string')]
    private string $email;

    #[ORM\Column(type: 'string')]
    private string $name;
}

On peut alors générer une factory pour cette entité :

bin/console make:factory App\\Entity\\User

Cette commande crée la classe UserFactory suivante :

// src/Factory/UserFactory.php
namespace App\Factory;

use App\Entity\User;
use Zenstruck\Foundry\Persistence\PersistentObjectFactory;
use Zenstruck\Foundry\Proxy;

/**
 * @extends PersistentObjectFactory<User>
 */
final class UserFactory extends PersistentObjectFactory
{
    protected function defaults(): array
    {
        return [
            'email' => self::faker()->email(),
            'name' => self::faker()->name(),
        ];
    }

    protected static function class(): string
    {
        return User::class;
    }
}

Utiliser les factories dans les tests

Une fois la factory créée, vous pouvez l’utiliser dans vos tests pour générer des utilisateurs :

public function testGetEmail(): void
{
    $user = UserFactory::createOne([
        'email' => $expected = 'john@doe.com'
    ]);

    self::assertSame($expected, $user->getEmail());
}

Et si vous avez besoin de plusieurs utilisateurs, vous pouvez en créer de cette façon :

$users = UserFactory::createMany(5);

Une introduction aux Stories

Les stories sont un excellent moyen de définir des scénarios de données réutilisables. Par exemple, si vous souhaitez qu’un utilisateur administrateur existe toujours par défaut, vous pouvez le définir dans une story :

// src/Story/DefaultUsersStory.php
namespace App\Story;

use App\Factory\UserFactory;
use Zenstruck\Foundry\Story;

final class DefaultUsersStory extends Story
{
    public function build(): void
    {
        UserFactory::createOne([
            'email' => 'admin@example.com',
            'name' => 'Administrator',
        ]);
    }
}

Vous pouvez ensuite charger cette story avec les fixtures Doctrine :

bin/console doctrine:fixtures:load

Assurez-vous que le Foundry loader est bien enregistré dans la configuration de FoundryBundle si nécessaire.

Factories intégrées

Foundry propose également des factories spécialisées pour des cas d’usage avancés :

  • ArrayFactory : pour générer des tableaux de données (par exemple pour simuler des réponses API).

  • ObjectFactory : pour créer des objets sans les persister.

  • PersistentProxyObjectFactory : utile lorsque vous souhaitez que les objets soient immédiatement persistés en base et accessibles via un Proxy.

Tester des Value Objects et des Agrégats en DDD

L’une des grandes forces de Zenstruck Foundry est sa capacité à gérer des modèles de domaine complexes, y compris les Value Objects et Agrégats dans le cadre du Domain-Driven Design (DDD). Foundry facilite la création des entités et de leurs objets de valeur associés, ce qui en fait un excellent choix pour tester des architectures DDD sophistiquées.

Découvrez les bases du Domain-Driven Design dans mon blog post précédent

Par exemple, imaginons que vous souhaitiez tester un Value Object comme Price. Grâce aux factories de Foundry, vous pouvez rapidement injecter des données réalistes dans vos objets métier.

final readonly class Price
{
    public function __construct(
        public int $amount,
        public string $currency,
    ) {
    }
}
use Zenstruck\Foundry\Object\Instantiator\ObjectFactory;

final class PriceFactory extends ObjectFactory
{
    protected function defaults(): array
    {
        return [
            'amount' => self::faker()->numberBetween(100, 1000),
            'currency' => self::faker()->randomElement(['€', '$']),
        ];
    }

    protected static function getClass(): string
    {
        return Price::class;
    }
}

Cela vous permet ainsi de tester le comportement des agrégats en DDD sans vous soucier de la complexité liée à la création ou la gestion des données sous-jacentes. Foundry vous aide à simuler des modèles métiers réalistes pour garantir des interactions cohérentes entre agrégats et objets de valeur.

Conclusion

Zenstruck Foundry est devenu un outil incontournable dans notre stack Symfony. Il réduit la répétition dans le code, améliore la fiabilité des tests et booste la productivité. Les stories pour les scénarios réutilisables et les factories avancées pour des besoins complexes en font un excellent atout pour n'importe quel projet Symfony.

En plus, sa compatibilité avec les principes du DDD permet de tester facilement des Value Objects et des Aggregates, ce qui en fait un très bon choix choix pour des projets avec des modèles de domaine complexes.

Démarrez avec Foundry

Transformez votre flux de travail de test Symfony dès aujourd’hui avec Foundry. Générez facilement des données de test, automatisez les tâches répétitives et assurez-vous de compter sur des tests plus fiables.

Image