Перейти к основному содержимому

Написание тестов

Структура теста

Блок describe предназначен для группировки связанных тестов.

describe("Название группы тестов", () => {
it("описание того, что должно произойти", async ({ browser }) => {
// Тело теста
});
});

В блоке it описываются тестовые сценарии.

it("описание того, что должно произойти", async ({ browser }) => {
// Тело теста
});

После установки testplane вы можете ознакомиться с примером теста, для этого перейдите в папку testplane-tests и откройте файл example.testplane.ts.

describe("test examples", () => {
it("docs search test", async ({ browser }) => {
await browser.openAndWait("https://testplane.io/");

// Find by tag name
const navBar = await browser.$("nav");

// Find by aria-label
await navBar.$("aria/Search").click();

// Find by placeholder
const fileSearchInput = await browser.findByPlaceholderText("Search docs");
await fileSearchInput.waitForDisplayed();
await fileSearchInput.setValue("config");

// Find by id
const fileSearchResults = await browser.$("#docsearch-list");

// Find by role
const fileSearchResultsItems = await fileSearchResults.findAllByRole("option");

await expect(fileSearchResultsItems.length).toBeGreaterThan(1);
});
});

Базовый синтаксис

Навигация

Для перемещения по страницам используйте метод:

await browser.url("https://testplane.io/ru/");

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

await browser.url("https://testplane.io/ru/");
await browser.$("h1").waitForExist({ timeout: 5000 });
const title = await browser.$("h1").getText();

Либо используйте команду:

await browser.openAndWait("https://testplane.io/ru/");

Команда await browser.openAndWait() по умолчанию дожидается загрузки всех необходимых элементов на странице.

Селекторы

Testplane поддерживает различные стратегии поиска элементов: CSS-селекторы (самые распространенные), текстовые селекторы (по содержимому), XPath для сложных запросов. Метод $() возвращает первый найденный элемент, а $$() — массив всех подходящих элементов:

const assert = require("assert");

describe("tests", () => {
it("Проверка отображения главной страницы", async ({ browser }) => {
await browser.url("https://testplane.io/ru/");
const title = await browser.getTitle();
assert.ok(title.includes("Testplane"));
});

it("Проверка наличия логотипа на главной странице", async ({ browser }) => {
await browser.url("https://testplane.io/ru/");
const logo = await browser.$("a.navbar__brand");
const isDisplayed = await logo.isDisplayed();
assert.strictEqual(isDisplayed, true);
});

it("Проверка навигационного меню", async ({ browser }) => {
await browser.url("https://testplane.io/ru/");
const menuItems = await browser.$$("nav.navbar a.navbar__item");
assert.ok(menuItems.length > 0);
});

it("Проверка наличия поля поиска", async ({ browser }) => {
await browser.url("https://testplane.io/ru/");
const searchButton = await browser.$("button.DocSearch");
const isExisting = await searchButton.isExisting();
assert.strictEqual(isExisting, true);
});
});

Взаимодействия с элементами

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

Для клика по элементу используйте метод element.click().

const assert = require("assert");

describe("Тест клика", () => {
it("Пример клика — открытие поиска", async ({ browser }) => {
await browser.url("https://testplane.io/ru/");

// Клик по кнопке поиска
const searchButton = await browser.$("button.DocSearch");
await searchButton.waitForClickable({ timeout: 5000 });
await searchButton.click();

// Проверяем, что модальное окно поиска появилось
const searchModal = await browser.$(".DocSearch-Modal");
const isDisplayed = await searchModal.isDisplayed();
assert.strictEqual(isDisplayed, true);
});
});

Чтобы заполнить поле для ввода текста используйте метод element.setValue("text").

const assert = require("assert");

describe("Тест ввода текста", () => {
it("Пример ввода текста — поиск по документации", async ({ browser }) => {
await browser.url("https://testplane.io/ru/");

// Открываем поиск
const searchButton = await browser.$("button.DocSearch");
await searchButton.waitForClickable({ timeout: 5000 });
await searchButton.click();

// Вводим текст в поле поиска
const searchInput = await browser.$("input.DocSearch-Input");
await searchInput.waitForDisplayed({ timeout: 5000 });
await searchInput.setValue("browser");

// Проверяем, что текст введен
const inputValue = await searchInput.getValue();
assert.strictEqual(inputValue, "browser");
});
});

Для двойного клика по элементу используйте метод element.doubleClick().

const assert = require("assert");

describe("Тест двойного клика", () => {
it("Пример двойного клика — выделение текста заголовка", async ({ browser }) => {
await browser.url("https://testplane.io/ru/");

// Находим заголовок на главной странице
const heading = await browser.$("h1");
await heading.waitForDisplayed({ timeout: 5000 });
await heading.scrollIntoView();

// Двойной клик по заголовку
await heading.doubleClick();

// Проверяем, что элемент существует и отображается
const isDisplayed = await heading.isDisplayed();
assert.strictEqual(isDisplayed, true);
});
});

