Hooks и обработка сценариев

В Protractor hooks представляют собой специальные функции, которые выполняются в определённые моменты жизненного цикла теста. Их использование позволяет управлять поведением тестов, настраивать окружение, выполнять подготовительные действия перед запуском сценариев и обрабатывать результаты после выполнения тестов. Hooks критически важны для поддержания чистоты тестовой среды и обеспечения предсказуемости тестов.


Основные типы Hooks

Protractor использует подход Jasmine или Mocha для определения жизненного цикла тестов. Соответственно, hooks делятся на несколько категорий:

  1. beforeAll / afterAll

    • beforeAll выполняется один раз перед всеми сценариями в конкретном блоке describe.
    • afterAll выполняется один раз после всех сценариев блока. Используются для глобальной подготовки или очистки, например, авторизация пользователя или очистка базы данных.
    describe('Тестирование авторизации', () => {
        beforeAll(async () => {
            await browser.get('https://example.com/login');
            await element(by.id('username')).sendKeys('admin');
            await element(by.id('password')).sendKeys('12345');
            await element(by.id('loginBtn')).click();
        });
    
        afterAll(async () => {
            await browser.quit();
        });
    
        it('Проверка успешного входа', async () => {
            expect(await element(by.css('.welcome')).isDisplayed()).toBe(true);
        });
    });
  2. beforeEach / afterEach

    • beforeEach запускается перед каждым сценарием it.
    • afterEach запускается после каждого сценария. Применяются для подготовки среды, сброса состояния или логирования ошибок после каждого теста.
    beforeEach(async () => {
        await browser.get('https://example.com');
    });
    
    afterEach(async () => {
        const logs = await browser.manage().logs().get('browser');
        if (logs.length) {
            console.log('Логи браузера:', logs);
        }
    });

Асинхронность в hooks

Protractor построен на Promise и async/await. Все hooks, выполняющие асинхронные операции (например, browser.get, взаимодействие с элементами), должны использовать async и await. Без этого возможны гонки данных и непредсказуемые ошибки.

beforeEach(async () => {
    await browser.get('https://example.com/dashboard');
});

Использование обычной функции без async приведёт к тому, что тест будет запускаться до завершения загрузки страницы, что вызовет падение проверки.


Управление сценариями с помощью hooks

Hooks позволяют создавать гибкую структуру тестов:

  • Сброс состояния: afterEach можно использовать для очистки кук, локального хранилища или базы данных.
  • Логирование и отчёты: запись скриншотов при падении теста через afterEach.
  • Условный запуск: внутри beforeEach можно проверять окружение и пропускать тесты в неподходящих условиях.

Пример записи скриншота при падении теста:

afterEach(async function () {
    if (this.currentTest.state === 'failed') {
        const png = await browser.takeScreenshot();
        require('fs').writeFileSync(`./screenshots/${this.currentTest.title}.png`, png, 'base64');
    }
});

Совмещение hooks и Page Object

Использование Page Object Model совместно с hooks повышает читаемость и переиспользуемость кода. Hooks отвечают за подготовку и очистку, Page Objects — за взаимодействие с элементами.

const LoginPage = require('./pages/login.page');

describe('Тестирование Login', () => {
    const loginPage = new LoginPage();

    beforeEach(async () => {
        await loginPage.open();
    });

    it('Ввод корректных данных', async () => {
        await loginPage.login('admin', '12345');
        expect(await loginPage.isWelcomeVisible()).toBe(true);
    });

    afterEach(async () => {
        await loginPage.clearSession();
    });
});

Важные практики при работе с hooks

  1. Минимизировать асинхронные операции в beforeAll для ускорения выполнения тестов.
  2. Использовать afterEach для сброса состояния, чтобы тесты оставались независимыми.
  3. Избегать побочных эффектов: не изменять глобальные переменные внутри hooks без крайней необходимости.
  4. Логировать ошибки: даже если тест падает, информация о проблеме должна сохраняться для анализа.
  5. Структурировать блоки describe логически, чтобы hooks применялись только к нужным сценариям.

Hooks в Protractor формируют основу управления жизненным циклом тестов, обеспечивают стабильность сценариев и дают возможность масштабировать автоматизацию без потери контроля над состоянием среды и результатами тестирования.