"Si un ouvrier veut bien faire son travail, il doit d'abord affûter ses outils." - Confucius, "Les Entretiens de Confucius. Lu Linggong"
Page de garde > La programmation > Concentrer vos tests sur le domaine. Un exemple PHPUnit

Concentrer vos tests sur le domaine. Un exemple PHPUnit

Publié le 2024-11-03
Parcourir:327

Introduction

Souvent, les développeurs essaient de tester 100 % (ou presque 100 %) de leur code. Apparemment, c'est l'objectif que chaque équipe devrait atteindre pour ses projets mais, de mon point de vue, une seule partie de l'ensemble du code devrait être entièrement testée : votre domaine.

Le domaine est, essentiellement, la partie de votre code qui définit ce que fait réellement le projet. Par exemple, lorsque vous conservez une entité dans la base de données, votre domaine n'est pas chargé de la conserver dans la base de données, mais de s'assurer que les données conservées ont un sens selon votre modèle économique. Il est possible que lorsque vous enregistrez vos données dans la base de données, vous utilisiez une bibliothèque externe comme PHP Doctrine. Cette bibliothèque est déjà entièrement testée, il n'est pas nécessaire de tester ce qu'elle fait. Si vous transmettez à Doctrine les données correctes, elles seront enregistrées dans la base de données sans problème.

L'exemple présenté dans les sections suivantes n'essaie pas de montrer comment fonctionne le Domain Driven Design, il existe de nombreux articles qui l'expliquent très bien. Je vais essayer de montrer comment avoir votre domaine bien défini et découplé peut vous aider à tester facilement et en vous concentrant sur ce que fait votre application.

L'exemple est construit sur un environnement Symfony et en utilisant la bibliothèque PHPUnit, mais l'idée est valable pour n'importe quel langage ou framework.

Le code à tester

Imaginons que notre application se connecte à une API externe qui renvoie des données sur la probabilité de pluie pour une date spécifiée. Les données renvoyées ressemblent à ceci :


{
   "date" : "2022-12-01",
   "rain_probability" : 0.75
}


Maintenant, nous devons prendre ces données et les classer selon cette cartographie :

  • probabilité_pluie FAIBLE
  • probabilité_pluie ≥ 0,40 && probabilité_pluie MOYEN
  • probabilité_pluie ≥ 0,75 : ÉLEVÉ

et enregistrez le résultat sur une table de base de données décrite par l'entité suivante :


#[ORM\Entity(repositoryClass: RainMeasure::class)]
class RainMeasure {

    #[ORM\Column]
    private string $date;

    #[ORM\Column]
    private float $probability;

    #[ORM\Column(length: 10)]
    private string $label;

    // Getters and setters
    // .......
}


Créons un gestionnaire qui récupère les données de l'API externe, définit l'étiquette en fonction de la probabilité de pluie et l'enregistre dans la base de données.


class RainMeassureHandler {
    private EntityManagerInterface $em;

    public function __construct(EntityManagerInterface $em)
    {
        $this->em = $em;
    }

    public function saveMeasure(array $measureData): void
    {
        if($measureData['rain_probability'] = 0.40 && $measureData['rain_probability'] setDate($measureData['date']);
        $rainMeasure->setProbability($measureData['rain_probability']);
        $rainMeasure->setLabel($label);

        $this->em->persist($rainMeasure);
        $this->em->flush();
    }
}


Si nous essayons de créer un test pour le gestionnaire ci-dessus, nous constaterons que nous devrons injecter l'EntityManagerInterface puisque le comportement que nous voulons tester (définir une étiquette en fonction de la valeur de probabilité) est couplé dans le même gestionnaire qui enregistre le résultat dans la base de données. Nous pourrions essayer de charger EntityManagerInterface en utilisant des simulations et des stubs mais est-ce nécessaire ?. Évidemment non. Comme dit précédemment, nous devrions essayer de nous concentrer sur le test du comportement qui appartient à notre domaine, c'est-à-dire obtenir la bonne étiquette en fonction de la probabilité de pluie.

Comportement de découplage que nous voulons tester

Afin de simplifier notre test, nous allons déplacer le comportement que nous souhaitons tester vers une autre classe :


class RainMeasureLabelHandler 
{
    public function getLabelFromProbability(float $prob): string
    {
        if($prob = 0.40 && $prob 

Et maintenant, notre RainMeassureHandler ressemblera à ceci :


class RainMeasureHandler 
{
    private EntityManagerInterface $em;

    public function __construct(EntityManagerInterface $em)
    {
        $this->em = $em;
    }

    public function saveMeasure(array $measureData): void
    {
        $rainMeasureLabelHandler = new RainMeasureLabelHandler();
        $label = $rainMeasureLabelHandler->getLabelFromProbability($measureData['rain_probability']);

        $rainMeasure = new RainMeasure();
        $rainMeasure->setDate($measureData['date']);
        $rainMeasure->setProbability($measureData['rain_probability']);
        $rainMeasure->setLabel($label);

        $this->em->persist($rainMeasure);
        $this->em->flush();
    }
}


Nous pouvons maintenant nous concentrer sur le test de notre RainMeasureLabelHandler qui ferait partie de notre domaine et n'aurait aucune dépendance vis-à-vis des couches externes. Le tester serait aussi simple que indiqué :

Focusing your tests on the domain. A PHPUnit example

Conclusion

Je voudrais dire que d'autres types de tests seraient également utiles. Peut-être avons-nous une API et souhaitons-nous tester les entrées et les sorties avec un environnement de test qui comprend une base de données et d'autres ressources dont nous pourrions avoir besoin. Mais n'oubliez pas de faire découpler votre domaine et de le tester entièrement.

Déclaration de sortie Cet article est reproduit sur : https://dev.to/icolomina/focusing-your-tests-on-the-domain-a-phpunit-example-c82?1 En cas de violation, veuillez contacter [email protected] pour le supprimer
Dernier tutoriel Plus>

Clause de non-responsabilité: Toutes les ressources fournies proviennent en partie d'Internet. En cas de violation de vos droits d'auteur ou d'autres droits et intérêts, veuillez expliquer les raisons détaillées et fournir une preuve du droit d'auteur ou des droits et intérêts, puis l'envoyer à l'adresse e-mail : [email protected]. Nous nous en occuperons pour vous dans les plus brefs délais.

Copyright© 2022 湘ICP备2022001581号-3