Пошаговое выполнение тестов

Protractor — это инструмент для автоматизированного тестирования Angular и AngularJS приложений, построенный поверх Selenium WebDriver. Основная особенность Protractor заключается в том, что он учитывает асинхронность Angular-приложений, автоматически ожидая завершения всех операций с DOM, HTTP-запросов и таймеров перед выполнением тестовых шагов.

Настройка среды для выполнения тестов

Перед началом выполнения тестов необходимо создать конфигурационный файл protractor.conf.js, в котором указываются основные параметры:

exports.config = {
    framework: 'jasmine',
    seleniumAddress: 'http://localhost:4444/wd/hub',
    specs: ['specs/*.spec.js'],
    capabilities: {
        browserName: 'chrome'
    },
    directConnect: true,
    allScriptsTimeout: 11000,
    getPageTimeout: 10000
};
  • framework — тестовый фреймворк (Jasmine, Mocha или Cucumber).
  • seleniumAddress — адрес сервера Selenium или использование directConnect для прямого подключения.
  • specs — путь к тестовым файлам.
  • capabilities — настройки браузера, в котором будет выполняться тест.
  • timeouts — управление ожиданиями для страниц и скриптов.

Организация тестов

Тестовый сценарий в Protractor обычно строится по следующей схеме:

  1. Подготовка (beforeEach) — открытие страницы, инициализация данных.
  2. Действия (it) — взаимодействие с элементами страницы: ввод данных, клики, скроллы.
  3. Проверки (expect) — валидация результатов действий.
  4. Очистка (afterEach) — возврат приложения в исходное состояние.

Пример структуры теста:

describe('Проверка формы входа', function() {

    beforeEach(function() {
        browser.get('https://example.com/login');
    });

    it('должна успешно авторизовать пользователя', function() {
        element(by.id('username')).sendKeys('admin');
        element(by.id('password')).sendKeys('12345');
        element(by.id('loginBtn')).click();

        expect(element(by.css('.welcome-message')).getText())
            .toEqual('Добро пожаловать, admin!');
    });

    afterEach(function() {
        browser.manage().deleteAllCookies();
    });

});

Асинхронность и ожидания

Protractor автоматически синхронизируется с Angular, но иногда требуется явно задать ожидания:

  • Ожидание элемента:
let EC = protractor.ExpectedConditions;
let submitBtn = element(by.id('submit'));
browser.wait(EC.elementToBeClickable(submitBtn), 5000);
submitBtn.click();
  • Ожидание текста или видимости:
let message = element(by.css('.alert-success'));
browser.wait(EC.visibilityOf(message), 7000);
expect(message.getText()).toContain('успешно');
  • Использование async/await для упрощения синтаксиса и явного контроля асинхронности:
it('должна отправить форму', async function() {
    await element(by.id('email')).sendKeys('test@example.com');
    await element(by.id('submit')).click();
    const text = await element(by.css('.result')).getText();
    expect(text).toBe('Форма отправлена');
});

Работа с элементами страницы

Protractor использует локаторы Selenium, но добавляет специфичные для Angular методы:

  • by.model('modelName') — связывает элемент с моделью Angular.
  • by.binding('bindingName') — обращение к данным через биндинги.
  • by.repeater('item in items') — работа с повторяющимися элементами (ng-repeat).

Примеры:

// Получение значения модели
let input = element(by.model('user.name'));
input.sendKeys('Иван');
expect(input.getAttribute('value')).toBe('Иван');

// Работа с повторяющимся списком
let items = element.all(by.repeater('item in itemList'));
expect(await items.count()).toBe(5);

Логирование и отладка шагов

Для отслеживания выполнения тестов можно использовать console.log, скриншоты и встроенные возможности Jasmine:

it('логирование и скриншоты', async function() {
    console.log('Начало теста');
    await element(by.id('action')).click();

    let screenshot = await browser.takeScreenshot();
    require('fs').writeFileSync('screenshot.png', screenshot, 'base64');

    console.log('Тест завершен');
});

Последовательное выполнение действий

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

  1. Дождаться полной загрузки страницы (browser.waitForAngular() автоматически вызывается в Angular-приложениях).
  2. Взаимодействовать с элементами только после их появления и доступности.
  3. Проверять результаты каждого шага перед переходом к следующему.

Пример цепочки действий:

await element(by.id('menu')).click();
await browser.wait(EC.visibilityOf(element(by.id('submenu'))), 5000);
await element(by.id('submenu-item')).click();
const headerText = await element(by.tagName('h1')).getText();
expect(headerText).toBe('Раздел настроек');

Рекомендации по надежности тестов

  • Избегать фиксированных sleep(), использовать ожидания через ExpectedConditions.
  • Использовать element.all() при работе с коллекциями элементов для точных проверок.
  • Минимизировать зависимость тестов друг от друга, каждый должен быть изолированным.
  • Включать очистку состояния приложения после каждого сценария.

Эти принципы позволяют создавать стабильные, поддерживаемые тестовые сценарии, которые корректно выполняются на различных браузерах и платформах, обеспечивая надежную автоматизацию проверки Angular-приложений.