Haramaki0326 / StudyToDo

2021年にチャレンジ、やりたいことリスト
0 stars 0 forks source link

フロントエンドのテストについて(ユニットテスト(Jest),スナップショットテスト(Jest), Integrationテスト(react-testing-library), E2Eテスト(cypress)) #74

Open Haramaki0326 opened 2 years ago

Haramaki0326 commented 2 years ago

ユニットテスト

Jest

参考

使い方

import sum from './math.js';

describe('sum', () => {
  test('sums up two values', () => {
    expect(sum(2, 4)).toBe(6);
  });
});

他の基本事項については基本的に上記参考の - Facebook製のJavaScriptテストツール「Jest」の逆引き使用例 -Qiita にすべて解説されている

スナップショットテスト

Jest

参考

Integrationテスト

react-testing-library

参考

概要

インストール

使い方

describe,test

describe,testについてはJestと同様

Imports

// import dependencies
import React from 'react'

// import API mocking utilities from Mock Service Worker
import {rest} from 'msw'
import {setupServer} from 'msw/node'

// import react-testing methods
import {render, fireEvent, waitFor, screen} from '@testing-library/react'

// add custom jest matchers from jest-dom
import '@testing-library/jest-dom'
// the component to test
import Fetch from '../fetch'
test('loads and displays greeting', async () => {
  // Arrange
  // Act
  // Assert
})

Mock

Arrange

renderメソッド
import React from 'react';
import { render, screen } from '@testing-library/react';

import App from './App';

describe('App', () => {
  test('renders App component', () => {
    render(<App />);

    screen.debug();
  });
});
image
renderメソッドの補足(Screen vs Renderクエリ)
  1. renderクエリ
    
    import React from 'react'
    import { render } from '@testing-library/react'

...

const { getByText } = render(

Foo
)

expect(getByText('Foo')).toBeInTheDocument()


2. `Screen`
``` js
import React from 'react'
import { render, screen } from '@testing-library/react'

...

render(<div>Foo</div>)

expect(screen.getByText('Foo')).toBeInTheDocument()
beforeEach,afterEach
describe('ToDoアプリ', () => {
  // 前準備
  beforeEach(() => {
    render(<App />);
  });
import {cleanup, render} from '@testing-library/react'
import test from 'ava'

test.afterEach(cleanup)

test('renders into document', () => {
  render(<div />)
  // ...
})

// ... more tests ...

Act,Assertion の準備

要素の選択
import React from 'react';
import { render, screen } from '@testing-library/react';

import App from './App';

describe('App', () => {
  test('renders App component', () => {
    render(<App />);

    expect(screen.getByText('Search:')).toBeInTheDocument();
  });
});
import React from 'react';
import { render, screen } from '@testing-library/react';

import App from './App';

describe('App', () => {
  test('renders App component', () => {
    render(<App />);

    // 暗黙的なアサーション
    // 存在しない場合はエラーを吐くため明示的なアサーションを書かなくてもよい
    screen.getByText('Search:');

    // 明示的なアサーション
    // こちらの方が推奨される書き方
    expect(screen.getByText('Search:')).toBeInTheDocument();
  });
});
import React from 'react';
import { render, screen } from '@testing-library/react';

import App from './App';

describe('App', () => {
  test('renders App component', () => {
    render(<App />);

    // fails
    expect(screen.getByText('Search')).toBeInTheDocument();

    // succeeds
    expect(screen.getByText('Search:')).toBeInTheDocument();

    // succeeds
    expect(screen.getByText(/Search/)).toBeInTheDocument();
  });
});
検索のタイプ
検索バリエーション
getBy
queryBy

import App from './App';

describe('App', () => { test('renders App component', () => { render();

expect(screen.queryByText(/Searches for JavaScript/)).toBeNull();

}); });

###### `findBy`
- [findByをいつ使うか? - Qiita](https://qiita.com/ossan-engineer/items/4757d7457fafd44d2d2f#findby%E3%82%92%E3%81%84%E3%81%A4%E4%BD%BF%E3%81%86%E3%81%8B)

###### 複数
- `getBy`、`queryBy`、`findBy` ⇒ これらは全て1つの要素だけを返す
- 複数の要素(例. [Reactコンポーネントのリスト](https://www.robinwieruch.de/react-list-component))をアサーションするには**All**で拡張できます。
  - `getAllBy`
  - `queryAllBy`
  - `findAllBy`

#### Act
- [説明-公式](https://testing-library.com/docs/ecosystem-user-event/)
- `userEvent` APIは`fireEvent` APIよりも実際のブラウザに近い振る舞いをする
- React Testing Libraryを使う時は、可能な限り**fireEventよりもuserEventを使うように心がけ**てください。現時点では、userEventはfireEventの全ての機能を含んではいませんが、将来的に変更される可能性があります。

``` js
import React from 'react';
import { render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';

import App from './App';

describe('App', () => {
  test('renders App component', async () => {
    render(<App />);

    // wait for the user to resolve
    await screen.findByText(/Signed in as/);

    expect(screen.queryByText(/Searches for JavaScript/)).toBeNull();

    await userEvent.type(screen.getByRole('textbox'), 'JavaScript');

    expect(
      screen.getByText(/Searches for JavaScript/)
    ).toBeInTheDocument();
  });
});

Assert

// assert that the alert message is correct using
// toHaveTextContent, a custom matcher from jest-dom.
expect(screen.getByRole('alert')).toHaveTextContent('Oops, failed to fetch!')

// assert that the button is not disabled using
// toBeDisabled, a custom matcher from jest-dom.
expect(screen.getByRole('button')).not.toBeDisabled()

E2Eテスト

cypress

Haramaki0326 commented 2 years ago

ロケータ(要素の特定方法)について

参考