Frame 130.jpg

Поговорим про грабли велосипедостроения, с которыми я уже познакомился при написании нового фреймворка тестирования Testo.

PHPUnit предоставляет множество вариантов одних и тех же проверок (утверждений) в тестах:

self::assertTrue(...);
$this->assertTrue(...);
assertTrue(...);

Все эти вызовы ведут в одно место — в фасад Assert на ~2300 строк.

<aside> 🤔

Но знаете ли вы, что в PHPUnit нет ни отдельной функции expectException(), ни одноимённого метода в фасаде Assert? В коде теста можно написать только $this->expectException().

</aside>

Это потому, что в PHPUnit тесты наследуются от TestCase (~2400 строк, расширяет Assert), в котором хранится и обрабатывается всё состояние теста. Мне это напоминает архитектуру Symfony Console, хуже которой я пока не встречал.

Как связаны состояние теста и проверка assertException? Дело в том, что проверка expect (ожидание) немного отличается от assert (утверждения) по семантике и механике:

В Testo другая политика.

С позиции Testo, тестовый класс — это владение разработчика, а не фреймворка. Вся метаинформация и оперативные данные, нужные фреймворку, хранится и обрабатывается в стороне.

Поэтому тестовым классам не нужно наследоваться от TestCase. В Testo тест-кейс не запускает сам себя и даже не знает своё имя в тестовой среде. Это позволяет писать более чистый код, и мы можем использовать конструктор как угодно.

Тестами могут быть даже обычные пользовательские функции!

#[Test]
function simpleTest(): void
{
    // test something
}