Связь шагов с тестами

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

Определение шагов теста

Шаг теста — это отдельное действие или проверка, которую необходимо выполнить в рамках одного сценария. В Protractor шаги обычно выражаются через вызовы элементов страницы и методов WebDriver:

await element(by.id('login')).sendKeys('user123');
await element(by.css('.submit-button')).click();
const message = await element(by.binding('welcomeMessage')).getText();
expect(message).toEqual('Добро пожаловать, user123');

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

Создание абстракции шагов

Для поддерживаемости тестов важно отделять логику шагов от самих тестов. Обычно создают Page Object или helper-функции:

class LoginPage {
    constructor() {
        this.usernameInput = element(by.id('login'));
        this.submitButton = element(by.css('.submit-button'));
        this.welcomeMessage = element(by.binding('welcomeMessage'));
    }

    async enterUsername(username) {
        await this.usernameInput.sendKeys(username);
    }

    async submit() {
        await this.submitButton.click();
    }

    async getWelcomeMessage() {
        return this.welcomeMessage.getText();
    }
}

В тестах это позволяет писать:

const loginPage = new LoginPage();
await loginPage.enterUsername('user123');
await loginPage.submit();
expect(await loginPage.getWelcomeMessage()).toEqual('Добро пожаловать, user123');

Такое разделение повышает читаемость и масштабируемость тестов.

Связь шагов с тестовыми сценариями

Каждый тестовый сценарий представляет собой последовательность шагов. В Protractor для их организации используют структуры describe и it из Jasmine или Mocha:

describe('Авторизация пользователя', () => {
    it('Должна корректно отображать приветствие после входа', async () => {
        await loginPage.enterUsername('user123');
        await loginPage.submit();
        const message = await loginPage.getWelcomeMessage();
        expect(message).toEqual('Добро пожаловать, user123');
    });
});
  • describe группирует тесты по функциональности или модулю.
  • it описывает отдельный сценарий, связывая шаги в логическую последовательность.

Каждый шаг внутри it можно рассматривать как атомарное действие. Нарушение порядка шагов часто приводит к флуктуациям тестов, особенно если тестируется динамическое веб-приложение.

Асинхронность и порядок выполнения

Protractor работает с промисами и async/await, что делает асинхронное выполнение шагов управляемым. Каждый шаг должен завершиться до перехода к следующему:

await element(by.id('username')).sendKeys('user123');
await element(by.id('password')).sendKeys('password123');
await element(by.id('loginButton')).click();

Если забыть await, шаги могут выполняться параллельно, что нарушит логическую связь сценария и вызовет ошибки.

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

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

console.log('Вводим имя пользователя');
await loginPage.enterUsername('user123');

console.log('Нажимаем кнопку входа');
await loginPage.submit();

console.log('Проверяем приветственное сообщение');
expect(await loginPage.getWelcomeMessage()).toEqual('Добро пожаловать, user123');

Такой подход облегчает поиск точек отказа и повышает прозрачность тестового сценария.

Переиспользуемость шагов

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

async function loginAs(username) {
    await loginPage.enterUsername(username);
    await loginPage.submit();
}

Теперь один вызов loginAs('user123') заменяет несколько строк кода в любом тесте.

Интеграция с BDD

При использовании BDD (Cucumber, Gherkin) каждый шаг сценария в Given/When/Then напрямую связывается с функцией Protractor, что обеспечивает чёткую трассируемость шагов до тестового кода:

Given('пользователь на странице входа', async () => {
    await browser.get('/login');
});

When('он вводит имя {string}', async (username) => {
    await loginPage.enterUsername(username);
});

Then('он видит сообщение {string}', async (message) => {
    expect(await loginPage.getWelcomeMessage()).toEqual(message);
});

Каждое действие в сценарии соответствует атомарному шагу, что облегчает поддержку и расширение набора тестов.

Выводы по организации шагов

  • Явная последовательность шагов обеспечивает стабильность тестов.
  • Page Objects и вспомогательные функции отделяют логику действий от сценариев.
  • Асинхронное выполнение через async/await гарантирует правильный порядок.
  • Логирование шагов помогает выявлять проблемы.
  • Переиспользуемость позволяет создавать масштабируемую систему тестов.
  • BDD-интеграция делает связь шагов и тестов очевидной и удобной для анализа.

Эффективная связь шагов с тестами является фундаментом устойчивого и поддерживаемого автоматизированного тестирования в Protractor.