Testplane предоставляет специальные методы для работы с различными элементами форм. Например, чекбоксы и радиокнопки управляются через клик.

const assert = require("assert");

describe("Взаимодействие с формами", () => {
it("Работа с чекбоксами через клик", async ({ browser }) => {
// Для демонстрации используем страницу с формой
await browser.url("https://the-internet.herokuapp.com/checkboxes");

const checkbox1 = await browser.$("#checkboxes input:nth-child(1)");
await checkbox1.waitForDisplayed({ timeout: 5000 });

// Проверяем начальное состояние
let isSelected = await checkbox1.isSelected();
assert.strictEqual(isSelected, false);

// Кликаем для выбора
await checkbox1.click();
isSelected = await checkbox1.isSelected();
assert.strictEqual(isSelected, true);

// Кликаем еще раз для снятия выбора
await checkbox1.click();
isSelected = await checkbox1.isSelected();
assert.strictEqual(isSelected, false);
});

it("Работа с радиокнопками через клик", async ({ browser }) => {
await browser.url("https://the-internet.herokuapp.com/");

// Переходим на страницу с примерами
const link = await browser.$("a[href='/forgot_password']");
await link.click();

// Работа с полем email (как пример радиокнопок)
const emailInput = await browser.$("#email");
await emailInput.waitForDisplayed({ timeout: 5000 });
await emailInput.setValue("test@example.com");

const value = await emailInput.getValue();
assert.ok(value.includes("test@example.com"));
});
});

Для выпадающих списков (<select>) есть удобные методы выбора опций по видимому тексту или значению атрибута.

const assert = require("assert");

describe("Работа с выпадающим списком", () => {
it("Работа с выпадающим списком (select) — выбор по тексту", async ({ browser }) => {
await browser.url("https://the-internet.herokuapp.com/dropdown");

const dropdown = await browser.$("#dropdown");
await dropdown.waitForDisplayed({ timeout: 5000 });

// Выбор опции по видимому тексту
await dropdown.selectByVisibleText("Option 1");

// Проверяем выбранное значение
let selectedValue = await dropdown.getValue();
assert.strictEqual(selectedValue, "1");

// Получаем текст выбранной опции
let selectedText = await dropdown.$("option:checked").getText();
assert.strictEqual(selectedText, "Option 1");
});
});

Assertions

Testplane задействует expect API из WebdriverIO для проверки состояния элементов и страниц — это позволяет формулировать утверждения (assertions) о том, какими должны быть свойства элементов или страницы в целом.

const assert = require("assert");

describe("tests", () => {
it("WebdriverIO assert — проверка URL", async ({ browser }) => {
await browser.url("https://testplane.io/ru/");

// WebdriverIO expect для browser
await expect(browser).toHaveUrl("https://testplane.io/ru/");
});

it("WebdriverIO assert — проверка существования элемента", async ({ browser }) => {
await browser.url("https://testplane.io/ru/");

const logo = await browser.$("a.navbar__brand");

// WebdriverIO expect для элемента
await expect(logo).toExist();
});

it("WebdriverIO assert — проверка видимости элемента", async ({ browser }) => {
await browser.url("https://testplane.io/ru/");

const searchButton = await browser.$("button.DocSearch");

// WebdriverIO expect
await expect(searchButton).toBeDisplayed();
});

// Примеры с Jest ассертами
it("Jest assert — проверка заголовка страницы", async ({ browser }) => {
await browser.url("https://testplane.io/ru/");

const title = await browser.getTitle();

// Jest expect
expect(title).toContain("Testplane");
});

it("Jest assert — проверка количества элементов", async ({ browser }) => {
await browser.url("https://testplane.io/ru/");

const menuItems = await browser.$$("nav.navbar a.navbar__item");

// Jest expect
expect(menuItems.length).toBeGreaterThan(0);
});

it("Jest assert — проверка атрибута элемента", async ({ browser }) => {
await browser.url("https://testplane.io/ru/");

const docsLink = await browser.$("a[href='/ru/docs/v8/']");
const href = await docsLink.getAttribute("href");

// Jest expect
expect(href).toBe("/ru/docs/v8/");
});

it("Jest assert — проверка URL с регулярным выражением", async ({ browser }) => {
await browser.url("https://testplane.io/ru/");

const currentUrl = await browser.getUrl();

// Jest expect с regex
expect(currentUrl).toMatch(/testplane\.io/);
});
});

Хуки

Хуки — это специальные функции, которые автоматически выполняются в определенные моменты жизненного цикла тестов. Они позволяют подготовить окружение перед тестами и очистить его после выполнения. По умолчанию доступны два вида хуков — beforeEach и afterEach, первый выполняется перед каждым тестом, а второй — после.

const assert = require("assert");

