«Если рабочий хочет хорошо выполнять свою работу, он должен сначала заточить свои инструменты» — Конфуций, «Аналитики Конфуция. Лу Лингун»
титульная страница > программирование > Сосредоточение ваших тестов на предметной области. Пример PHPUnit

Сосредоточение ваших тестов на предметной области. Пример PHPUnit

Опубликовано 3 ноября 2024 г.
Просматривать:408

Введение

Многие разработчики пытаются протестировать 100% (или почти 100%) своего кода. По-видимому, это цель, которую каждая команда должна достичь в своих проектах, но, с моей точки зрения, полностью тестировать следует только одну часть всего кода: ваш домен.

По сути, домен — это часть вашего кода, которая определяет, что на самом деле делает проект. Например, когда вы сохраняете объект в базе данных, ваш домен не отвечает за его сохранение в базе данных, а следит за тем, чтобы сохраненные данные соответствовали вашей бизнес-модели. Возможно, при сохранении данных в базе данных вы будете использовать внешнюю библиотеку, например PHP Doctrine. Эта библиотека уже полностью протестирована, нет необходимости тестировать, что она делает. Если вы передадите в доктрину правильные данные, они будут сохранены в базе данных без проблем.

Пример, показанный в следующих разделах, не пытается показать, как работает предметно-ориентированный дизайн, существует множество статей, которые очень хорошо объясняют это. Я попытаюсь показать, как четкое определение и разделение вашего домена может помочь легко протестировать и сосредоточиться на том, что делает ваше приложение.

Пример построен в среде Symfony и с использованием библиотеки PHPUnit, но идея справедлива для любого языка или платформы.

Код для тестирования

Представим, что наше приложение подключается к внешнему API, который возвращает данные о вероятности дождя на указанную дату. Возвращенные данные выглядят следующим образом:


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


Теперь нам нужно взять эти данные и классифицировать их следующим образом:

  • rain_probability НИЗКИЙ
  • вероятность_дождя ≥ 0,40 && вероятность_дождя СРЕДНИЙ
  • вероятность_дождя ≥ 0,75: ВЫСОКИЙ

и сохраните результат в таблице базы данных, описанной следующим объектом:


#[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
    // .......
}


Давайте создадим обработчик, который получает внешние данные API, устанавливает метку в соответствии с вероятностью дождя и сохраняет ее в базе данных.


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();
    }
}


Если мы попытаемся создать тест для вышеуказанного обработчика, мы обнаружим, что нам нужно будет внедрить EntityManagerInterface, поскольку поведение, которое мы хотим протестировать (установка метки в соответствии со значением вероятности), является соединены в одном обработчике, который сохраняет результат в базу данных. Мы могли бы попытаться загрузить EntityManagerInterface с помощью макетов и заглушек, но нужно ли это? Очевидно, нет. Как было сказано ранее, мы должны попытаться сосредоточиться на тестировании поведения, которое принадлежит нашему домену, который получает правильную метку в зависимости от вероятности дождя.

Поведение разделения, которое мы хотим протестировать

Чтобы упростить наш тест, мы собираемся перенести поведение, которое хотим протестировать, в другой класс:


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

И теперь наш RainMeasureHandler будет выглядеть так:


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();
    }
}


Теперь мы можем сосредоточиться на тестировании нашего RainMeasureLabelHandler, который будет частью нашего домена и не будет зависеть от внешних слоев. Тестировать это будет так же просто, как показано:

Focusing your tests on the domain. A PHPUnit example

Заключение

Хотелось бы сказать, что и другие тесты будут полезны. Возможно, у нас есть API, и мы хотим протестировать ввод и вывод с помощью тестовой среды, которая включает базу данных и другие ресурсы, которые нам могут понадобиться. Но не забудьте отделить и полностью протестировать свой домен.

Заявление о выпуске Эта статья воспроизведена по адресу: https://dev.to/icolomina/focusing-your-tests-on-the-domain-a-phpunit-example-c82?1. В случае нарушения прав обращайтесь по адресу [email protected]. удалить его
Последний учебник Более>

Изучайте китайский

Отказ от ответственности: Все предоставленные ресурсы частично взяты из Интернета. В случае нарушения ваших авторских прав или других прав и интересов, пожалуйста, объясните подробные причины и предоставьте доказательства авторских прав или прав и интересов, а затем отправьте их по электронной почте: [email protected]. Мы сделаем это за вас как можно скорее.

Copyright© 2022 湘ICP备2022001581号-3