Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Sign up for free
Menu
Search
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
React Hooksのテストを書いてみよう
Search
Sponsored
·
Your Podcast. Everywhere. Effortlessly.
Share. Educate. Inspire. Entertain. You do you. We'll handle the rest.
→
markey
August 08, 2019
Programming
410
0
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
React Hooksのテストを書いてみよう
React Hooksのテストを書いてみよう
markey
August 08, 2019
Other Decks in Programming
See All in Programming
自分的「カンファレンスの楽しみ方」
syumai
0
200
モジュールの視点からSwiftを読み解く #iosdc
s_shimotori
0
100
Building an Out-of-Order CPU
latte72
1
760
AWS Step Functions 大規模並列の壁を越える / jaws-sonic-2026-niigata-step-functions
kasacchiful
PRO
1
440
AHC070解法紹介
eijirou
0
110
初心者DevRelとして参加者だった私が、DevRel Talks!#2に登壇するまでにしてきたこと
sokohirai
0
370
GKE アップグレード前に知っておきたい Blue/Green と PDB の関係
stkk
0
160
LL言語やWebフレームワークのPostgreSQL対応 〜DBの機能がユーザーに届くまで〜
kentaroutakeda
0
150
AIエージェント時代のコードレビューを設計する
nogu66
6
2.6k
変化を抱擁するドキュメントの作り方 - ビジネスルール駆動開発がもたらす、コードとの新しい関係
ioki
2
150
LoopHub - ローカルで動く GitHub で、AI と共同開発
jugyo
1
520
RSSとCodexを使ってX投稿自動化してみた
ochtum
0
110
Featured
See All Featured
Sam Torres - BigQuery for SEOs
techseoconnect
PRO
0
540
Unlocking the hidden potential of vector embeddings in international SEO
frankvandijk
0
930
Design of three-dimensional binary manipulators for pick-and-place task avoiding obstacles (IECON2024)
konakalab
0
590
My Coaching Mixtape
mlcsv
0
310
Navigating Team Friction
lara
192
16k
Distributed Sagas: A Protocol for Coordinating Microservices
caitiem20
333
23k
4 Signs Your Business is Dying
shpigford
187
23k
The Psychology of Web Performance [Beyond Tellerrand 2023]
tammyeverts
49
3.6k
How to Talk to Developers About Accessibility
jct
2
540
Chasing Engaging Ingredients in Design
codingconduct
0
310
AI: The stuff that nobody shows you
jnunemaker
PRO
9
990
Practical Tips for Bootstrapping Information Extraction Pipelines
honnibal
25
2.1k
Transcript
React Hooks のテストを書い てみよう Meguro.es #22 08/08
自己紹介 名前: markey, markey_koichan(Twitter) 職業: フロントエンドエン ジニア スキル: React/Vue/TypeScript
テスト、書いてますか?
React Hooks のテスト、書い てますか?
React Hooks 誕生後の世界 UI コンポーネント→Function Component ビジネスロジック→Custom Hook
こんないいことが UI とロジックが分離され、テスタブルなコードに ビジネスロジックをCustom Hook に集約する(API からのデータ取 得・加工、状態、ハンドラー) UI コンポーネントの開発は受け取るProps
の定義と、それらを元に した表示のみ UI コンポーネント開発者はロジック部分やAPI の仕様などを一切知 る必要がない 複数の開発者が同一ページのUI とロジックを並行開発することが可 能
今こそ、テストをやるチャン ス
それぞれのテスト UI コンポーネント→Storybook + reg-suit ビジネスロジック→@testing-library/react-hooks
今日話すのはここ UI コンポーネント→Storybook + reg-suit ビジネスロジック→@testing-library/react-hooks ビジネスロジック→@testing-library/react-hooks
@testing-library/react-hooks 公式ドキュメント React Hooks のテストユーティリティライブラリ hook をシンプルな関数のように実行でき( ラッパーコンポーネント は不要) 、
hook の更新も容易 メインのファイルはわずか93 行
パッケージの追加 yarn add --dev @testing-library/react-hooks yarn add --dev @testing-library/react-hooks #
もしくは # もしくは npm install --save-dev @testing-library/react-hooks npm install --save-dev @testing-library/react-hooks
@testing-library/react-hooks を使ったシンプルなテスト import import { { useState useState, , useCallback
useCallback } } from from 'React' 'React' export export default default function function useCounter useCounter( () ) { { const const [ [count count, , setCount setCount] ] = = useState useState( (0 0) ) const const increment increment = = useCallback useCallback( (( () ) => => setCount setCount( (( (x x) ) => => x x return return { { count count, , increment increment } } } } import import { { renderHook renderHook } } from from '@testing-library/react-hook '@testing-library/react-hook import import useCounter useCounter from from '.' '.' test test( ('should use counter' 'should use counter', , ( () ) => => { {
ブラウザ上でのhook の動作をシミュレートして、 値を更新するには? test test( ('should increment counter' 'should increment
counter', , ( () ) => => { { const const { { result result } } = = renderHook renderHook( (( () ) => => useCounter useCounter( () )) ) expect expect( (result result. .current current. .count count) ). .toBe toBe( (0 0) ) // act でラップする // act でラップする act act( (( () ) => => { { result result. .current current. .increment increment( () ) } }) ) expect expect( (result result. .current current. .count count) ). .toBe toBe( (1 1) ) } }) )
Context から値を取得するときはどうする? (Redux, Apollo Client, ...) const const CounterStepContext CounterStepContext
= = React React. .createContext createContext( (1 1) ) export export const const CounterStepProvider CounterStepProvider = = ( ({ { step step, , children children } }) ) < <CounterStepContext CounterStepContext. .Provider value Provider value= ={ {step step} }> >{ {children children} }< < ) ) export export function function useCounter useCounter( () ) { { const const [ [count count, , setCount setCount] ] = = useState useState( (0 0) ) // increment する値はContext から取得 // increment する値はContext から取得 const const step step = = useContext useContext( (CounterStepContext CounterStepContext) ) const const increment increment = = useCallback useCallback( (( () ) => => setCount setCount( (( (x x) ) => => x x
import import { { useCounter useCounter, , CounterStepProvider CounterStepProvider }
} from from '.' '.' test test( ('should use custom step when incrementing' 'should use custom step when incrementing', , ( () ) => => const const wrapper wrapper = = ( ({ { children children } }) ) => => ( ( < <CounterStepProvider step CounterStepProvider step= ={ {2 2} }> >{ {children children} }< </ /CounterSt CounterSt ) ) // renderHook の第2 引数にwrapper オプションを指定 // renderHook の第2 引数にwrapper オプションを指定 const const { { result result } } = = renderHook renderHook( (( () ) => => useCounter useCounter( () ), , { { w w expect expect( (result result. .current current. .count count) ). .toBe toBe( (0 0) ) act act( (( () ) => => { { result result. .current current. .increment increment( () ) } }) )
非同期な関数の実行はどうする? export export default default function function useCounter useCounter( ()
) { { const const [ [count count, , setCount setCount] ] = = useState useState( (0 0) ) const const increment increment = = useCallback useCallback( (( () ) => => setCount setCount( (( (x x) ) => => x x // 0.1 秒後に非同期にincrement する // 0.1 秒後に非同期にincrement する const const incrementAsync incrementAsync = = useCallback useCallback( (( () ) => => setTimeout setTimeout( (i i return return { { count count, , increment increment, , incrementAsync incrementAsync } } } }
test test( ('should increment counter after delay' 'should increment counter
after delay', , async async ( () ) = = const const { { result result, , waitForNextUpdate waitForNextUpdate } } = = renderHook renderHook( (( () ) = = result result. .current current. .incrementAsync incrementAsync( () ) // 実行直後はまだincrement されていない // 実行直後はまだincrement されていない expect expect( (result result. .current current. .count count) ). .toBe toBe( (0 0) ) // Promise がresolve されるまで待つ // Promise がresolve されるまで待つ await await waitForNextUpdate waitForNextUpdate( () ) expect expect( (result result. .current current. .count count) ). .toBe toBe( (1 1) ) } }) )
@testing-library/react-hooks で 快適なテストライフを
ご清聴ありがとうございまし た! ( 副業募集中...React とTypeScript チョットカケマス...)