describe("Пример работы с хуками", () => {
beforeEach(async ({ browser }) => {
console.log("--- OUTER BEFOREEACH ---");
await browser.url("https://testplane.io/ru/");
});

afterEach(async ({ browser }) => {
console.log("--- OUTER AFTEREACH ---");
});

it("Внешний тест", async ({ browser }) => {
const title = await browser.getTitle();
assert.ok(title.length > 0);
});

describe("Внутренний блок тестов", () => {
beforeEach(async ({ browser }) => {
console.log("--- INNER BEFOREEACH ---");
// Сначала выполнится outer beforeEach, потом этот
await browser.url("https://testplane.io/ru/docs/v8/");
});

afterEach(async ({ browser }) => {
console.log("--- INNER AFTEREACH ---");
// Сначала выполнится этот afterEach, потом outer
});

it("Внутренний тест 1", async ({ browser }) => {
const currentUrl = await browser.getUrl();
assert.ok(currentUrl.includes("docs"));
});

it("Внутренний тест 2", async ({ browser }) => {
const heading = await browser.$("h1");
const isDisplayed = await heading.isDisplayed();
assert.strictEqual(isDisplayed, true);
});
});
});

Ожидания

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

const assert = require("assert");

describe("Примеры ожиданий в Testplane", () => {
it("Ожидание появления и кликабельности элемента", async ({ browser }) => {
await browser.url("https://testplane.io/ru/");

// Ожидаем, что кнопка поиска появится на странице
const searchButton = await browser.$("button.DocSearch");
await searchButton.waitForDisplayed({
timeout: 5000,
timeoutMsg: "Кнопка поиска не появилась в течение 5 секунд",
});

// Ожидаем, что элемент станет кликабельным
await searchButton.waitForClickable({
timeout: 3000,
timeoutMsg: "Кнопка поиска не стала кликабельной",
});

await searchButton.click();

// Ожидаем появления модального окна поиска
const searchModal = await browser.$(".DocSearch-Modal");
await searchModal.waitForDisplayed({ timeout: 3000 });

const isDisplayed = await searchModal.isDisplayed();
assert.strictEqual(isDisplayed, true);
});

it("Ожидание изменения текста элемента", async ({ browser }) => {
await browser.url("https://testplane.io/ru/");

const heading = await browser.$("h1");

// Ожидаем, что элемент будет существовать
await heading.waitForExist({
timeout: 5000,
timeoutMsg: "Заголовок не найден на странице",
});

// Ожидаем, что у элемента будет определенный текст
await heading.waitUntil(
async function () {
const text = await this.getText();
return text.length > 0;
},
{
timeout: 5000,
timeoutMsg: "Текст заголовка не появился",
},
);

const text = await heading.getText();
assert.ok(text.length > 0);
});

it("Ожидание с использованием browser.waitUntil для проверки URL", async ({ browser }) => {
await browser.url("https://testplane.io/ru/");

const docsLink = await browser.$("a[href='/ru/docs/v8/']");
await docsLink.waitForExist({ timeout: 5000 });

// Используем JavaScript click для надежности
await browser.execute(el => el.click(), docsLink);

// Ожидаем изменения URL с помощью browser.waitUntil
await browser.waitUntil(
async () => {
const currentUrl = await browser.getUrl();
return currentUrl.includes("docs");
},
{
timeout: 5000,
timeoutMsg: "URL не изменился на страницу документации",
},
);

const finalUrl = await browser.getUrl();
assert.ok(finalUrl.includes("docs"));
});
});

Работа с JavaScript кодом

Иногда нужно выполнить произвольный JavaScript-код в контексте страницы — например, для работы с localStorage, вызова функций или манипуляции DOM напрямую. Метод execute() выполняет код в браузере и может возвращать результат.

const assert = require("assert");

describe("Примеры работы с JavaScript кодом", () => {
it("Выполнение JavaScript кода в контексте страницы", async ({ browser }) => {
await browser.url("https://testplane.io/ru/");

// Пример 1: Получение данных из localStorage
await browser.execute(() => {
localStorage.setItem("testKey", "testValue");
localStorage.setItem("userName", "John Doe");
});

const storageValue = await browser.execute(() => {
return localStorage.getItem("testKey");
});
assert.strictEqual(storageValue, "testValue");

// Пример 2: Манипуляция DOM — изменение текста элемента
const newText = await browser.execute(() => {
const heading = document.querySelector("h1");
if (heading) {
const originalText = heading.textContent;
heading.textContent = "Измененный заголовок";
return originalText;
}
return "";
});

const modifiedHeading = await browser.$("h1");
const currentText = await modifiedHeading.getText();
assert.strictEqual(currentText, "Измененный заголовок");

// Пример 3: Вызов функции с параметрами
const sum = await browser.execute(
(a, b) => {
return a + b;
},
5,
10,
);
assert.strictEqual(sum, 15);
});
});