Pull to refresh

Comments 54

Ок. Ок. В начале поста вы пишете, что открывая сайт фреймворка PHPUnit я вижу тесты калькулятора, которые не имеют отношение к моему веб-приложению, построенному на основе паттерна MVC. Я ожидал в конце статьи увидеть живой пример, например, тестирования модуля аутентификации. А по факту я вижу голую абстракцию.
Ок. Вопрос такой: а кто написал модуль аутентификации? Я бы вот его не писал, а взял из какого-то фреймворка. И убедился, что там он протестирован. То есть, статья о том, что прежде всего нужно тестировать приложения вцелом. И тестировать нужно конкретно код приложения.
Название статьи вам о чем-нибудь говорит?

Я так и не понял: статья о нужности тестирования или о том, все-таки, как же легко начать тестировать?
Ну в нужности тестирования, я полагаю, никто не сомневается. Статья о том, что начинать нужно с функциональных тестов. И то какие лучше элементы тестировать юнит-тестами.

При этом, да, я забыл обозначить, что если вы пишите фреймворк сами, или пишщите к нему отдельныме модули, то конечно, их стоит тестировать изначально.
Я это и без поста знаю.

Я junior, но в следствие проблем с предыдущим проектом, я решил покрыть следующий проект максимально тестами, насколько мне это позволят сроки и другие факторы. Заголовок поста меня заинтересовал, а войдя я даже ссылок на литературу не увидел.
Максимальное покрытие это хорошо. Спорить не буду. Я лишь заостряю внимание, с чего стоит начать. При этом, позвольте такой вопрос: ваш нынешний проект, он использует какие-то сторонние фреймворки?
Вообщем, спасибо. Я уточнил это в статье.
Присоединяюсь. Как незнакомый с тестированием, я понял что данная статья одна из тех, которые пишут о том, как легко начать тестировать тем, кто уже этим занимается пару лет :)
Не-не-не, те кто этим занимаются много лет, заберут табуретку из начала поста и будут ею швырять в меня )
Объясните, пожалуйста, что вы хотите этим текстом тогда сказать? что не нужно тестировать конкретные методы, а тестировать результат — вывод в браузер?
Точно.

Вот только, чтобы избежать лишних таубреток уточню: сначала протестируйте вывод в браузер, а потом, тестируйте отдельные методы.
Так-с, уже начинаю понимать. Теперь просто представим, что я внутренний заказчик от которого зависит принятие решений по поводу будет ли использоваться какое-либо тестирование и какое будет.

Она пересыпана терминалогией, которая начинающему незнакома, местами есть отсылки к тому, что перед этим предлагалось забыть. Мне было не трудно забыть, ибо я ничего и так не знаю об юнит-тестах, кроме пары общих фраз. Но оказывается я должен что-то знать все равно :)
Часто разделяют автоматизированные тесты веб-приложений на 4 вида (это не касаясь нагрузочных, юзабилити и т. п.):

— приёмочные — проверяют конечный результат, как правило в браузере, то есть что непосредственно знает браузер (и как следствие показывает пользователю), получая html/js/css с сервера со всеми заголовками и т. п., проверяется не только приложение (php-код), но и сервер, и браузер (например JS-код) и прочая среда. Выполняются долго. Запускаются редко.

— функциональные — проверяют почти то же самое, но на более низком уровне, сервер и браузер уже не используются обычно, а проверяется вывод скрипта, то есть что html код соответствует ожидаемому, что в базу внесены нужные изменения и т. п. Зачастую используют эмуляторы браузеров. Выполняются быстрее. Запускаются чаще.

— интеграционные — опускаются ещё ниже, проверяется взаимодействие отдельных слоев приложения, например, что роутер, получив URL (или URI? вечно их путаю), вызовет контроллер с нужными параметрами и что контроллер, получив параметры передаст в шаблон нужные переменные (тесты роутера и тесты контроллера — обычно два разных теста). Выполняются относительно быстро, запускаются часто.

— модульные (юнит) — самый низкий уровень, тестирование отдельных методов, тупо что метод с параметрами возвращает нужное значение. Выполняются очень быстро, запускаются также часто, как нажимается кнопка save или run. В идеале автоматически при её нажатии :)

На самом деле разделение довольно условно и зачастую сложно однозначно отнести конкретный тест к одному из слоев (из-за лени разработчиков :) ) — он может быть, например, как и модульный с одной стороны (проверяем вывод в ответ на ввод), так и интеграционный с другой (вывод заключается в вызове другого метода с зависящими от входных параметров). На PHPunit в принципе их писать можно, но ни разу не видел такого.

По хорошему надо тестировать всё, но, скажем, приёмочные тесты отнимают довольно много времени и если нет отдельных тестировщиков, то ими часто пренебрегают (особенно если сложного JS на клиенте нет). Функциональные дают чуть меньшую уверенность в том, что приложение работает как ожидалось, но отнимают относительно мало времени, по сути один тест является спецификацией одной ветки выполнения, то есть переписыванием ТЗ с человеческого языка на алгоритмический в терминах приложения и ЯП. Интеграционные при желании оттестировать всё что можно занимают много времени и часто являются детализацией функциональных, разбивая их на несколько частей, что несколько снижает энтузиазм их написания («это же уже работает!»). Модульные пишутся просто (если архитектура нормальная) и быстро. Если считать функциональные спецификацией приложения, то модульные это спецификация методов, с хорошей архитектурой метод многого делать не должен и спецификации примитивны.

