- Взаимное влияние тестов
- Условные конструкции в тесте
- Тест вне тестов
- Слишком сильная детализация
- Код с тестами писать дольше, чем код без тестов
Как и любой другой код, тесты можно писать по-разному, в том числе очень плохо. Помимо каких-то общих практик и стандартов кодирования, у тестов есть свои особенности, о которых надо знать. В этом уроке мы пройдемся по некоторым из них.
Взаимное влияние тестов
Одно из ключевых правил — тесты не должны влиять друг на друга. Это значит, что любой тест выполняется так, как будто других тестов не существует в природе.
Нарушить это правило очень просто. Один тест может создать файл, изменить переменную или записать что-то в базу. Если остальные тесты наткнутся на эти изменения, то они могут пойти не по плану:
- Упасть там, где не должны падать
- Успешно пройти там, где не должны проходить
Кроме этого, в такой ситуации вводится неопределенность. Такие тесты иногда могут падать без видимых причин. Например, когда тест запускают изолированно, то он работает, а когда вместе с остальными — падает:
<?php
class SomeTest extends TestCase
{
private $user;
public function testOne(): void
{
$this->user = ['name' => 'Vasya'];
}
public function testTwo(): void
{
// Здесь используется пользователь, которого создал другой тест
// Этот тест зависит от работы предыдущего теста
// Он не может работать без последовательного запуска обоих тестов
$this->user['name'] = 'Petya';
}
}
Особенно часто такая ситуация возникает в тестах, активно взаимодействующих с внешней средой — базой данных или файловой системой. Тестирование побочных эффектов имеет свои хитрости и рассматривается в курсе по продвинутому тестированию.
Условные конструкции в тесте
Перейдем к условным конструкциям:
<?php
class SomeTest extends TestCase
{
public function testSomething(): void
{
if (/* что-нибудь */) {
// Выполняем код одним способом
// Здесь может быть проверка
} else {
// Выполняем код другим способом
// Здесь может быть проверка
}
// Здесь может быть проверка
}
}
Фактически, любое ветвление внутри тестов — это несколько тестов в рамках одного теста. Надо от этого избавляться и никогда так не писать.
Тест вне тестов
Задача setUp
— готовить данные и среду для тестирования, а задача test
— вызывать тестируемый код и проводить проверки. Но иногда разработчики переусердствуют:
<?php
class SomeTest extends TestCase
{
private $result;
public setUp(): void
{
// Вызывается тестируемый код, что противоречит идее setUp
$this->result = sum(5, 9);
}
public function testSum(): void
{
$this->assertEquals(14, $this->result);
}
}
В этом примере тестируемый код вызывается в setUp
. Такой подход усложняет анализ тестов, потому что переворачивает все с ног на голову.
Слишком сильная детализация
Под влиянием голосов из интернета программисты стремятся максимально разносить код по файлам, модулям и функциям. То же самое наблюдается и в тестах. Вместо одного теста со всеми необходимыми проверками новички иногда создают по пять тестов, в каждом из которых ровно одна проверка:
<?php
class SomeTest extends TestCase
{
public function testAge(): void
{
$user = ['name' => 'Mark', 'age' => 28];
// Здесь код, добавляющий пользователя в базу данных
$this->assertEquals(28, $user['age']);
}
public function testName(): void
{
$user = ['name' => 'Mark', 'age' => 28];
// Здесь код, добавляющий пользователя в базу данных
$this->assertEquals('Mark', $user['name']);
}
}
Чаще всего, единственным результатом такого разделения будет слишком большой объем кода и сложный рефакторинг в будущем, когда кода станет по-настоящему много.
Код с тестами писать дольше, чем код без тестов
Это очень интересный вопрос, по которому можно понять, насколько хорошо программист пишет тесты. Некоторые виды тестирования действительно сложны и требуют дополнительного времени, но ежедневные тесты, которые пишутся вместе с кодом, должны приводить к ускорению разработки. И на это есть пять причин:
- Тесты влияют на дизайн кода, помогая раньше выявлять неудачные решения
- Тесты упрощают подготовку входных данных, ведь с ними она проводится всего один раз
- Тесты упрощают проверку кода — они сами проверяют все, включая пограничные случаи
- Тесты позволяют реже проверять код вручную, что ускоряет рефакторинг
- Тесты снижают уровень стресса
Дополнительные материалы
Остались вопросы? Задайте их в разделе «Обсуждение»
Вам ответят команда поддержки Хекслета или другие студенты
- Статья «Как учиться и справляться с негативными мыслями»
- Статья «Ловушки обучения»
- Статья «Сложные простые задачи по программированию»
- Вебинар «Как самостоятельно учиться»
Для полного доступа к курсу нужен базовый план
Базовый план откроет полный доступ ко всем курсам, упражнениям и урокам Хекслета, проектам и пожизненный доступ к теории пройденных уроков. Подписку можно отменить в любой момент.