Что произойдет, если у вас будет больше тестов, чем зергов в рое? На самом деле намного больше. Вы должны найти способ контролировать и управлять ими. В этой статье я поделюсь некоторыми советами и рекомендациями, которые вы можете использовать при написании приемочных тестов. Я буду использовать среду тестирования Codeception, чтобы проиллюстрировать лучшие практики, но, несомненно, они могут быть перенесены в любую среду принятия, которую вы используете для тестирования.
В кодецепцию
Разработка и создание отличного веб-приложения означает, что наш рабочий процесс и архитектура позволяют постоянно улучшать продукт. Чтобы сделать наши продукты стабильными и быть уверенными в том, что новые коммиты не окажут негативного влияния на существующий код, мы используем методы автоматического тестирования. И так же, как нам нужна правильная архитектура для нашего приложения, нам необходимо разработать правильную архитектуру для нашей платформы тестирования.
Платформа тестирования — это полная инфраструктура наших тестов. И когда я говорю «тесты», я имею в виду не только модульные тесты. Думай шире. Приложение также необходимо протестировать в браузере с Selenium (или альтернативой). Поэтому нам нужны юнит-тесты, тесты Selenium, возможно API-тесты, и все они должны выполняться вместе. Каким-то образом. Я хотел бы представить вам Codeception — современную среду тестирования PHP, основанную на компонентах Symfony2, Mink и PHPUnit.
Codeception включает в себя более 20 модулей для тестирования популярных PHP-фреймворков, API (REST, SOAP), хранилищ данных (MySQL, PostgreSQL, MongoDB и т. Д.) И веб-приложений с Selenium WebDriver. Проверьте это на официальном сайте: codeception.com
И какой лучший способ выполнить все эти тесты, чем на сервере Continuous Integration после каждого коммита? Я рекомендую использовать Codeception в качестве основного блока для вашей платформы автоматизации тестирования; Codeception может выполнять тесты Selenium, API и PHPUnit в одном и создавать полные отчеты HTML и XML для систем CI. Он может даже создать полный отчет о покрытии кода для всех тестов.
Начать писать тесты с Codeception довольно легко. Вы можете научить своих тестировщиков писать такие тесты, так как для начала требуются только самые базовые знания PHP. Я оставлю вас для самостоятельного изучения основ Codeception, поскольку я хочу рассказать вам о том, как Codeception может помочь вам создать более совершенную платформу автоматизации тестирования.
Улей испытаний
Недостаточно сказать «Мы пишем тесты» или «Мы практикуем TDD / BDD». То, к чему вы должны стремиться, — это создание надежной платформы автоматизации тестирования. На самом деле не имеет значения, пишете ли вы свои тесты перед кодом, или код перед тестами, или тесты, описанные как история (в BDD-стиле), или тесты как код. Что действительно важно, так это то, как вы управляете всеми этими тестами.
Может быть более 1000, 10000 или 100000 тестов, и они могут выполняться в течение трех или четырех часов. Вы должны держать код для своих тестов в чистоте и простоте. Тесты должны легко реорганизовываться (так как они постоянно меняются в зависимости от приложения), и их должно легко расширять. По сути, вы должны следовать тем же рекомендациям, которые вы используете для написания рабочего кода при написании тестового кода.
Базовый тест
Вот типовой приемочный тест в Codeception. В этом случае я отправляю приглашение другу с веб-сайта. Чтобы проверить это, мне нужно войти в систему, сгенерировать код приглашения, а затем попытаться зарегистрировать нового пользователя с кодом. Вот как сценарий может выглядеть в Codeception:
<?php $I = new WebGuy($scenario); $I->wantTo('generate invitation code and sign up using it'); $I->amOnPage('/login'); $I->fillField('Username','tester1'); $I->fillField('Password','123456'); $I->click('Sign In'); $I->see('Hello, tester1'); $I->click('Invite'); $I->see('Copy this invitation code'); $code = $I->grabTextFrom('#invitation_code'); $I->click('Logout'); $I->amOnPage('/register'); $I->see('You can sign up if you have invitation code!', 'h1'); $I->fillField('Invitation Code', $code); $I->fillField('Username','tester2'); $I->fillField('Password','654321'); $I->click('#invite_form input[type=submit]'); $I->see('Hello, tester2');
Даже если вы не знакомы с Codeception, этот тест должен быть достаточно читабельным; все действия описаны с точки зрения пользователя, и здесь не используются специальные технические термины. Этот тест может выглядеть простым и понятным, но если у вас есть такие тесты, вам следует подумать о его рефакторинге И вот почему …
Шаблон дизайна: объект страницы
Вы должны избегать использования жестко закодированных значений непосредственно в своих тестах, когда это возможно, поскольку это сделает тесты более устойчивыми к изменениям. Предположим, что аналогичные формы входа и регистрации используются в других тестах. Если поле имени пользователя было переименовано в «Логин», вам нужно будет переписать тесты, использующие логин. Мы можем использовать шаблон Page Object и CSS / XPath для поиска элементов на странице. То же самое касается страницы приглашения.
Объект страницы — это объект, представляющий страницу (или несколько типичных страниц) вашего сайта. Он может быть записан в виде класса со статическими свойствами и методами.
<?php class InvitePage { // URL of a page public static $URL = '/register'; // This properties define a UI map for Login Page public static $codeField = "Invitation Code"; public static $usernameField = "Username"; public static $passwordField = "Password"; public static $submitButton = "#invite_form input[type=submit]"; }
Теперь часть теста можно переписать следующим образом:
<?php $I->amOnPage(InvitePage::$URL); $I->fillField(InvitePage::$codeField, $code); $I->fillField(InvitePage::$usernameField,'tester2'); $I->fillField(InvitePage::$passwordField,'654321'); $I->click(InvitePage::$submitButton);
В этом случае все тесты, посещающие страницу приглашения, используют одни и те же переменные для размещения элементов на странице. Если какой-либо элемент меняет свою позицию, вы можете при необходимости обновить класс InvitePage
, не касаясь самих тестов.
Шаблон проектирования: контроллер
Мы удалили некоторые жестко закодированные переменные из теста, но что произойдет, если вы внедрите двухфакторную аутентификацию в разрабатываемом веб-приложении. Что это значит для ваших тестов? Это означает, что вам нужно обновить все тесты, для запуска которых требуется авторизованный пользователь. Напомню: могут быть и тысячи тестов. Было бы естественно переместить некоторую логику сценария в класс, чтобы мы могли повторно использовать сценарии входа / выхода и регистрации в других тестах.
Я спросил некоторых друзей-инженеров по автоматизации, как они относятся к такому классу. Они использовали термин Step Object (который часто встречается в BDD), но я бы скорее назвал его Контроллером из-за сходства с контроллерами, которые мы используем в веб-приложениях. Нет строгих правил, определяющих, как должны выглядеть объекты страницы или объекты шага; Вы можете строить их как хотите. Вот пример контроллера, который я бы использовал для теста Codeception:
<?php class UserController { protected $user; public function __construct(WebGuy $I) { $this->user = $I; } public function login($username, $password) { $this->user->amOnPage(LoginPage::$URL); $this->user->fillField(LoginPage::$usernameField, $username); $this->user->fillField(LoginPage::$passwordField, $password); $this->user->click(LoginPage::$submitButton); $this->user->see("Hello, $username"); } public function logout() { $this->user->click("Logout"); } public function registerWithInviteCode($code, $username, $password) { $this->user->amOnPage(InvitePage::$URL); $this->user->fillField(InvitePage::$codeField, $code); $this->user->fillField(InvitePage::$usernameField, $username); $this->user->fillField(InvitePage::$passwordField, $password); $this->user->click(InvitePage::$submitButton); } }
Теперь в коде есть логические блоки, и сценарий будет выглядеть намного чище:
<?php $I = new WebGuy($scenario); $U = new UserController($I); $I->wantTo('generate invitation code and sign up using it'); $U->login('tester1', '123456'); $I->click('Invite'); $I->see('Copy this invitation code'); $code = $I->grabTextFrom('#invitation_code'); $U->logout(); $U->registerWithInviteCode($code, 'tester2', '654321'); $I->see('Hello, tester2');
из<?php $I = new WebGuy($scenario); $U = new UserController($I); $I->wantTo('generate invitation code and sign up using it'); $U->login('tester1', '123456'); $I->click('Invite'); $I->see('Copy this invitation code'); $code = $I->grabTextFrom('#invitation_code'); $U->logout(); $U->registerWithInviteCode($code, 'tester2', '654321'); $I->see('Hello, tester2');
Внедряя контроллеры и объекты страниц, мы избавились от большинства жестко заданных значений и общих шагов сценария. Он может регистрировать пользователей из других тестов, и это действительно полезно, поскольку, вероятно, большая часть функциональности вашего приложения доступна только авторизованным пользователям. Вы можете написать 10, 100 или даже 1000 тестов, но используя объекты страниц и контроллеры, они не создадут путаницу и их будет легко поддерживать.
Сообщить командиру
Из-за рефакторинга тестовый код, вероятно, потерял часть своей читабельности не для разработчиков. К счастью, Codeception может помочь с этим тоже. Codeception покажет вам все шаги сценария, которые были выполнены при выполнении теста:
$ ./codecept.phar run accept --steps Codeception PHP Testing Framework v1.5.5 Работает на PHPUnit 3.7.14 от Себастьяна Бергманна. Прием люксов начался Попытка сгенерировать код приглашения и зарегистрироваться с его помощью (InviteCept.php) Сценарий: * Я нахожусь на странице '/ логин' * Я заполняю поле «Имя пользователя», «tester1» * Я заполняю поле «Пароль», «123456» * Я нажимаю «Войти» * Я вижу «Привет, тестер1» * Я нажимаю «Пригласить» * Я вижу "Скопировать этот код приглашения" * Я беру текст с "#invitation_code" * Я нажимаю «Выйти» * Я нахожусь на странице '/ зарегистрироваться' * Я вижу: «Вы можете зарегистрироваться, если у вас есть код приглашения!», «H1» * Я заполняю поле «Код приглашения», «iuSia89ak» * Я заполняю поле «Имя пользователя», «tester2» * Я заполняю поле «Пароль», «654321» * Я нажимаю "#invite_form input [type = submit]" * Я вижу «Привет, тестер2» Время: 10 секунд, память: 26.00Mb ОК (1 тест, 4 утверждения)
В этом случае вывод читабелен. Этот сценарий может даже быть показан нетехническому человеку, менеджеру или бизнес-аналитику, и они поймут, что происходит. Codeception позволяет генерировать HTML-отчеты, написанные аналогичным образом. Они могут быть показаны менеджерам или бизнес-аналитикам, чтобы продемонстрировать, что и как вы используете.
Вывод
В настоящее время инженеры по автоматизации тестирования предпочитают Java и Ruby, но, как разработчик PHP, вы, несомненно, заинтересованы в тестировании платформ, которые хорошо работают с вашим кодом PHP и написаны на самом PHP. Codeception — отличный инструмент, позволяющий легко начать приемочное тестирование, и он достаточно гибок, чтобы создать надежную платформу автоматизации тестирования.
Но независимо от того, какую платформу вы используете, имейте в виду, что недостаточно просто писать тесты. Чтобы сделать тесты чистыми, стабильными и поддерживаемыми, используйте принципы KISS и DRY, которые вы уже знаете. В этом вам помогут шаблоны проектирования, такие как Page Object и Controller (Step Object).
Изображение через Fotolia