apeescape2.com
  • メイン
  • データサイエンスとデータベース
  • 人とチーム
  • ブランドデザイン
  • Webフロントエンド
Webフロントエンド

Reactテスト駆動開発:ユーザーストーリーから本番まで

この投稿では、ユーザーストーリーから開発まで、テスト駆動開発(TDD)を使用してReactアプリを開発します。また、TDDにはJestとEnzymeを使用します。このガイドを完了すると、次のことができるようになります。

  • 要件に基づいてエピックとユーザーストーリーを作成します。
  • ユーザーストーリーに基づいてテストを作成します。
  • TDDを使用してReactアプリを開発します。
  • EnzymeとJestを使用してReactアプリをテストします。
  • レスポンシブデザインのためにCSS変数を使用/再利用します。
  • 提供された小道具に基づいて異なる方法でレンダリングおよび機能する再利用可能なReactコンポーネントを作成します。
  • ReactPropTypesを使用してコンポーネントの小道具をタイプチェックします。

この記事は、Reactの基本的な知識があることを前提としています。 Reactを初めて使用する場合は、 公式チュートリアル ApeeScapeの2019Reactチュートリアルをご覧ください。 パート1 そして パート2 。

テスト駆動型Reactアプリの概要

いくつかのUIコンポーネントで構成される基本的なポモドーロタイマーアプリを構築します。各コンポーネントには、対応するテストファイルに個別のテストセットがあります。まず、プロジェクトの要件に基づいて、次のようにエピックとユーザーストーリーを作成できます。



大作 ユーザーストーリー 合否基準
ユーザーとして、自分の時間を管理できるようにタイマーを使用する必要があります。 ユーザーとして、時間をカウントダウンできるようにタイマーを開始する必要があります。 ユーザーが次のことができることを確認します。

*タイマーを開始します
*タイマーがカウントダウンを開始するのを参照してください

ユーザーがスタートボタンを2回以上クリックしても、時間のカウントダウンが中断されないようにする必要があります。
ユーザーとして、必要なときにだけ時間をカウントダウンできるように、タイマーを停止する必要があります。 ユーザーが次のことができることを確認します。

*タイマーを停止します
*タイマーが停止したことを確認してください

ユーザーが停止ボタンを2回以上クリックしても、何も起こりません。
ユーザーとして、最初から時間をカウントダウンできるように、タイマーをリセットする必要があります。 ユーザーが次のことができることを確認します。

*タイマーをリセットする
*デフォルトにリセットされたタイマーを参照してください

ワイヤーフレーム

ワイヤーフレーム

プロジェクトの設定

まず、を使用してReactプロジェクトを作成します Reactアプリを作成する 次のように:

$ npx create-react-app react-timer $ cd react-timer $ npm start

URLで開いている新しいブラウザタブが表示されます http:// localhost:3000 。を使用して実行中のReactアプリを停止できます Ctrl + C 。

次に、追加します です そして 酵素 およびいくつかの依存関係は次のとおりです。

$ npm i -D enzyme $ npm i -D react-test-renderer enzyme-adapter-react-16

また、というファイルを追加または更新します setupTests.js の中に src ディレクトリ:

import { configure } from ‘enzyme’; import Adapter from ‘enzyme-adapter-react-16’; configure({ adapter: new Adapter() });

以来 Reactアプリを作成する を実行します setupTests.js 各テストの前にファイルを実行し、酵素を適切に構成します。

CSSの構成

変数と基本的なCSSリセットを記述します。 CSS変数 アプリケーションでグローバルに利用できます。から変数を定義します :rootスコープ 。変数を定義するための構文は、それぞれが–で始まり、その後に変数名が続くカスタムプロパティ表記を使用することです。

に移動します index.css ファイルを作成し、以下を追加します。

:root { --main-font: “Roboto”, sans-serif; } body, div, p { margin: 0; padding: 0; }

次に、CSSをアプリケーションにインポートする必要があります。 index.jsファイルを次のように更新します。

import React from ‘react’; import ReactDOM from ‘react-dom’; import ‘./index.css’; ReactDOM.render( document.getElementById(“root”) )

浅いレンダリングテスト