Внутреннему заказчику я бы посоветовал (особенно при работе с существующим приложением без тестов) для начала заказать, чтобы исполнители начинали с функциональных тестов (на новую функциональность или на ту, которую нужно изменить), как минимум для основной ветки выполнения (обычный сценарии работы) и использовали модульные в нетривиальных случаях, когда функциональными добраться до неосновной ветки выполнения сложно и/или долго (например для ситуаций типа «нет места на диске» или «сервер БД недоступен»). При обнаружении бага прежде чем искать его (особенно если сходу не понятно где он конкретно), сначала написать тест, который с этим багом заваливается, а без него должен пройти. При небольшом рефакторинге (типа выделения метода-объекта) писать модульные и интеграционные (если не сложно, а сложно быть не должно) тесты.

Спасибо за такой развернутый комментарий.

Кстати, ты спрашивал как в Codeception сделать новую test suite для интеграционных тестов. Теперь это делается командой

codecept generate:suite name guyname
Спасибо. Всё никак не приступлю к попытке внедрения codecept на существующий проект. Но скоро :)
Спасибо огромное — вот примерно такого не хватало как по мне в статье :) ибо в ней рассчитывается, что пользователь должен что-то знать, а проблема как раз в том, что в плане тестирования трудно к чему-то подступиться, ибо непонятно с чего начать.

И ещё в статье немного непонятно сделано с переходом от функционального тестирования к модульному — на этом переходе объяснение обрывается и дальше как-то водянисто — не так как в начале — с примерами.
И ещё вопрос, что делать с JS — ведь много функционала в современном приложении работает черех ajax — как его тестировать?
Через Selenium.
Можно как писать внтури Selenium IDE, так и через те же тесты в Codeception.
Именно выполнение JS-кода и его связь с сервером — через Selenium, как приёмочные тесты.

Упростит задачу если предварительно серверную часть протестировать функциональнымии, то есть например, что на запрос типа GET /users/volch.json (или GET /api/users/volch — на любителя, мне первый вариант больше нравится) сервер вернёт именно json, причём корректный имеено для этого запроса. Это чтобы не ковырять JS, когда проблема на самом деле в сервере.
А мне второй. Но обоснованно. В первом через URI сообщается больше информации, чем это может потребоваться. В частности, он жестко задаем формат выходных данных — JSON. Если код-клиент этого URI потребует для работы XML, то придется в нем изменять URI, хотя по сути данные останутся прежними. Во-втором же при правильной реализации можно этим рулить через Content-Type работая с одним и тем же URI.

RESTfull очень любопытный и, имхо, правильный подход в контексте веба.
Собственно я хотел показать разницу между /api/users/volch и /users/volch*

Тогда вообще GET /users/volch :) Идеологически оно, конечно, правильно. Но мне как-то проще поменять uri в клиенте, чем формировать и менять при необходимости Content-Type. Плюс помню были проблемы с корректной обработкой в самом популярном на то время клиенте IE5.5
*На PHPunit в принципе их писать можно, но ни разу не видел такого. В другом месте это должно было быть, про приёмочные, но эту «ветку» решил удалить и так много получилось, но эта фраза как-то выжила, причём не в том месте где должна была быть.
О том как легко начать тестировать. Об этом написано в заголовке.
Или приведённые два примера вы находите сложными?
Данные примеры — это приемочные тесты или модульные? Почем дальше идет речь о том, что нужно использовать PHPUnit? Потом говорится, что их можно и не использовать.

Есть ещё какие-то функциональные тесты…
Начиналось в стате всё с функциональных тестов. Если напишите их, получайте ачивку и переходите к юнит тестам.
А вы из тех безнадёжных, которым нужны видеоуроки иначе дела не будет?
Голой абстракицией вы назвали пример поиска строки на странице и проверка раотоспособности формы? Действительно, это же базовые примеры PHPUnit-а…

Отличня статья, лично меня Codeception очень заинтересовал. Особенно после сравнения автора с PHPUnit gist.github.com/1498755
Как-то не-русски получилось: «сравнения автора с PHPUnit».
Сравнения автором одинаковых тестов на PHPUnit и Codeception.
Лично я из статьи так и не понял, как могу легко начать тестировать? Т.е. кроме того, что мне нужно скачать один из тестировочных фреймов и определить задачи для них. Но это ведь понятно и без пояснений. Лично для меня не хватает работающих примеров.
Как я понял статья не для начинающих, а для тех, кто хочет перейти с юнит-тестов на этот Codeception. Для начинающих тут ничего полезного нет.
Там один пример и он работающий. Начните с него.

Остальные ситуации объяснены на пальцах.
А вы можете описать что нужно сделать, чтобы эти тесты работали с:

