Laravel Zero — это микро-фреймворк для консольных приложений на базе Laravel Framework, позволяющий легко и быстро разрабатывать функционал работающий без веба. Но инициатором этой статьи стал кейс и несколько часов потраченного времени.
Вводная
При разработке интерактивного консольного приложения на базе Laravel Zero, я решил использовать Laravel Prompts в качестве гибкого, лёгкого и красивого взаимодействия с пользователем. И, пока разработка велась под Windows, проблем не было никаких и внезапное осознание того, что под Windows всё работает, а под Linux — нет, от части привело меня в ступор…
Тестирование
Итак, всё по порядку. Допустим, в приложении имеется консольная команда с таким кодом:
use Illuminate\Console\Command; use function Laravel\Prompts\text; class FooCommand extends Command { protected $signature = 'foo'; protected $description = 'Command description'; public function handle(): void { $first = text('First question'); $second = text('Second question'); $this->info('First is ' . $first); $this->info('Second is ' . $second); } }
Также имеем Pest тест:
use App\Commands\FooCommand; it('some', fn() => test()->artisan(FooCommand::class) ->expectsQuestion('First question', 'qwerty') ->expectsQuestion('Second question', 'wasd') ->expectsOutputToContain('First is qwerty') ->expectsOutputToContain('Second is wasd') ->assertSuccessful() );
При запуске теста под Windows проблем с ним никаких не будет:
$ vendor/bin/pest --filter FooTest PASS Tests\Feature\FooTest ✓ it some 0.34s Tests: 1 passed (10 assertions) Duration: 0.51s
НО стоит запустить его в WSL (Ubuntu), линуксе или любом месте, что не является Windows, то сразу получаем ошибку:
$ vendor/bin/pest --filter FooTest FAILED Tests\Feature\FooTest > it some AssertionFailedError Question "First question" was not asked. at vendor/illuminate/testing/PendingCommand.php:370 366▕ */ 367▕ protected function verifyExpectations() 368▕ { 369▕ if (count($this->test->expectedQuestions)) { ➜ 370▕ $this->test->fail('Question "'.Arr::first($this->test->expectedQuestions)[0].'" was not asked.'); 371▕ } 372▕ 373▕ if (count($this->test->expectedChoices) > 0) { 374▕ foreach ($this->test->expectedChoices as $question => $answers) { +3 vendor frames 4 tests/Feature/FooTest.php:13
Это значит, что консоль либо не может, либо даже не пытается ввести данные.
Исследование
На странице документации Prompts есть раздел где сказано, что из-за особенностей Windows, а также некоторых окружений, нужно явно использовать fallback значения.
Начиная с Laravel Framework 10.17, библиотека Laravel Prompts поставляется «в коробке», а значит явно должна этой «коробкой» использоваться. И мы не ошиблись! В коде консольных команд присутствует трейт ConfiguresPrompts с реализацией нужных fallback значений. Это нам на руку, так как не придётся изобретать велосипед.
Но вопрос в ошибке тестирования остаётся открытым. Изучая код, на четвёртой же его строчке видим функцию активации этих fallback значений:
Prompt::fallbackWhen(windows_os() || $this->laravel->runningUnitTests());
И становится понятно почему под Windows всё работает, а в остальных случаях нет. Вызов dd($this->laravel->runningUnitTests())
возвращающий false
подтверждает догадки.
А ларчик просто открывался…
Метод runningUnitTests
достаточно прост и он проверяет имя окружения под которым запущена команда:
public function runningUnitTests() { return $this->bound('env') && $this['env'] === 'testing'; }
Добавив над оператором возврата строчку dd($this['env'])
внезапно получаем development
. И он выглядит очень знакомым…
Где в Laravel приложениях задаётся имя окружения при тестировании? Правильно! в phpunit.xml
файле. Открываем файл и что видим? А ничего мы не видим! Окружение-то не задаётся вовсе так как оно нам не нужно. Куда нужно идти в этом случае? Верно! В config/app.php
и видим…
return [ // ... 'env' => 'development', // ... ];
Решение
Теперь настройки окружения нам нужны, но не полностью. Таким образом, в файл phpunit.xml
добавляем строчки:
<php> <env name="APP_ENV" value="testing" /> </php>
Затем в знакомом файле config/app.php
меняем значение на:
-'env' => 'development', +'env' => env('APP_ENV', 'production'),
Запускаем тесты и наслаждаемся результатом:
$ vendor/bin/pest --parallel ................................. Tests: 33 passed (108 assertions) Duration: 2.69s Parallel: 16 processes
Всё.
ссылка на оригинал статьи https://habr.com/ru/articles/892010/
Добавить комментарий