diff --git a/i18n/ru/docusaurus-plugin-content-docs/current/quickstart/index.mdx b/i18n/ru/docusaurus-plugin-content-docs/current/quickstart/index.mdx index de250999..6fa8d256 100644 --- a/i18n/ru/docusaurus-plugin-content-docs/current/quickstart/index.mdx +++ b/i18n/ru/docusaurus-plugin-content-docs/current/quickstart/index.mdx @@ -4,36 +4,59 @@ sidebar_position: 1 import Tabs from "@theme/Tabs"; import TabItem from "@theme/TabItem"; +import Admonition from "@theme/Admonition"; -# Установка {#install} +# Установка и настройка -Запустите установщик testplane с помощью `npm`. +## Системные требования + +Чтобы начать работу с testplane, установите `Node.js` версии 18.0 и выше. + +## Установка {#install} + +Для запуска установщика testplane, с помощью `npm` выполните следующую команду: ```bash npm init testplane@latest YOUR_PROJECT_PATH ``` -Если вы не хотите использовать дефолты при инициализации проекта, а настроить его с помощью визарда, укажите опцию `-v`. +Чтобы настроить проект, а не использовать дефолты при его инициализации, укажите опцию `-v`. + +После выполнения команды установки в директории проекта появится следующий набор файлов и папок: + +```bash +node_modules +testplane-tests + example.testplane.ts + ts.config.json +package-lock.json +package.json +testplane.config.ts +``` ## Настройка {#setup} -После выполнения команды, указанной выше, в корне проекта сгенерится файл `testplane.config.ts` с базовой настройкой. +В файле `testplane.config.ts` содержится базовый набор настроек для запуска тестов: ```typescript export default { - // https://testplane.io/ru/docs/v8/basic-guides/managing-browsers/ gridUrl: "local", baseUrl: "http://localhost", pageLoadTimeout: 0, httpTimeout: 60000, testTimeout: 90000, resetCursor: false, + + // В параметре sets содержится информация о директории, в которой находятся тесты + // и перечень браузеров, в которых они будут запускаться: sets: { desktop: { files: ["testplane-tests/**/*.testplane.(t|j)s"], browsers: ["chrome", "firefox"], }, }, + + // В поле `browsers` описана конфигурация используемых браузеров: browsers: { chrome: { headless: true, @@ -48,9 +71,9 @@ export default { }, }, }, + plugins: { "html-reporter/testplane": { - // https://github.com/gemini-testing/html-reporter enabled: true, path: "testplane-report", defaultView: "all", @@ -60,39 +83,10 @@ export default { }; ``` -Вы можете загрузить браузеры, описанные в конфиге, отдельно от запуска самого Testplane: +Чтобы загрузить браузеры, описанные в конфиге, отдельно от запуска самого Testplane, выполните команду: ```bash npx testplane install-deps ``` Без предварительного запуска команды, недостающие браузеры будут автоматически загружены с первым запуском Testplane. - -## Создание теста {#test_creation} - -Перейдите в файл `tests/example.testplane.js` с тестом. В нем вы можете посмотреть пример теста или написать свой. Например, - -```javascript -describe("github", async function () { - it("should find testplane", async function ({ browser }) { - await browser.url("https://github.com/gemini-testing/testplane"); - const elem = await browser.$("#readme h1"); - - await expect(elem).toHaveText("Testplane"); - }); -}); -``` - -## Запуск теста {#test_running} - -Теперь вы можете запустить тесты: - -```bash -npx testplane -``` - -или запустить gui-режим и запустить тест через интерфейс в браузере - -```bash -npx testplane gui -``` diff --git a/i18n/ru/docusaurus-plugin-content-docs/current/quickstart/running-tests.mdx b/i18n/ru/docusaurus-plugin-content-docs/current/quickstart/running-tests.mdx index 2461ca29..dc1655bb 100644 --- a/i18n/ru/docusaurus-plugin-content-docs/current/quickstart/running-tests.mdx +++ b/i18n/ru/docusaurus-plugin-content-docs/current/quickstart/running-tests.mdx @@ -2,54 +2,174 @@ sidebar_position: 3 --- -# Запуск тестов +# Запуск и отладка -Используйте команду `npx testplane` для запуска всех тестов в вашем проекте. +## Запуск тестов -## Запуск конкретного файла +Для запуска тестов используйте команду: -Если вы хотите запустить всю группу тестов, которые находятся в конкретном файле, то укажите путь к этому файлу в качестве входного параметра для testplane: +```bash +npx testplane +``` + +Также тесты можно запускать в `gui`-режиме, для этого выполните команду: ```bash -testplane src/features/Reviews/Reviews.test/MyReview/MyReview.a11y@touch-phone.testplane.js +npx testplane gui ``` -## Опция `--grep` +### Запуск конкретного теста + +У вас имеется набор тестов, и вам нужно запустить только один из них. + +```javascript +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); + }); +}); +``` -Если же вы хотите запустить конкретный тест, то воспользуйтесь опцией `--grep`, указав в качестве ее значения полное имя теста: +В таком случае выполните команду: ```bash -testplane --grep "Доступность Оставление отзыва" +testplane --grep "Проверка наличия поля поиска" ``` -## Директива `.only` +В кавычках вам необходимо передать содержимое скобок ключевого слова `it`. -Ещё вы можете воспользоваться директивой `.only` для набора тестов `describe` и конкретного теста `it`, аналогично тому как это реализовано в `mocha` (см. раздел [exlusive tests](https://mochajs.org/#exclusive-tests)): +### Запуск тестов в конкретных браузерах -Например: +По умолчанию тесты запускаются в тех браузерах, которые указаны в файле `testplane.config.ts`. ```javascript -describe.only("Доступность", function () { - // набор тестов... -}); +browsers: ["chrome", "firefox"]; +``` + +При выполнении команды `npx testplane` тесты запустятся в браузерах Google Chrome и Mozilla Firefox. + +```bash +# Запуск во всех браузерах (по умолчанию) +testplane +``` + +Чтобы выполнить тесты в конкретном браузере, используйте команду: + +```bash +# Запуск только в Chrome +testplane --browser chrome ``` -или +Также вы можете указать конкретный браузер для работы в теле теста. ```javascript -it.only("Оставление отзыва", async function () { - // код теста... +// tests/browser-specific.test.js +describe("Browser specific tests", () => { + it("should work in all browsers", async ({ browser }) => { + await browser.url("https://example.com"); + }); + + // Пропустить тест в Safari + testplane.skip.in("safari", "Feature not supported in Safari"); + it("should work only in Chrome and Firefox", async ({ browser }) => { + await browser.url("https://example.com"); + // ... тело теста + }); + + // Запустить только в Chrome + testplane.only.in("chrome"); + it("should work only in Chrome", async ({ browser }) => { + await browser.url("https://example.com"); + // ... тело теста + }); }); ``` -## Запуск тестов несколько раз {#running_tests_multiple_times} -Иногда может быть полезным запустить один и тот же тест несколько раз — например, для проверки стабильности. Плагин [@testplane/test-repeater][testplane-test-repeater] позволяет запустить тесты заданное количество раз. +### Запуск теста из конкретного файла -После установки и включения плагина вы можете запустить тесты нужное количество раз, используя следующую команду: +Чтобы запустить тесты из конкретного файла, выполните команду: ```bash -npx testplane --test-repeater-repeat 5 --grep 'Имя теста' +# Запуск конкретного файла +testplane ../testplane-tests/example.testplane.ts +``` + +Где `../testplane-tests/example.testplane.ts` — это путь к файлу с тестами. + +### Режим пользовательского интерфейса + +В Testplane вы можете работать с тестами в UI-формате с помощью Testplane UI. + +![](/img/docs/html-reporter/html-reporter-demo.png) + +О процессах установки и настройки Testplane UI вы можете прочитать в разделе [UI.](..//html-reporter//overview.mdx) + +## Отладка + +### Отладка в gui-формате + +Отслеживать процесс выполнения тестов очень легко, если запустить их в `gui`-режиме. В подобном формате работы html-reporter продемонстрирует, какие тесты были успешно выполнены, а в каких присутствуют ошибки, а также укажет характер этих ошибок. + +![Интерфейс Testplane GUI](/img/docs/guides/testplane-gui.png) + +### Browser.debug() + +В Testplane имеется встроенный инструмент для отладки — `browser.debug`. + +```javascript +it("отладка с паузой", async ({ browser }) => { + // Открываем тестируемую страницу + await browser.url("/page"); + + // browser.debug() останавливает выполнение теста + // и открывает интерактивную консоль (REPL — Read-Eval-Print Loop) + await browser.debug(); + + // После вызова debug() тест приостанавливается + // В консоли можно вводить команды WebdriverIO в реальном времени: + + // Примеры команд, которые можно вводить в REPL: + // > await browser.$('.button').click() - кликнуть по кнопке + // > await browser.getTitle() - получить заголовок страницы + // > await browser.$$('.items') - найти все элементы + // > .exit - выйти из режима отладки + + // Этот код выполнится только после выхода из debug() + await browser.$(".button").click(); +}); ``` -[testplane-test-repeater]: ../../plugins/testplane-test-repeater +### Отладка через Testplane UI + +Наиболее удобным способом для работы с отладкой тестов является UI-режим, в нем вы можете в реальном времени наблюдать выполнение тестов. + +![](/gif/docs/ui/run-debug.gif) + +И находить нестабильные, медленные тесты или другие проблемы с помощью опций «сортировка» и «группировка». + +![](/gif/docs/ui/analytics.gif) diff --git a/i18n/ru/docusaurus-plugin-content-docs/current/quickstart/writing-tests.mdx b/i18n/ru/docusaurus-plugin-content-docs/current/quickstart/writing-tests.mdx index 9b4bed96..01e55b5a 100644 --- a/i18n/ru/docusaurus-plugin-content-docs/current/quickstart/writing-tests.mdx +++ b/i18n/ru/docusaurus-plugin-content-docs/current/quickstart/writing-tests.mdx @@ -5,4 +5,558 @@ draft: true # Написание тестов - +## Структура теста + +Блок `describe` предназначен для группировки связанных тестов. + +```javascript +describe("Название группы тестов", () => { + it("описание того, что должно произойти", async ({ browser }) => { + // Тело теста + }); +}); +``` + +В блоке `it` описываются тестовые сценарии. + +```javascript +it("описание того, что должно произойти", async ({ browser }) => { + // Тело теста +}); +``` + +После установки testplane вы можете ознакомиться с примером теста, для этого перейдите в папку `testplane-tests` и откройте файл `example.testplane.ts`. + +```javascript +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); + }); +}); +``` + +## Базовый синтаксис + +### Навигация + +Для перемещения по страницам используйте метод: + +```javascript +await browser.url("https://testplane.io/ru/"); +``` + +Если на странице имеются элементы, которые отображаются с задержкой, для корректного выполнения тестов укажите явное ожидание: + +```javascript +await browser.url("https://testplane.io/ru/"); +await browser.$("h1").waitForExist({ timeout: 5000 }); +const title = await browser.$("h1").getText(); +``` + +Либо используйте команду: + +```javascript +await browser.openAndWait("https://testplane.io/ru/"); +``` + +Команда `await browser.openAndWait()` по умолчанию дожидается загрузки всех необходимых элементов на странице. + +### Селекторы + +Testplane поддерживает различные стратегии поиска элементов: `CSS`-селекторы (самые распространенные), текстовые селекторы (по содержимому), `XPath` для сложных запросов. Метод `$()` возвращает первый найденный элемент, а `$$()` — массив всех подходящих элементов: + +```javascript +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); + }); +}); +``` + +### Взаимодействия с элементами + +После знакомства с селекторами и нахождения элемента можно выполнить различные действия: клик, ввод текста, двойной клик. + +```javascript +const assert = require("assert"); + +describe("tests, () => { + + it("Пример клика — открытие поиска", async ({browser}) => { + await browser.url("https://testplane.io/ru/"); + + // Клик по кнопке поиска + const searchButton = await browser.$("button.DocSearch"); + await searchButton.waitForClickable({timeout: 5000}); + await searchButton.click(); + await browser.pause(1000); + + // Проверяем, что модальное окно поиска появилось + const searchModal = await browser.$(".DocSearch-Modal"); + const isDisplayed = await searchModal.isDisplayed(); + assert.strictEqual(isDisplayed, true); + }); + + it("Пример ввода текста — поиск по документации", async ({browser}) => { + await browser.url("https://testplane.io/ru/"); + + // Открываем поиск + const searchButton = await browser.$("button.DocSearch"); + await searchButton.waitForClickable({timeout: 5000}); + await searchButton.click(); + await browser.pause(500); + + // Вводим текст в поле поиска + const searchInput = await browser.$("input.DocSearch-Input"); + await searchInput.waitForDisplayed({timeout: 5000}); + await searchInput.setValue("browser"); + await browser.pause(1000); + + // Проверяем, что текст введен + const inputValue = await searchInput.getValue(); + assert.strictEqual(inputValue, "browser"); + }); + + it("Пример двойного клика — выделение текста заголовка", async ({browser}) => { + await browser.url("https://testplane.io/ru/"); + + // Находим заголовок на главной странице + const heading = await browser.$("h1"); + await heading.waitForDisplayed({timeout: 5000}); + await heading.scrollIntoView(); + await browser.pause(500); + + // Двойной клик по заголовку + await heading.doubleClick(); + await browser.pause(500); + + // Проверяем, что элемент существует и отображается + const isDisplayed = await heading.isDisplayed(); + assert.strictEqual(isDisplayed, true); + }); +}); +``` + +### Assertions + +Testplane задействует `expect API` из `WebdriverIO` для проверки состояния элементов и страниц — это позволяет формулировать утверждения (`assertions`) о том, какими должны быть свойства элементов или страницы в целом. + +```javascript +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`, первый выполняется перед каждым тестом, а второй — после. + +```javascript +const assert = require("assert"); + +describe("Примеры работы с хуками", () => { + // beforeEach — выполняется перед каждым тестом + beforeEach(async ({ browser }) => { + console.log("--- Выполняется BEFOREEACH — перед каждым тестом ---"); + await browser.url("https://testplane.io/ru/"); + await browser.pause(500); + }); + + // afterEach — выполняется после каждого теста + afterEach(async ({ browser }) => { + console.log("--- Выполняется AFTEREACH — после каждого теста ---"); + const currentUrl = await browser.getUrl(); + console.log("Текущий URL:", currentUrl); + // Можно делать скриншоты, очищать данные и т.д. + }); + + it("Тест 1 — проверка заголовка", async ({ browser }) => { + const title = await browser.getTitle(); + assert.ok(title.includes("Testplane")); + }); + + it("Тест 2 — проверка логотипа", async ({ browser }) => { + const logo = await browser.$("a.navbar__brand"); + const isDisplayed = await logo.isDisplayed(); + assert.strictEqual(isDisplayed, true); + }); + + it("Тест 3 — проверка поиска", async ({ browser }) => { + const searchButton = await browser.$("button.DocSearch"); + const isExisting = await searchButton.isExisting(); + assert.strictEqual(isExisting, true); + }); +}); + +describe("Пример вложенных 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 автоматически ждет появления элементов, но для сложных сценариев можно использовать специальные методы ожидания. + +```javascript +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")); + }); +}); +``` + +### Работа с формами + +Testplane предоставляет специальные методы для работы с различными элементами форм. Чекбоксы и радиокнопки управляются через клик. Для выпадающих списков `(