Группировка тестов через #[Group]
На прошлой неделе я писал новый компонент для Cycle ORM — cycle/transaction. Тесты к нему я, разумеется, писал на Testo — и сразу захотел воспроизвести привычный по Cycle подход: гонять один и тот же набор тестов по всем поддерживаемым базам данных. Тут-то и выяснилось, что одной нужной детали в Testo пока нет.
Как принято писать тесты в Cycle
Тесты Cycle написаны на PHPUnit. Для тестов, которые работают с реальными базами данных, там сложилась удобная практика:
Пишется абстрактный класс с тестами;
Затем под каждый драйвер наследуются финальные классы, которые подключают конкретный драйвер.
На финальных классах проставляются группы:
php/** * @group driver * @group driver-mysql */Здесь
driverозначает, что тест работает с базой напрямую, аdriver-mysqlуже уточняет конкретный драйвер. Удобство очевидно: можно запустить тесты только на SQLite или на любом другом выбранном драйвере. Ровно так они и вызываются в CI — отдельным прогоном на каждую базу данных.
Группы в Testo
В Testo группировки тестов ещё не было. Так что пришло время это добавить. На всё про всё ушло несколько часов вместе с проверкой гипотез и финальной полировкой: функционал прекрасно вписался в плагин Filter.
Ещё на старте я заметил одну деталь: группу driver в моих тестах можно вынести в родительский класс, а не дублировать в каждом потомке. Поэтому наследование групп я добавил сразу.
Группы здесь — это строковые метки, которые вы навешиваете атрибутом #[Group]#[Group(string ...$names)]Помечает класс, метод или функцию одной или несколькими группами для выборочной фильтрации.. Тот же сценарий с абстрактным классом и драйверами теперь выглядит так:
#[Group('driver')]
abstract class TransactionTestCase
{
public function commitsTransaction(): void { /* ... */ }
}
#[Test]
#[Group('driver-mysql')]
final class MySqlTransactionTest extends TransactionTestCase {}
#[Test]
#[Group('driver-sqlite')]
final class SqliteTransactionTest extends TransactionTestCase {}Выбор групп при запуске задаётся флагом --group:
# Только тесты на SQLite
testo run --group=driver-sqlite
# Все тесты, работающие с базами напрямую
testo run --group=driver
# Всё, кроме медленных
testo run --group=!slowНеожиданный финал
Честно говоря, я счёл группировку тестов рядовой фичей и не придал ей особого значения, поэтому не стал писать отдельный пост. Но сегодня пошёл почитать фидбек с запуска беты, и наткнулся на то, что наследование групп просили ещё в PHPUnit с 2019 года. И не получили:
I am sorry to say this, but me this does not sound useful. Inherit groups from parent classes #3935
Забавно: именно эта фича пригодилась мне при первом же использовании атрибута #[Group]#[Group(string ...$names)]Помечает класс, метод или функцию одной или несколькими группами для выборочной фильтрации..
И вот я здесь, чтобы напомнить простую вещь: Testo ориентирован на потребности разработчика.
Если существующий инструмент не решает проблемы сообщества, появление нового — лишь вопрос времени. Так Testo и появился.
Несите свои идеи и потребности в Testo — там у них все шансы быть реализованными. Даже если вы не используете Testo, имейте в виду: фичи из Testo постепенно перетекают и в PHPUnit, просто с опозданием.
![Группировка тестов: атрибут #[Group]](/blog/filter-group/preview.png)