Изначально я хотел написать общий пост о PHP генераторах, функции, появившейся в PHP 5.5.
Однако, поскольку я очень ленивый и мне все никак не удается придумать хорошие примеры использования генераторов, я решил сделать этот мини-пост, посвященный одному такому использованию.
Провайдеры данных в PHPUnit
Часто используемой функцией PHPUnit являются провайдеры данных. В провайдере данных вы задаете список списков аргументов, а методы тестирования, использующие провайдер данных, вызываются по одному разу для каждого списка аргументов.
Часто провайдеры данных создаются с переменной массива, в которую запихиваются списки аргументов. Пример (включая плохое именование):
/**
* @dataProvider provideUserInfo
*/
function testSomeStuff( string $userName, int $userAge ) {}
function provideUserInfo() {
$return = [];
$return[] = [ 'Such Name', 42 ];
$return[] = [ 'Very Name', 23 ];
$return['Named parameter set'] = [ 'So Name', 1337 ];
return $return;
}
Не очень приятная вещь здесь заключается в том, что у вас есть переменная (explicit state), и вы изменяете ее (mutable state).
Более функциональный подход — просто возвращать массив, содержащий непосредственно списки аргументов. Однако если создание списка аргументов сложнее, чем в данном примере, и требует наличия состояния, это может не сработать.
А когда такое состояние требуется, в итоге вы получаете еще большую сложность и большую вероятность того, что переменная $return
укусит вас.
Использование yield
Возможно, вы не в курсе, что провайдеры данных не обязательно должны возвращать массив. Они должны возвращать iterable
, поэтому они также могут возвращать Iterator
и, соответственно, Generator
. Это означает, что вы можете написать описанный выше провайдер данных следующим образом:
function provideUserInfo() {
yield [ 'Such Name', 42 ];
yield [ 'Very Name', 23 ];
yield 'Named parameter set' => [ 'So Name', 1337 ];
}
Явного состояния не видно!
Источник: Yield in PHPUnit data providers.
Источник: https://www.kobzarev.com/programming/yield-in-phpunit-data-providers/