PHPUnit и тестирование заголовков

hell0w0rd

Продвинутый новичок
Если у тебя есть Response, который ты почему-то называешь Layout, тебе нужно один раз протестить то, что при вызове setStatusCode он устанавливает код ответа, при вызове setContentType устанавливает тип контента и так далее. Далее нужно проверять только то, что дергается setStatusCode с аргументом 404, на пример.
Или что JsonResponse дергает setContentType с 'application/json' и так далее.
 

grigori

( ͡° ͜ʖ ͡°)
Команда форума
в в принципе, откуда в приложении ставить код и заголовки ответа? из контроллера или из layout? второе кажется правильнее
неважно - header() или $response->setStatusCode();
 

hell0w0rd

Продвинутый новичок
PHP:
return new Response('Foo', 404);
Проверяй.
PHP:
  public function __construct($content = '', $status = 200, $headers = array())
    {
        $this->headers = new ResponseHeaderBag($headers);
        $this->setContent($content);
        $this->setStatusCode($status);
        $this->setProtocolVersion('1.0');
        if (!$this->headers->has('Date')) {
            $this->setDate(new \DateTime(null, new \DateTimeZone('UTC')));
        }
    }
Ну и проверю.
Мы тестируем не абстрактное нечто, а код, который написали. Не надо тестить ради тестов.
 

grigori

( ͡° ͜ʖ ͡°)
Команда форума
зря так ржете.
у ТС ситуация любого проекта с legacy, у меня то же самое - проекту хрен знает сколько лет, в наследство получена кучка дерьма, работаю как сапер, переписать все заново - надо много месяцев, нам это не разрешают по стратегическим причинам, надо обернуть тестами. что проверять? коды ответа, конечно

Мы тестируем не абстрактное нечто, а код, который написали
это ваш частный случай, а бывает, что тестировать надо именно абстрактное нечто
 
Последнее редактирование:

hell0w0rd

Продвинутый новичок
зря так ржете.
у ТС ситуация любого проекта с legacy, у меня то же самое - проекту хрен знает сколько лет, в наследство получена кучка дерьма, работаю как сапер, переписать все заново - надо много месяцев, нам это не разрешают, надо обернуть тестами. что проверять? коды ответа, конечно
какие коды ответа? Ну вызывается header просто так - пройдись find and replace и замени на foo_set_header, который можно мокнуть и протестить.
И да, я к тому что эту задачу можно решить как юнит-тестами так и функциональными.
 

hell0w0rd

Продвинутый новичок
Что конкретно протестить? В обертке ты можешь многое, например if(headers_sent()) {} и дальше что угодно, хочешь - исключение, хочешь - пропускать. Ошибки в принципе не будет, будет то, что ты решил.
 

Вурдалак

Продвинутый новичок
Мы тестируем не абстрактное нечто, а код, который написали. Не надо тестить ради тестов.
Нет, ты не проверишь. Ты собрался мокать то, что создается где-то внутри:
Реально, чего тут до сих пор обсуждается? Сделал мок Response и вперед.
Да и потом, тестировать именно вызов setter'а — это не то, что мы хотим тестировать. Если я заменю в конструкторе setter на прямое присваивание property, то тест не должен сломаться.
 

AmdY

Пью пиво
Команда форума
Да что вы выдумываете очередную кабаеву, если нравится через жопу и выплёвываются заголовки или контент сразу в потом, то тестируйте в другом потоке, запрашивая по http через guzzle, codeception.....
 

hell0w0rd

Продвинутый новичок
Вурдалак, с одной стороны ты прав, тест не должен зависить от реализации, с другой - мы тестируем не непонятное нечто. Мы тестируем свой код, который не в пьяном бреду писали. Вон, в Symfony в последнем релизе между твигом и симфони убирают прослойку в виде Templating, потому что потестили и поняли, что в 99% супер-абстракция никому не нужна, а нужна производительность, которая на ровном месте теряется.
 

grigori

( ͡° ͜ʖ ͡°)
Команда форума
для тех кто в танке. мы тестируем чужой код
и ТС, судя по описанию задачи - тоже
 

whirlwind

TDD infected, paranoid
Тест может не зависить от реализации, только если он чисто state-based. Чисто функциональные/приемочные, интеграционные тесты создают бОльшую часть окружения и по этому выглядят по большей части state-based test. Отсюда blackbox testing и прочие разговоры про полную заменимость реализации. Это действительно так. Но обеспечить 100% покрытие такими тестами очень сложно, так как по совокупности они охватывают большой алгоритмический объем -> математическая сложность при 100% покрытии просто по человечески нереализуема. Прибегают ко всяким хитростям, например перекрестный охват кейсов, то есть когда один тест тестирует кучу кейсов. Здесь есть негативная побочка - поскольку тесты не локализуют четко кейс, в будущем на них всегда тратится куча времени: при возврате к тесту полдня курим - что же тут вообще происходит?!

С модульными тестами все по другому. Модульные тесты легко писать и они хорошо локализуют проблемы. При полном покрытии практически навсегда избавляемся от ситуации: здесь исправили, там отвалилось. И в этом смысл модульных тестов - помогать команде работь фиксить/менять/ломать со спокойной душой. Модульные тесты функциональные лишь от части. И state-based для модульных можно использовать в ограниченном количестве случаев, например, когда ведется работа с примитивами/entities/value object и т.п. В случаях, когда юнит взаимодействует с другими подсистемами и классами, не всегда эффективно использовать тестирование состояния. Если стремиться к этому, тесты будут получаться адски пухлыми, непонятными, медленными завязанными на всякую инфраструктуру типа ObjectMother/Builder и т.п. Что бы этого избежать, нужно использовать behaviour-based через моки или стабы. Как только мы вводим использование тестирования поведения - можно сразу забыть про независимость модульных тестов от реализации. По этому надо придерживаться не крайностей, а золотой середины: behaviour/state = 50/50.
 

hell0w0rd

Продвинутый новичок
Вурдалак, ты прав, но ты оказываешься не прав в том, что мы не можем получить параметры Response, вне зависимости от реализации.
PHP:
$client = static::createClient();
$crawler = $client->request('GET', '/demo/hello/Fabien');
$response = $client->getResponse()
...
В общем это мы обсуждаем идеальный случай, когда есть фреймворк и покрываем мы свой код, а тут легаси и чужой код, как оказалось, так что единственный вариант - предложенный Amdy)
 
Сверху