Чистота тестового кода в Protractor
Сложные e2e-сценарии часто страдают избыточностью и
непредсказуемостью. В контексте Protractor это проявляется в чрезмерном
количестве ожиданий, дублировании селекторов, неконтролируемой логике
внутри it-блоков и слабой модульности. Поддержка таких
тестов становится дорогой и рискованной, особенно при частых изменениях
UI.
Тесты в Protractor должны быть декларативными. Логические ветвления,
вычисления и вспомогательные фильтры желательно переносить в утилиты или
Page Object. Внутри it остаются только действия и проверки.
Это делает сценарий линейным и удобным для понимания.
Плохо
it('добавляет товар в корзину', () => {
element(by.css('.product')).click();
browser.sleep(3000);
const price = parseFloat(
element(by.css('.price')).getText().then(t => t.replace('₽', ''))
);
if (price > 1000) {
element(by.css('.discount')).click();
}
expect(element(by.css('.cart-item')).isPresent()).toBe(true);
});
Хорошо
it('добавляет товар в корзину', () => {
catalogPage.addItem();
cartPage.applyPossibleDiscount();
expect(cartPage.hasItem()).toBe(true);
});
Page Object уменьшает связность между тестом и DOM-структурой. Все селекторы, ожидания и операции концентрируются в одном месте. Это уменьшает количество изменений в тестах при рефакторинге интерфейса.
Ключевые моменты Page Object
Важно избегать чрезмерной универсальности объектов страницы. Page Object описывает конкретный экран, а не абстрактный модуль. Дробление экранов на мелкие объекты оправдано только при действительно независимых зонах UI.
sleepbrowser.sleep() нарушает предсказуемость и увеличивает
время прогона. Вместо фиксированных задержек применяются
ExpectedConditions или кастомные ожидания, привязанные к
состоянию UI.
const EC = protractor.ExpectedConditions;
browser.wait(EC.visibilityOf(element), 5000);
Ожидания выражают намерение: что должно произойти для продолжения сценария. Это повышает стабильность тестового набора и снижает флейки.
Смешение by.css, by.id,
by.binding и by.model без чётких правил
усложняет навигацию по коду. Чистый тестовый код определяет
последовательность предпочтений: обычно CSS-селекторы первичны, а
Angular-специфичные — вспомогательны. Полезна политика именования
CSS-классов для тестирования, например data-role или
data-testid, что устраняет хрупкость селекторов при
переработке стилей.
Дублирование шагов увеличивает стоимость изменений и приводит к
несогласованности поведения. В Protractor это часто проявляется в
однотипных цепочках click(), sendKeys() и
wait(). Инкапсуляция в Page Object или утилиты позволяет
переиспользовать логику и формировать тестовые DSL-конструкции.
loginPage.loginAs('admin');
orderPage.submitOrder();
Такие конструкции повышают выразительность и уменьшают когнитивную нагрузку.
Чистый код в тестах предусматривает чёткую границу между сценарием и фиксированными данными. Строки, даты и константы выносятся в структуру фикстур или фабрик. Динамические данные генерируются детерминированно, чтобы исключить случайные падения.
Допустимы три источника данных:
Смешение этих уровней внутри it нарушает читаемость и
усложняет отладку.
Проверка должна быть ясной и отражать бизнес-смысл. Неформализованные ожидания, такие как проверка наличия элемента на странице, должны коррелировать с результатом действия. Например, после оформления заказа проверяется статус, а не просто появление блока.
expect(orderPage.status()).toEqual('Оформлен');
Чрезмерное количество проверок в одном тесте делает его хрупким. Один
it выражает один сценарий и одну точку достоверности.
Тест должен читаться сверху вниз без необходимости удерживать сложное
состояние в голове. Protractor допускает цепочки асинхронных операций,
что при неправильном применении приводит к вложенности. Линейность
достигается Page Object-методами и грамотным использованием
await в современных версиях, полностью убирающим
callback-ад.
Тесты должны быть изолированы. Результат одного сценария не должен становиться предусловием другого. В Protractor это приводит к необходимости сброса состояния, использованию API для подготовки данных или старту с начального экрана. Чистота достигается при минимальном количестве глобальных зависимостей.
Важен единый подход к диагностике падений. Page Object может содержать сообщения об ошибках или логирование, упрощающее поиск причины. Разрозненные сообщения затрудняют анализ и приводят к неверным выводам о стабильности тестового набора.
Чистота тестового кода — процесс, а не одноразовое действие.
Избавление от sleep, сокращение дублирования,
стандартизация селекторов и рост выразительности сценариев ведут к
тестам, которые легче сопровождать и масштабировать. В контексте
Protractor это особенно важно, учитывая тесную связь с UI-слоем и
насыщенность Angular-специфичными механизмами.
Такая дисциплина позволяет техническому долгу не накапливаться, а тестовой базе — оставаться инструментом уверенности, а не источником хаоса.