Skip to content

Commit

Permalink
Merge pull request #24 from gemini-testing/docs.component-testing
Browse files Browse the repository at this point in the history
docs: describe component testing guide
  • Loading branch information
DudaGod authored Aug 14, 2024
2 parents ad008b1 + 361156e commit b5b4ada
Show file tree
Hide file tree
Showing 6 changed files with 347 additions and 267 deletions.
134 changes: 1 addition & 133 deletions blog/component-testing.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -38,139 +38,7 @@ import Admonition from "@theme/Admonition";

### Как использовать?

Будем настраивать тестирование react-компонентов, написанных на TypeScript. Поэтому, для начала установим необходимые зависимости:

```bash
npm i testplane vite @vitejs/plugin-react @testing-library/react --save-dev
npm i react --save
```

Создаем Vite конфиг, в котором подключим плагин для поддержки React. Пример:

```javascript
// vite.config.ts
import { defineConfig } from "vite";
import react from "@vitejs/plugin-react";

export default defineConfig({
plugins: [react()],
});
```

Теперь настроим запуск тестов в браузере. Для этого укажем опцию [testRunEnv](https://github.com/gemini-testing/testplane/blob/master/docs/config.md#testrunenv). Пример:

```javascript
// .testplane.conf.ts
export const {
// ...
system: {
// ...
testRunEnv: ['browser', { viteConfig: './vite.config.ts' }],
},
sets: {
linux: {
files: [
'src/tests/**/*.testplane.tsx'
],
browsers: [
'chrome'
]
},
},
}
```

После чего можем написать тест, в котором просто выведем значение `document` в консоль без использования команды [browser.execute](/docs/v8/commands/browser/execute):

```javascript
// src/tests/test.testplane.tsx
it("should log document", async () => {
console.log(document);
});
```

Если бы такой тест выполнялся в окружении Node.js, то он бы упал с ошибкой `ReferenceError: document is not defined`. Но в нашем случае он будет выполнен прямо в браузере, где доступна глобальная переменная `document`. Поэтому, в логе браузера и терминала (про эту возможность расскажем ниже) мы увидим следующее:

```
{
location: {
ancestorOrigins: {},
href: 'http://localhost:56292/run-uuids/23d2af81-4259-425c-8214-c9e770d75ea4',
origin: 'http://localhost:56292',
protocol: 'http:',
host: 'localhost:56292',
hostname: 'localhost',
port: '56292',
pathname: '/run-uuids/23d2af81-4259-425c-8214-c9e770d75ea4',
search: '',
hash: ''
}
}
```

Напишем более сложный тест с рендерингом React-компонента. Для этого сначала напишем небольшой компонент:

```javascript
// src/components/Component.tsx
import { useState } from "react";

// Простой компонент с тайтлом и кнопкой-счетчиком
function Component() {
const [count, setCount] = useState(0);

return (
<div id="root">
<h1>Testplane Component Testing!</h1>
<button onClick={() => setCount(count => count + 1)}>count is {count}</button>
</div>
);
}

export default Component;
```

И напишем сам тест, который будет тестировать наш React-компонент:

```javascript
// src/tests/test.testplane.tsx
import { render } from "@testing-library/react";
import Component from "../components/Component";

it("should render react button", async ({ browser }) => {
render(<Component />); // рендерим компонент на сгенеренной странице Vite

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

await button.click();
await button.click();

await expect(button).toHaveText("count is 2");
});
```

С полноценно работающими примерами можно ознакомиться [здесь](https://github.com/gemini-testing/testplane/tree/master/examples/component-testing).

<Admonition type="warning" title="На данный момент есть ограничения">
- поддерживаются только компоненты, написанные на React в файлах `.jsx` и `.tsx`. Поддержка Vue
также есть в планах; - нет доступа к `currentTest` из хуков и теста; - временно не
поддерживается плагин @testplane/global-hook.
</Admonition>

### Какие дополнительные возможности поддерживаются?

#### 1. Hot Module Replacement (HMR)

В Vite поддерживается [HMR](https://vitejs.dev/guide/api-hmr.html). Это означает, что если изменить загруженный файл, то произойдет или ремаунт компонента, или полная перезагрузка страницы. В случае, если компонент описан в отдельном файле (т.е. не в одном файле с тестом), то будет выполнен ремаунт, но тест перезапущен не будет. А если изменить файл с тестом, то произойдет перезагрузка страницы, которая приведет к тому, что Testplane прервет выполнение текущего теста и запустит его заново. За счет такой возможности в Vite можно очень быстро разрабатывать компоненты и писать для них тесты. Рекомендуется использовать вместе с REPL-режимом.

При изменении исходников компонента не происходит полного перезапуска теста (маунтится по новой только сам компонент). При этом, если изменить код теста, то происходит полный перезапуск.

#### 2. Использование инстанса browser и expect прямо в DevTools браузера

В консоли браузера, в котором выполняется тест, доступны инстанс самого `browser` и инстанс `expect`. Это довольно удобно использовать при дебаге теста.

#### 3. Логи из консоли браузера в терминале

Вызов команд `log`, `info`, `warn`, `error`, `debug` и `table` на объекте `console` в браузере приводят к тому, что отображается информация не только в DevTools браузера, но также и в терминале, из которого был запущен Testplane. Т.е. можно вызвать `console.log` в тесте/компоненте и затем увидеть результат его выполнения в терминале. Это также довольно удобно при дебаге теста.
Узнайте больше об этом в нашей документации <a href="/docs/v8/guides/component-testing">Компонентное тестирование</a>.

### Заключение

Expand Down
1 change: 1 addition & 0 deletions docs/config/system.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ import TestRunEnvExample from "@site/docs/config/_partials/examples/_system-test
<tr><td>[`diffColor`](#diff_color)</td><td>`string`</td><td>`"#ff00ff"`</td><td>Цвет, которым нужно отображать дифф на скриншотах.</td></tr>
<tr><td>[`parallelLimit`](#parallel_limit)</td><td>`number`</td><td>`1`</td><td>Максимальное количество браузеров, которые могут быть запущены одновременно.</td></tr>
<tr><td>[`fileExtensions`](#file_extensions)</td><td>`string[]`</td><td>`[".js", ".mjs", ".ts", ".mts", ".jsx", ".tsx"]`</td><td>Расширения файлов, в которых Testplane будет искать тесты для запуска.</td></tr>
<tr><td>[`testRunEnv`](#testrunenv)</td><td>`nodejs` или `browser` или `Array`</td><td>`nodejs`</td><td>Возможно указать в каком окружении должны выполняться тесты.</td></tr>
</tbody>
</table>

Expand Down
168 changes: 168 additions & 0 deletions docs/guides/component-testing.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,168 @@
import Admonition from "@theme/Admonition";

# Компонентное тестирование (экспериментальное)

## Введение

Узнайте больше об этом в посте про <a href="/blog/component-testing-intro">Компонентное тестирование</a> в нашем блоге.

## Пример

```typescript
import { render } from '@testing-library/react';
import Component from '../Component';

it('should render react component', async ({browser}) => {
// Отрендерить компонент на изолированной странице
render(<Component />);

// Найти кнопку внутри компонента и кликнуть по ней
const button = await browser.$("button");
await button.click();

// Проверить, что текст кнопки имеет ожидаемое значение
await expect(button).toHaveText("count is 1");
});
```

## Как начать?

Давайте настроим тестирование реакт компонентов, написанных на Typescript.

### Шаг 1: Установка Testplane и необходимых зависимостей

```bash
npm init testplane@latest
npm i vite @vitejs/plugin-react @testing-library/react --save-dev
npm i react --save
```

### Шаг 2: Создание конфигурации Vite и подключение плагина react

```typescript title="vite.config.ts"
import { defineConfig } from "vite";
import react from "@vitejs/plugin-react";

export default defineConfig({
plugins: [react()],
});
```

### Шаг 3: Настройка запуска тестов в браузере (используя опцию testRunEnv)

```typescript title=".testplane.conf.ts"
export default {
// ...
system: {
// ...
testRunEnv: ["browser", { viteConfig: "./vite.config.ts" }],
},
sets: {
linux: {
files: ["src/tests/**/*.testplane.tsx"],
browsers: ["chrome"],
},
},
};
```

### Шаг 4: Написание теста

Чтобы проверить правильную конфигурацию, мы можем написать самый простой тест, в котором выводим значение document в консоль без использования команды [browser.execute][browser-execute]:

```typescript title="src/tests/test.testplane.tsx"
it("should log document", async () => {
console.log(document);
});
```

Если бы такой тест был выполнен в среде Node.js, то он упал бы с ошибкой: `ReferenceError: document is not defined`. Но в нашем случае он будет выполнен непосредственно в браузере, где глобальная переменная `document` доступна. Поэтому в консоли браузера и терминала мы увидим следующее:

```
{
location: {
ancestorOrigins: {},
href: 'http://localhost:56292/run-uuids/23d2af81-4259-425c-8214-c9e770d75ea4',
origin: 'http://localhost:56292',
protocol: 'http:',
host: 'localhost:56292',
hostname: 'localhost',
port: '56292',
pathname: '/run-uuids/23d2af81-4259-425c-8214-c9e770d75ea4',
search: '',
hash: ''
}
}
```

Давайте напишем более сложный тест с рендером компонента:

```typescript title="src/tests/test.testplane.tsx"
import { render } from '@testing-library/react';
import Component from '../Component';

it('should render react component', async ({browser}) => {
// Отрендерить компонент на изолированной странице
render(<Component />);

// Найти кнопку внутри компонента и кликнуть по ней
const button = await browser.$("button");
await button.click();

// Проверить, что текст кнопки имеет ожидаемое значение
await expect(button).toHaveText("count is 1");
});
```

И исходный код самого компонента:

```typescript title="src/Component.tsx"
import { useState } from 'react';

// A simple component with a title and a counter button
function Component() {
const [count, setCount] = useState(0);

return (
<div id="root">
<h1>Testplane Component Testing</h1>
<button onClick={() => setCount((count) => count + 1)}>
count is {count}
</button>
</div>
);
}
```

Полностью работающие примеры можно найти [здесь][testplane-examples-component-testing].

## Временные ограничения

<Admonition type="warning">
* поддерживаются только компоненты, написанные на React в файлах .jsx и .tsx. Возможность
написания тестов в файлах .js будет реализована в ближайшем будущем. Мы также планируем
поддержку фреймворка Vue; * нет доступа к currentTest из it, beforeEach и afterEach. Это будет
добавлено в ближайшем будущем; * плагин [@testplane/global-hook][testplane-global-hook] в
настоящее время временно не поддерживается.
</Admonition>

## Дополнительные возможности

### Горячая замена модулей (HMR)

[HMR][vite-hmr] поддерживается в Vite. Это означает, что если вы измените загруженный файл, либо компонент будет повторно монтироваться, либо страница будет полностью предварительно загружена. Если компонент описан в отдельном файле (т.е. не в том же файле, что и тест), произойдет повторная установка, но тест не будет перезапущен. А если вы измените файл теста, страница будет перезагружена, что заставит Testplane прервать выполнение текущего теста и запустить его заново. Благодаря этой функции вы можете быстро разрабатывать компоненты в Vite и писать для них тесты. Рекомендуется использовать ее вместе с [REPL режимом][repl-mode].

### Использование экземпляров browser и expect напрямую в средствах разработчика браузера

Инстансы `browser` и `expect` доступны в глобальной области видимости браузера. Это довольно удобно использовать при отладке теста.

### Логи из консоли браузера в терминале

Вызов команд `log`, `info`, `warn`, `error`, `debug` и `table` на объекте `console` в браузере приводит к отображению информации не только в средствах разработчика браузера, но также в терминале, из которого был запущен Testplane. То есть, вы можете вызывать `console.log` в тесте/компоненте и увидеть результат его выполнения в терминале. Это особенно удобно при отладке тестов.

[test-run-env-option]: ../config/system.mdx#testrunenv
[browser-execute]: ../commands/browser/execute.mdx
[testplane-examples-component-testing]: https://github.com/gemini-testing/testplane/tree/master/examples/component-testing
[testplane-global-hook]: https://github.com/gemini-testing/testplane-global-hook
[vite-hmr]: https://vitejs.dev/guide/api-hmr.html
[repl-mode]: ../command-line/index.mdx#repl
Loading

0 comments on commit b5b4ada

Please sign in to comment.