Написание тестов
Структура теста
Блок 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);
});
});