Переиспользование браузерной сессии

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


Основные принципы

В стандартной конфигурации Protractor каждая спецификация или it блок может открывать новый экземпляр браузера. Это обеспечивает чистоту тестов, но увеличивает время выполнения. Переиспользование сессии позволяет:

  • Сохранять cookies, локальное хранилище и сеансовые данные.
  • Избегать повторного входа в систему при последовательных тестах.
  • Сократить накладные расходы на запуск браузера и инициализацию Angular.

Принцип работы основывается на том, что один экземпляр browser остаётся активным на протяжении нескольких тестов или файлов спецификаций.


Настройка конфигурации Protractor

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

exports.config = {
    framework: 'jasmine',
    specs: ['specs/**/*.spec.js'],
    directConnect: true,
    capabilities: {
        browserName: 'chrome',
        chromeOptions: {
            args: ['--disable-infobars', '--start-maximized']
        }
    },
    // Основная настройка для переиспользования сессии
    restartBrowserBetweenTests: false,
    // Опционально: управление сессиями на уровне файлов спецификаций
    SELENIUM_PROMISE_MANAGER: false
};

Ключевые моменты:

  • restartBrowserBetweenTests: false — запрещает перезапуск браузера между тестами.
  • SELENIUM_PROMISE_MANAGER: false — рекомендуется отключать для использования современного синтаксиса async/await.
  • При использовании multiCapabilities необходимо убедиться, что каждый поток тестов использует отдельную сессию, иначе могут возникать конфликты.

Сценарии использования

1. Последовательное тестирование авторизации

Если первый тест выполняет вход в систему, а последующие проверяют функциональность уже после авторизации, переиспользование сессии позволяет не выполнять повторный логин:

describe('Авторизация и функциональность', () => {

    beforeAll(async () => {
        await browser.get('https://example.com/login');
        await element(by.id('username')).sendKeys('admin');
        await element(by.id('password')).sendKeys('password');
        await element(by.id('loginButton')).click();
        await browser.wait(ExpectedConditions.urlContains('/dashboard'), 5000);
    });

    it('Проверка виджета на дашборде', async () => {
        const widgetText = await element(by.css('.widget-title')).getText();
        expect(widgetText).toBe('Основной виджет');
    });

    it('Проверка меню пользователя', async () => {
        const userMenu = await element(by.css('.user-menu')).isPresent();
        expect(userMenu).toBe(true);
    });

});

В этом примере браузерная сессия сохраняется между тестами, что исключает повторный вход.


2. Тестирование с сохранением состояния

При работе с корзинами, настройками пользователя или другими элементами, где важно состояние приложения, переиспользование сессии позволяет избежать лишней подготовки данных:

it('Добавление товара в корзину', async () => {
    await element(by.css('.product-1')).click();
    await element(by.css('.add-to-cart')).click();
    const cartCount = await element(by.css('.cart-count')).getText();
    expect(cartCount).toBe('1');
});

it('Проверка корзины без повторного добавления', async () => {
    await browser.get('https://example.com/cart');
    const items = await element.all(by.css('.cart-item')).count();
    expect(items).toBe(1);
});

Ограничения и предостережения

  • Изоляция тестов нарушается. Плохие практики могут привести к тому, что тесты будут зависеть друг от друга.
  • Накопление состояния. С течением времени локальное хранилище и cookies могут создавать конфликты, особенно при длительном запуске.
  • Проблемы с параллельными тестами. В многопоточном режиме (например, с shardTestFiles: true) необходимо тщательно контролировать сессии, иначе данные одного теста могут влиять на другой.
  • Рекомендуется периодически очищать cookies или локальное хранилище между блоками describe, если тесты чувствительны к состоянию.
afterAll(async () => {
    await browser.manage().deleteAllCookies();
    await browser.executeScript('window.localStorage.clear();');
});

Использование вместе с Page Object

Переиспользование браузера особенно удобно при структурировании тестов через Page Object. Page Object хранит методы для взаимодействия с приложением, а повторное использование сессии позволяет вызывать их последовательно без потери состояния:

class LoginPage {
    constructor() {
        this.username = element(by.id('username'));
        this.password = element(by.id('password'));
        this.loginButton = element(by.id('loginButton'));
    }

    async login(user, pass) {
        await this.username.sendKeys(user);
        await this.password.sendKeys(pass);
        await this.loginButton.click();
        await browser.wait(ExpectedConditions.urlContains('/dashboard'), 5000);
    }
}

const loginPage = new LoginPage();

describe('Функциональные тесты', () => {

    beforeAll(async () => {
        await browser.get('https://example.com/login');
        await loginPage.login('admin', 'password');
    });

    it('Проверка элементов дашборда', async () => {
        const header = await element(by.css('h1')).getText();
        expect(header).toBe('Добро пожаловать');
    });

});

Переиспользование браузерной сессии в Protractor позволяет создавать более быстрые и эффективные тесты, сохранять состояние между сценариями и оптимизировать время выполнения больших наборов спецификаций, при этом требуя аккуратного управления зависимостями между тестами.