ご存知かもしれませんが、TDDプロセスは次のようになります。

  1. テストを追加します。
  2. すべてのテストを実行すると、テストが失敗することがわかります。
  3. テストに合格するためのコードを記述します。
  4. すべてのテストを実行します。
  5. リファクタリング。
  6. 繰り返す。

したがって、浅いレンダリングテストの最初のテストを追加してから、テストに合格するコードを記述します。名前の付いた新しいスペックファイルを追加します App.spec.js に src / components / App 次のようなディレクトリ:

import React from ‘react’; import { shallow } from ‘enzyme’; import App from ‘./App’; describe(‘App’, () => { it(‘should render a ’, () => { const container = shallow(); expect(container.find(‘div’).length).toEqual(1); }); });

次に、テストを実行できます。

$ npm test

テストが失敗することがわかります。

アプリコンポーネント

次に、テストに合格するためのAppコンポーネントの作成に進みます。案内する App.jsx ディレクトリ内 src / components / App 次のようにコードを追加します。

import React from ‘react’; const App = () => ; export default App;

ここで、テストを再度実行します。

$ npm test

これで最初のテストに合格するはずです。

アプリCSSの追加

ファイルを作成します App.css ディレクトリ内 src / components / App 次のように、アプリコンポーネントにスタイルを追加します。

.app-container { height: 100vh; width: 100vw; align-items: center; display: flex; justify-content: center; }

これで、CSSをにインポートする準備ができました。 App.jsx ファイル:

import React from ‘react’; import ‘./App.css’; const App = () => ; export default App;

次に、更新する必要があります index.js 次のようにAppコンポーネントをインポートするファイル:

import React from 'react' import ReactDOM from 'react-dom' import './index.css' import App from './components/App/App' import * as serviceWorker from './serviceWorker' ReactDOM.render( , document.getElementById('root') ) // If you want your app to work offline and load faster, you can change // unregister() to register() below. Note this comes with some pitfalls. // Learn more about service workers: https://bit.ly/CRA-PWA serviceWorker.unregister()

タイマーコンポーネントの追加

最後に、アプリにはタイマーコンポーネントが含まれるため、 App.spec.js アプリ内のタイマーコンポーネントの存在を確認するファイル。また、浅いレンダリングテストは各テストケースの前に実行する必要があるため、最初のテストケースの外側でコンテナ変数を宣言します。

import React from 'react' import { shallow } from 'enzyme' import App from './App' import Timer from '../Timer/Timer' describe('App', () => { let container beforeEach(() => (container = shallow())) it('should render a ', () => { expect(container.find('div').length).toEqual(1) }) it('should render the Timer Component', () => { expect(container.containsMatchingElement()).toEqual(true) }) })

npm testを実行した場合この段階では、Timerコンポーネントがまだ存在しないため、テストは失敗します。

タイマーの浅いレンダリングテストの作成

次に、という名前のファイルを作成します Timer.spec.js 名前の付いた新しいディレクトリに タイマー 下 src / components ディレクトリ。

また、浅いレンダリングテストを追加します Timer.spec.js ファイル:

import React from 'react' import { shallow } from 'enzyme' import Timer from './Timer' describe('Timer', () => { let container beforeEach(() => (container = shallow())) it('should render a ', () => { expect(container.find('div').length).toBeGreaterThanOrEqual(1) }) })

予想どおり、テストは失敗します。

タイマーコンポーネントの作成

次に、という新しいファイルを作成しましょう Timer.jsx ユーザーストーリーに基づいて同じ変数とメソッドを定義します。

import React, { Component } from 'react'; class Timer extends Component { constructor(props) { super(props); this.state = { minutes: 25, seconds: 0, isOn: false }; } startTimer() { console.log('Starting timer.'); } stopTimer() { console.log('Stopping timer.'); } resetTimer() { console.log('Resetting timer.'); } render = () => { return ; }; } export default Timer;

これはテストに合格し、 すべき レンダリングします Timer.spec.js ファイル、しかしテスト いけない アプリコンポーネントにタイマーコンポーネントをまだ追加していないため、タイマーコンポーネントをレンダリングします。

タイマーコンポーネントをに追加します App.jsx このようなファイル:

import React from 'react'; import './App.css'; import Timer from '../Timer/Timer'; const App = () => ( ); export default App;

