Написание модульных тестов с помощью PHPUnit, часть 1: настройка
Ранее в этом месяце мы начали рассматривать установку PHPUnit в Visual Studio Code с конечной целью научиться писать модульные тесты для наших проектов на основе WordPress.
С этой целью в этом сообщении предполагается, что вы прочитали следующие сообщения, и предполагается, что вы ознакомились с несколькими предыдущими сообщениями:
- Среда разработки WordPress (с использованием диспетчера пакетов)
- IDE для разработки WordPress
- Работа с пользовательскими настройками в Visual Studio Code
И, конечно же, установка PHPUnit в Visual Studio Code, как указано выше. Как только это будет сделано, мы будем готовы продолжить. Но следует иметь в виду, что это будет традиционный или всеобъемлющий курс по написанию модульных тестов.
Вместо этого все дело в написании модульных тестов для проектов WordPress.
Модульные тесты с PHPUnit, часть 1: настройка
Прежде чем углубиться в это, я хочу прояснить, что это не столько пост о разработке через тестирование, сколько пост, который закладывает основу для понимания написания модульных тестов. И затем, в конце концов, мы будем работать над написанием модульных тестов для нашего кода.
Те из вас, кто ранее читал о модульном тестировании, знают, что написание модульных тестов — это тема, по которой имеется много информации, и в этой статье мы не будем пытаться охватить все это. Вместо этого будет использоваться более прагматичный подход к написанию модульных тестов для плагинов на основе WordPress, веб-приложений и тому подобного.
1 Написание модульных тестов
Всякий раз, когда вы впервые приступите к написанию модульных тестов, вам будут представлены как методы setUp, так и методы tearDown. Это распространено в PHPUnit (как и в других средах тестирования). Есть несколько особенностей этих двух конкретных методов, которые часто вызывают проблемы.
Короче говоря, люди относятся к таким функциям следующим образом:
- setUp подобен конструктору, в котором вы создаете экземпляр своего класса, а затем подготавливаете все необходимое для теста, включая тестируемый объект, необходимые данные и так далее.
- tearDown — это деструктор, в котором вы сбрасываете все, а затем избавляетесь от своих объектов. Обычно это чаще встречается в скомпилированных языках, но и в PHPUnit его нельзя упускать.
И хотя я вполне могу это понять, это не всегда так. Я говорю из опыта здесь тоже. Наоборот, именно отсюда происходит фактическое модульное тестирование фраз. Все дело в тестировании кода юнитов и в чистом и лаконичном виде.
Так для чего вообще нужны эти методы? Это может быть особенно сложной привычкой или даже концептуальной моделью, когда вы только начинаете процесс. С этой целью я хочу изучить цель каждого метода, а затем, как подойти к этому при работе с проектами на основе WordPress.
И, как обычно, я постараюсь сделать это максимально простым и прагматичным. Меня гораздо меньше интересует теория, стоящая за некоторыми вещами, чем то, как она может хорошо служить как моему бизнесу, так и моим проектам. (Конечно, это не обесценивание теории, но сейчас не место для этого, и этот блог не для этого.)
2 Функция настройки
Несмотря на то, что я начинаю с краткого обсуждения метода setUp, важно помнить, что его родственная функция (как некоторые считают) нужна не всегда.
Например, если вы пишете код, в котором все, что вы делаете, — это создание экземпляра объекта или набора объектов, то метод tearDown может не понадобиться. Подробнее об этом я расскажу в следующем разделе.
С учетом сказанного предположим, что у вас есть класс, отвечающий за выполнение некоторой логики предметной области. Помните, что для целей этого поста нас не интересует код, который будет делать то, что WordPress делает естественным образом, и который уже имеет свой собственный набор тестов.
Под этим я подразумеваю, что нас интересует код, который работает именно в проблемной области. Например, возможно, нас интересует написание класса, кэширующего данные в базе данных. Одна из частей информации, которая отвечает за кэширование информации, — это то, как долго данные должны храниться в кэше. Таким образом, кандидат на модульное тестирование будет использовать то, что мы можем устанавливать и изменять количество времени, верно?
Конечно, возможно, эти данные жестко запрограммированы, но для примера предположим обратное. Это подразумевает следующее:
- У нас есть класс, который служит нашим кешем,
- Класс поддерживает часть данных экземпляра о том, как долго должен быть установлен кеш,
- Время кеша можно задать из сторонних классов,
- Время кеша можно прочитать из сторонних классов.
Это означает, что модульный тест будет включать:
- Настройка класса,
- Определение значения,
- Утверждая, что значение, которое было определено, соответствует ожидаемому,
- Изменение значения,
- Утверждение измененного значения было обновлено.
Таким образом, базовый класс может выглядеть примерно так (вся документация исключена из класса, чтобы сделать код максимально кратким):
<?php
class AcmeCache
{
private $duration;
public function __construct()
{
$this->duration = 43200;
}
public function setDuration($duration)
{
$this->duration = $duration;
}
public function getDuration()
{
return $this->duration;
}
// More cache code omitted...
}
Обратите внимание, что по умолчанию время кэширования установлено на 12 часов (в секундах). Класс также поддерживает возможность как изменения, так и чтения длительности.
Это означает, что мы можем написать тесты, которые проверяют:
- если начальное значение соответствует ожидаемому,
- если новое значение соответствует ожидаемому (и что оно перезаписывает начальное значение)
<?php
use PHPUnitFrameworkTestCase;
class AcmeCacheTest extends TestCase
{
protected $cache;
protected function setUp()
{
$this->cache = new AcmeCache();
}
public function testDefaultDuration()
{
$this->assertTrue($this->cache->getDuration() === 43200);
}
public function testNewDuration()
{
$this->cache->setDuration(1000);
$this->assertFalse($this->cache->getDuration() === 43200);
$this->assertTrue($this->cache->getDuration() === 1000);
}
// More to come...
}
Одна из вещей, которые я хотел бы отметить в приведенном выше коде, заключается в том, что вы можете прочитать, что каждый тест должен иметь одно утверждение, тогда как testNewDuration явно имеет два утверждения.
Я склонен принимать идею одного утверждения на тест как эмпирическое правило. Например, в данном случае я хочу утверждать, что исходное значение перезаписывается или нигде не сохраняется, а сохраняется новое значение.
Однако это может быть не всегда так, поэтому вам, возможно, придется относиться к таким ситуациям с осторожностью.
Как видите, это не имеет ничего общего с WordPress; однако это связано с логикой тестирования, относящейся конкретно к рассматриваемой области. А именно продолжительность кэша. И в этом суть модульного тестирования: тестирование логического поведения модулей кода, чтобы убедиться, что все работает так, как ожидалось.
И в зависимости от того, когда вы пишете этот код, у вас могут быть неудачные тесты. В конечном итоге это может помочь при разработке классов, но это уже другая тема, а не часть этой статьи.
Запуск тестов
После того как тесты написаны, важно иметь возможность выполнить их, чтобы увидеть, проходят ли они, если нет, что проходит, а что нет. Но мы еще не закончили. Я хочу дать всесторонний взгляд на модульное тестирование в контексте WordPress, и это связано с обсуждением того, что WordPress предоставляет, а чего нет, некоторых заблуждений и того, как запускать эти тесты в терминале или в Visual Studio Code.
В следующем посте этой серии мы рассмотрим функцию tearDown и то, как (и когда) ее использовать, когда она нужна, а когда нет, а затем мы немного рассмотрим модуль тестирование в WordPress в целом.
В конечном счете, мы работаем над тем, чтобы получить полное представление о том, как это сделать и как сделать это правильно. Но важно заложить основу для этого, и сделать это на нескольких постах проще, чем на одном монолитном посте.
Итак, изучение tearDown(), его использования и того, как выполнять тесты из командной строки, станет темой следующего поста в этой серии.

