Использование таблиц данных в Protractor позволяет организовать тестовые сценарии более эффективно, обеспечивая многоразовость и масштабируемость автоматизированных тестов. Таблицы данных — это структура, в которой хранятся входные данные и ожидаемые результаты для различных вариантов тестирования одного и того же функционала.
В Protractor таблицы данных обычно реализуются в виде массивов объектов JavaScript или внешних файлов (JSON, CSV, Excel), которые затем импортируются в тесты. Такой подход обеспечивает отделение данных от логики теста, что упрощает поддержку и расширение сценариев.
Пример простой таблицы данных:
const loginData = [
{ username: 'user1', password: 'pass1', expectedResult: 'success' },
{ username: 'user2', password: 'wrongpass', expectedResult: 'failure' },
{ username: '', password: '', expectedResult: 'failure' }
];
Каждый объект в массиве соответствует одной комбинации данных для теста.
it и forEachДля применения таблиц данных в сценариях используется перебор массива с генерацией тестов динамически. Это позволяет создавать параметризованные тесты без дублирования кода.
loginData.forEach(data => {
it(`should login with username: ${data.username}`, async () => {
await element(by.id('username')).sendKeys(data.username);
await element(by.id('password')).sendKeys(data.password);
await element(by.id('loginButton')).click();
if (data.expectedResult === 'success') {
expect(await element(by.id('welcomeMessage')).isPresent()).toBe(true);
} else {
expect(await element(by.id('errorMessage')).isPresent()).toBe(true);
}
});
});
Ключевой момент: каждое значение из таблицы автоматически подставляется в тест, что упрощает проверку большого числа комбинаций.
Для больших проектов часто применяются внешние файлы с данными. Наиболее популярны форматы JSON и CSV.
JSON пример:
loginData.json
[
{ "username": "user1", "password": "pass1", "expectedResult": "success" },
{ "username": "user2", "password": "wrongpass", "expectedResult": "failure" }
]
Импорт в тест:
const loginData = require('./loginData.json');
loginData.forEach(data => {
it(`should login with username: ${data.username}`, async () => {
await element(by.id('username')).sendKeys(data.username);
await element(by.id('password')).sendKeys(data.password);
await element(by.id('loginButton')).click();
if (data.expectedResult === 'success') {
expect(await element(by.id('welcomeMessage')).isPresent()).toBe(true);
} else {
expect(await element(by.id('errorMessage')).isPresent()).toBe(true);
}
});
});
Использование внешних файлов облегчает поддержку тестов и позволяет хранить таблицы данных отдельно от кода.
Таблицы данных применяются не только для простых форм, но и для комплексных сценариев, где требуется несколько шагов с разными входными данными.
Пример сценария с формой регистрации:
const registrationData = [
{ name: 'Alice', email: 'alice@example.com', password: '12345', role: 'admin' },
{ name: 'Bob', email: 'bob@example.com', password: 'abcde', role: 'user' }
];
registrationData.forEach(data => {
it(`should register user ${data.name} with role ${data.role}`, async () => {
await element(by.id('name')).sendKeys(data.name);
await element(by.id('email')).sendKeys(data.email);
await element(by.id('password')).sendKeys(data.password);
await element(by.id('role')).sendKeys(data.role);
await element(by.id('registerButton')).click();
const successMessage = await element(by.id('successMessage')).getText();
expect(successMessage).toContain(data.name);
});
});
Преимущество: один сценарий охватывает множество комбинаций данных, сокращая количество повторяющихся тестов и повышая читаемость кода.
Для некоторых тестов заранее известные данные не подходят, и их необходимо генерировать во время выполнения. Для этого применяются функции генерации случайных значений:
function generateRandomUser() {
const id = Math.floor(Math.random() * 1000);
return { username: `user${id}`, password: `pass${id}`, expectedResult: 'success' };
}
const dynamicData = Array.from({ length: 5 }, generateRandomUser);
dynamicData.forEach(data => {
it(`should login with dynamically generated user: ${data.username}`, async () => {
await element(by.id('username')).sendKeys(data.username);
await element(by.id('password')).sendKeys(data.password);
await element(by.id('loginButton')).click();
expect(await element(by.id('welcomeMessage')).isPresent()).toBe(true);
});
});
Такой подход особенно полезен для тестирования масштабируемости и устойчивости приложения при большом объёме пользователей.
Для улучшения структуры тестов таблицы данных часто комбинируются с Page Object Model (POM). Это позволяет отделить логику взаимодействия с интерфейсом от данных теста.
Пример использования Page Object с таблицей данных:
loginPage.js
class LoginPage {
constructor() {
this.usernameField = element(by.id('username'));
this.passwordField = element(by.id('password'));
this.loginButton = element(by.id('loginButton'));
this.welcomeMessage = element(by.id('welcomeMessage'));
this.errorMessage = element(by.id('errorMessage'));
}
async login(username, password) {
await this.usernameField.sendKeys(username);
await this.passwordField.sendKeys(password);
await this.loginButton.click();
}
async isSuccess() {
return this.welcomeMessage.isPresent();
}
async isFailure() {
return this.errorMessage.isPresent();
}
}
module.exports = new LoginPage();
login.spec.js
const loginData = require('./loginData.json');
const loginPage = require('./loginPage');
loginData.forEach(data => {
it(`should login with username: ${data.username}`, async () => {
await loginPage.login(data.username, data.password);
if (data.expectedResult === 'success') {
expect(await loginPage.isSuccess()).toBe(true);
} else {
expect(await loginPage.isFailure()).toBe(true);
}
});
});
Использование POM вместе с таблицами данных делает код чистым, читаемым и легко расширяемым.
Таблицы данных в сценариях Protractor обеспечивают масштабируемость тестов, удобство поддержки и снижение дублирования кода, делая автоматизацию более эффективной и структурированной.