これですべてのテストに合格するはずです。

タイマーCSSの追加

タイマーに関連するCSS変数を追加し、小型デバイス用のメディアクエリを追加します。

ファイルを更新する index.css 次のように:

:root { --timer-background-color: #FFFFFF; --timer-border: 1px solid #000000; --timer-height: 70%; --timer-width: 70%; } body, div, p { margin: 0; padding: 0; } @media screen and (max-width: 1024px) { :root { --timer-height: 100%; --timer-width: 100%; } }

また、作成します Timer.css ディレクトリの下のファイル コンポーネント/タイマー :

.timer-container { background-color: var(--timer-background-color); border: var(--timer-border); height: var(--timer-height); width: var(--timer-width); }

更新する必要があります Timer.jsx インポートするには Timer.css ファイル。

import React, { Component } from 'react' import './Timer.css'

ここでReactアプリを実行すると、ブラウザーに境界線のある単純な画面が表示されます。

TimerButtonの浅いレンダリングテストを作成する

3つのボタンが必要です。 起動停止 、および リセット 、したがって、作成します TimerButtonコンポーネント 。

まず、更新する必要があります Timer.spec.js の存在を確認するファイル TimerButton のコンポーネント タイマー 成分:

it('should render instances of the TimerButton component', () => { expect(container.find('TimerButton').length).toEqual(3) })

それでは、を追加しましょう TimerButton.spec.js と呼ばれる新しいディレクトリのファイル TimerButton 下 src / components ディレクトリを作成し、次のようにテストをファイルに追加しましょう。

import React from 'react' import { shallow } from 'enzyme' import TimerButton from './TimerButton' describe('TimerButton', () => { let container beforeEach(() => { container = shallow( ) }) it('should render a ', () => { expect(container.find('div').length).toBeGreaterThanOrEqual(1) }) })

ここで、テストを実行すると、テストが失敗することがわかります。

を作成しましょう TimerButton.jsx のファイル TimerButton 成分:

Excel2016でpowerpivotを使用する方法
import React from 'react'; import PropTypes from 'prop-types'; const TimerButton = ({ buttonAction, buttonValue }) => ( ); TimerButton.propTypes = { buttonAction: PropTypes.func.isRequired, buttonValue: PropTypes.string.isRequired, }; export default TimerButton;

npm testを実行した場合この段階で、テスト TimerButtonコンポーネントのインスタンスをレンダリングする必要があります ただし、TimerButtonコンポーネントをTimerコンポーネントにまだ追加していないため、失敗します。

をインポートしましょう TimerButton コンポーネントと3つ追加 TimerButton のrenderメソッドのコンポーネント Timer.jsx :

render = () => { return ( ); };

TimerButton CSS

次に、TimerButtonコンポーネントのCSS変数を追加します。に変数を追加しましょう :ルート スコープ index.css ファイル:

:root { ... --button-border: 3px solid #000000; --button-text-size: 2em; } @media screen and (max-width: 1024px) { :root { … --button-text-size: 4em; } }

また、というファイルを作成しましょう TimerButton.css の中に TimerButton 下のディレクトリ src / components ディレクトリ:

.button-container { flex: 1 1 auto; text-align: center; margin: 0px 20px; border: var(--button-border); font-size: var(--button-text-size); } .button-container:hover { cursor: pointer; }

更新しましょう TimerButton.jsx それに応じてインポートする TimerButton.css ファイルとボタンの値を表示するには:

import React from 'react'; import PropTypes from 'prop-types'; import './TimerButton.css'; const TimerButton = ({ buttonAction, buttonValue }) => (

{buttonValue}

); TimerButton.propTypes = { buttonAction: PropTypes.func.isRequired, buttonValue: PropTypes.string.isRequired, }; export default TimerButton;

また、更新する必要があります Timer.css 3つのボタンを水平に揃えるために、 Timer.css ファイルも:

import React from 'react'; import PropTypes from 'prop-types'; import './TimerButton.css'; const TimerButton = ({ buttonAction, buttonValue }) => (

{buttonValue}

); TimerButton.propTypes = { buttonAction: PropTypes.func.isRequired, buttonValue: PropTypes.string.isRequired, }; export default TimerButton;

ここでReactアプリを実行すると、次のような画面が表示されます。

タイマー

タイマーのリファクタリング

次のような関数を実装したいので、タイマーをリファクタリングします。 startTimer、stopTimer、restartTimer 、および resetTimer 。更新しましょう Timer.spec.js 最初のファイル:

describe('mounted Timer', () => { let container; beforeEach(() => (container = mount())); it('invokes startTimer when the start button is clicked', () => { const spy = jest.spyOn(container.instance(), 'startTimer'); container.instance().forceUpdate(); expect(spy).toHaveBeenCalledTimes(0); container.find('.start-timer').first().simulate('click'); expect(spy).toHaveBeenCalledTimes(1); }); it('invokes stopTimer when the stop button is clicked', () => { const spy = jest.spyOn(container.instance(), 'stopTimer'); container.instance().forceUpdate(); expect(spy).toHaveBeenCalledTimes(0); container.find('.stop-timer').first().simulate('click'); expect(spy).toHaveBeenCalledTimes(1); }); it('invokes resetTimer when the reset button is clicked', () => { const spy = jest.spyOn(container.instance(), 'resetTimer'); container.instance().forceUpdate(); expect(spy).toHaveBeenCalledTimes(0); container.find('.reset-timer').first().simulate('click'); expect(spy).toHaveBeenCalledTimes(1); }); });

テストを実行すると、更新されていないため、追加されたテストが失敗することがわかります。 TimerButton コンポーネントはまだです。更新しましょう TimerButton クリックイベントを追加するコンポーネント:

const TimerButton = ({ buttonAction, buttonValue }) => ( buttonAction()}>

{buttonValue}

);

これで、テストに合格するはずです。

次に、各関数がで呼び出されたときの状態を確認するためのテストをさらに追加します。 マウントされたタイマー テストケース:

it('should change isOn state true when the start button is clicked', () => { container.instance().forceUpdate(); container.find('.start-timer').first().simulate('click'); expect(container.instance().state.isOn).toEqual(true); }); it('should change isOn state false when the stop button is clicked', () => { container.instance().forceUpdate(); container.find('.stop-timer').first().simulate('click'); expect(container.instance().state.isOn).toEqual(false); }); it('should change isOn state false when the reset button is clicked', () => { container.instance().forceUpdate(); container.find('.stop-timer').first().simulate('click'); expect(container.instance().state.isOn).toEqual(false); expect(container.instance().state.minutes).toEqual(25); expect(container.instance().state.seconds).toEqual(0); });

テストを実行すると、各メソッドをまだ実装していないため、テストが失敗することがわかります。それでは、テストに合格するために各関数を実装しましょう。

startTimer() { this.setState({ isOn: true }); } stopTimer() { this.setState({ isOn: false }); } resetTimer() { this.stopTimer(); this.setState({ minutes: 25, seconds: 0, }); }

テストを実行すると、テストに合格することがわかります。それでは、残りの関数をで実装しましょう Timer.jsx :

import React, { Component } from 'react'; import './Timer.css'; import TimerButton from '../TimerButton/TimerButton'; class Timer extends Component { constructor(props) { super(props); this.state = { minutes: 25, seconds: 0, isOn: false, }; this.startTimer = this.startTimer.bind(this); this.stopTimer = this.stopTimer.bind(this); this.resetTimer = this.resetTimer.bind(this); } startTimer() { if (this.state.isOn === true) { return; } this.myInterval = setInterval(() => { const { seconds, minutes } = this.state; if (seconds > 0) { this.setState(({ seconds }) => ({ seconds: seconds - 1, })); } if (seconds === 0) { if (minutes === 0) { clearInterval(this.myInterval); } else { this.setState(({ minutes }) => ({ minutes: minutes - 1, seconds: 59, })); } } }, 1000); this.setState({ isOn: true }); } stopTimer() { clearInterval(this.myInterval); this.setState({ isOn: false }); } resetTimer() { this.stopTimer(); this.setState({ minutes: 25, seconds: 0, }); } render = () => { const { minutes, seconds } = this.state; return ( {minutes}:{seconds <10 ? `0${seconds}` : seconds} ); }; } export default Timer;

以前に準備したユーザーストーリーに基づいて、すべての機能が機能することがわかります。

タイマー

これが、TDDを使用して基本的なReactアプリを開発した方法です。ユーザーストーリーと受け入れ基準がより詳細である場合、テストケースをより正確に記述できるため、さらに貢献できます。

まとめ

TDDを使用してアプリケーションを開発する場合、プロジェクトを叙事詩やユーザーストーリーに分類するだけでなく、受け入れ基準に十分に備えることが非常に重要です。この記事では、プロジェクトを分解し、準備された受け入れ基準をReactTDD開発に使用する方法を紹介したいと思います。

React TDDに関連するリソースはたくさんありますが、この記事が、ユーザーストーリーを使用したReactでのTDD開発について少し学ぶのに役立つことを願っています。このアプローチをエミュレートすることを選択した場合は、完全なソースコードを参照してください ここに 。

基本を理解する

テスト駆動開発をどのように行いますか?

テスト駆動開発の場合、最初にテストを作成し、テストが失敗するかどうかを確認する必要があります。テストが失敗したことを確認したら、テストに合格するコードを記述し、必要に応じてリファクタリングします。次に、次のテストのためにこれらの手順をすべて繰り返します。

Reactで何をテストする必要がありますか?

テストを作成する主な理由は、アプリが正常に機能することを確認することです。 Reactでは、アプリがエラーなしで正しくレンダリングされるかどうかをテストする必要があります。また、出力と状態、およびイベントをテストする必要があります。最後に、他のテクノロジースタックと同様にエッジケースをテストする必要があります。

テスト駆動開発は良いですか?

テスト駆動開発は、本番環境のバグを減らし、コードの品質を向上させ、コードの保守を容易にするため、有益です。また、回帰テストの自動テストも提供します。ただし、TDDはGUIテストにコストがかかる可能性があり、TDDが多すぎるとコードがより複雑になります。

成功に向けて調整–投資家がスタートアップに求めるものへのガイド

財務プロセス

成功に向けて調整–投資家がスタートアップに求めるものへのガイド
アプリを収益性の高いものにする、パート2 –モバイルファネルの活用

アプリを収益性の高いものにする、パート2 –モバイルファネルの活用

バックエンド

人気の投稿
Nuxt.jsを使用したサーバー側のレンダリングされたVue.jsアプリの作成
Nuxt.jsを使用したサーバー側のレンダリングされたVue.jsアプリの作成
React.JSエコシステムのナビゲート
React.JSエコシステムのナビゲート
次の大きなものの構築–ビジネスアイデア開発のガイド
次の大きなものの構築–ビジネスアイデア開発のガイド
危機における経済的苦痛:予測することはできず、準備することもできます
危機における経済的苦痛:予測することはできず、準備することもできます
オンデマンド製品開発:デジタルトランスフォーメーションの推進
オンデマンド製品開発:デジタルトランスフォーメーションの推進
 
ブロックチェーンID管理:データセキュリティ革命の火付け役
ブロックチェーンID管理:データセキュリティ革命の火付け役
フロントエンドフレームワーク:ソリューションまたは巨大な問題?
フロントエンドフレームワーク:ソリューションまたは巨大な問題?
愛を込めてデザイナーへ(フロントエンド開発者からの手紙)
愛を込めてデザイナーへ(フロントエンド開発者からの手紙)
Swiftのプロトコル指向プログラミング入門
Swiftのプロトコル指向プログラミング入門
フリーランスのファイナンスコンサルタントが大企業をどのように打ち負かしているか
フリーランスのファイナンスコンサルタントが大企業をどのように打ち負かしているか
人気の投稿
  • プロトタイプとモックアップは、ソフトウェアクラスの設計を行う際に最も役立ちます。
  • ヒューリスティック評価とは
  • c ******コンパイル
  • モジュールを使用すると、プログラマーはチームで作業できなくなります。
  • 次のうち、デザインにおけるアイテムの相互関係を意味するのはどれですか?
  • 次のうち、閉鎖の原則ではないものはどれですか?
  • デザインリストの要素と原則
カテゴリー
モバイルデザイン Uiデザイン アジャイル デザイナーライフ 仕事の未来 ブランドデザイン 人とチーム 革新 バックエンド ツールとチュートリアル

© 2021 | 全著作権所有

apeescape2.com