$I->click('Войти');
$I->see('Личный кабинет');


если все файлы проекта в win-1251?

На выходе в консоли выводятся, естественно, не читаемые символы.
Тут важно не что в консоли выводится, а что выводится на самом сайте.
То есть, важней всего, чтоб кодировка файлов проекта совпадала с кодировкой сайта.

А вот кирилица в консоли это впринципе болезненная тема. Постараюсь изучить возможности.
Какая ОС, кстати?
find . -name '*.php' -type f | while read i; do iconv -f WINDOWS-1251 -t UTF-8 "$i" >tmp; mv tmp "$i"; done
Блин, пока набирал ответ — уже написали что это windows.
О да, знающие решение проблемы люди видать минусуют.
Кириллицу в консоли я победил с помощью ansicon. Но все равно, при выводе результатов возникают проблемы. Я завтра на работе все шаги повторю, чтобы вспомнить. Я могу вам потом прислать скрин вывода результатов? А то сам я победить не могу)
ОС — win7 64
Оки. Будет интересно. Там у меня с цветами глюк был, на винде цвета по дефолту выводились. Я его вроде поправил, тепер цвета нужно включать через конфигурацию.
Опишите простым и понятным языком, как взаимодействует пользователь с вашим приложением. Затем запишите все то же самое на алгоритмическом языке. Получите тест. Для большинства начинающих уже первый этап становится серьезным испытанием. :)
Так и просится слово «бросить» в названии статьи:)
Отличная статья! Очень полезно для тех кто хочет начать тестировать, но не знает с чего начать или все время откладывает!

Я, лично, теперь точно попробую!
Тестирование это конечно хорошо, но писать тестирование утомительно, если только сайты не делаются на основе какой то одной платформы.
А одна платформа подразумевает что все основные моменты уже и так протестированы.
ХЗ я не сторонник писания тестов, просто не вижу в этом смысл для себя.
Про платформу я вроде говорил неоднократно в статье. Тестировать её не надо.
Тестируйте только то, что сделали сами. Если вы уверены, что ссылка А всегда работает и форма Б всегда работает — ну тоже, не тестируйте.

Только скажу, что с ростом проекта уверенности стает всё меньше и меньше )
Платформу я имел ввиду движок сайта, магазина или еще чаго. Если на нем поднят не первый проект то там по дефолту уже баги закрыты.
Ну если его вообще не менять из проекта в проект, только дизайн править, то да.
Если вы пишите под протестированный движок (как протестирован — не важно), или просто доверяете его разработчикам, или платформу получили в виде чёрного ящика (а-ля dll), то тесты пишите только на свой код. Не надо проверять, например, что предоставляемая платформой обёртка для БД действительно пишет в БД — это уже не ваша зона ответственности как разработчика продукта на платформе: убедились, что вызов обёртки идёт с нужными параметрами — пошли дальше. Если есть баги в платформе, касающиеся вашей функциональности, то они выявятся на функциональных/приёмочных тестах и сможете пофиксить платформу или отправить багрепорт, а пока фиксят написать костыль для обхода. А наличие модульных и интеграционных тестов на свой код позволит однозначно отнести непроходящий функциональный тест на совесть разработчика платформы (или что доки к ней не читаете и, например, пытаетесь использовать PL/SQL в MySQL ;) )
но писать тестирование утомительно, если только сайты не делаются на основе какой то одной платформы.

А вот тут не согласен. Платформа у нас одна и едина. Называется Веб. И тестировать там ничего утомительного. Перед сдачей сайту заказчику вы что делаете? Просматриваете сайт на наличие ошибок, смотрите, чтобы всё работало. Возьмите и один раз запишите свои шаги и будут вам функциональные тесты.
Утомительно покрытие кода тестами для галочки, потому что «так нужно», заставили, да ещё тестирующий фреймворк не знаешь толком, а архитектура заставляет писать даже модульные тесты с десятком стабов/моков и проверкой БД. В общем покрывать тестами существующий код, написанный без учета необходимости тестирования.

А вот когда пишешь с нуля или на платформе, написанной с учетом практик тестирования, да ещё сначала пишешь тесты, а потом код, который их выполняет, то это становится не утомительным, а прикольным (в хорошем смысле слова). И архитектура сама собой получается такой что, например, какие-то изменения нужно вносить только в одно место, заведомо зная, что на работу остальных они не повлияют. А если повлияют, то узнаешь об этом моментально, а не когда заказчик посреди ночи начнёт названивать.
Спасибо, приятный стиль изложения.
Интересно было бы узнать ваше мнение, как бы вы решали проблему тестирования, если бы сложность логики на клиенте (в браузере, на ExtJS) приближалась бы к «толстому» клиенту, с многочисленными динамически подгружаемыми JS-формами и довольно большим локальным хранилищем данных (Gears->IndexedDB).
Применим ли в данном случае Codeception?
Для яваскрипт кода используйте Jasmine, он заменит вам юнит-тесты. Для функциональных тестов, наверняка, лучше сам по себе Selenium.

Codeception нужен для тестирования серверной части.
Sign up to leave a comment.

Articles