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
上手に付き合うコンポーネントテスト
Search
Yosuke Kurami
September 20, 2024
Programming
2.4k
6
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
上手に付き合うコンポーネントテスト
Yosuke Kurami
September 20, 2024
More Decks by Yosuke Kurami
See All by Yosuke Kurami
GraphQL の onError と Nullability のこれから
quramy
0
170
TypeScript LSP の今までとこれから
quramy
1
2.3k
フロントエンドテストの育て方
quramy
12
3.9k
App Router 悲喜交々
quramy
8
770
Patched fetch did not work
quramy
6
820
GraphQL あるいは React における自律的なデータ取得について
quramy
18
6k
Next.js App Router
quramy
15
4k
Fragment Composition of GraphQL
quramy
17
5k
reg-viz VRT tools
quramy
4
1.8k
Other Decks in Programming
See All in Programming
[JA] Domain Modeling with Vanilla Rails: 「操作」から再考するRailsの設計論
yasaichi
4
790
作って学ぶSpring BootのAuto Configuration / JJUG Night Seminar 2026-10-19
rshindo
0
200
re:Inventに行く前に知っておきたい現地参加のノウハウ
nokomoro3
0
460
全ての永続トークンを、生まれる前に消し去りたい!
sylph01
2
1.1k
最近”作らせてる” ローカルAIアプリの話
akit37
0
490
RAG の “R” を Swift で覗いてみる 〜「意味から探す」検索の仕組み〜
nao_randd
0
170
When benchmarks go bad - what I learned from measuring performance wrong
hollycummins
0
240
우리의 Nitro Modules는 당신의 Turbo Modules보다 아름답다
l2hyunwoo
0
150
AmebaブログはKMPから卒業します
kmars0605
0
220
複雑なUIコンポーネントとの ⻑い付き合い⽅:波及するバグからテスト戦略を経て、安全な再設計へ
mixplace
0
450
AI時代のTerminal環境を UNIX哲学で設計・運用する
yasunori0418
1
200
Groovy as a human and AI friendly programming language
paulk
0
100
Featured
See All Featured
Context Engineering - Making Every Token Count
addyosmani
9
1.2k
A Tale of Four Properties
chriscoyier
163
24k
We Are The Robots
honzajavorek
0
400
Ethics towards AI in product and experience design
skipperchong
2
440
Statistics for Hackers
jakevdp
799
230k
Designing for Timeless Needs
cassininazir
1
530
Optimizing for Happiness
mojombo
378
71k
Ten Tips & Tricks for a 🌱 transition
stuffmc
1
270
Build your cross-platform service in a week with App Engine
jlugia
234
19k
RailsConf & Balkan Ruby 2019: The Past, Present, and Future of Rails at GitHub
eileencodes
141
35k
Utilizing Notion as your number one productivity tool
mfonobong
4
620
The Organizational Zoo: Understanding Human Behavior Agility Through Metaphoric Constructive Conversations (based on the works of Arthur Shelley, Ph.D)
kimpetersen
PRO
0
500
Transcript
্खʹ͖߹͏ ίϯϙʔωϯτςετ 2024.09.20 @Quramy
About me - id: @Quramy (GitHub / X ) -
͓ࣄ: Web ϑϩϯτΤϯυΤϯδχΞ - React, Next.js, GraphQL - ՝֎׆ಈ: ςετࢧԉܥπʔϧͷ࡞ - Prisma ORM ؔ࿈: jest-prisma, prisma-fabbrica - Visual Testing ؔ࿈: reg-suit, Storycap
Visual Testing ಉձ https://speakerdeck.com/quramy/reg-viz-vrt-tools?slide=6
Agenda - ίϯϙʔωϯτςετͷಋೖ - ίϯϙʔωϯτςετͷӡ༻
ಋೖฤ
ࣗಈςετͷత - εϐʔυΛଛͳΘͣʹ։ൃΛଓ͚ΔͨΊ - طଘͷػೳ͕ͳ͘ಈ࡞͚͍ͭͮͯ͠Δ͜ͱΛ୲อͯ͘͠ΕΔ - ϑϩϯτΤϯυͷ߹ʮݟ͕ͨͲͷΑ͏ʹมߋ͞ΕΔͷ͔ʯ͕Մࢹ Խ͞ΕΔͱɺϨϏϡΞଆͷ֬ೝίετݮʹͭͳ͕Δ
උ͑େࣄ - ϓϩδΣΫτ্ཱͪ͛࣌ίϯϙʔωϯτςετಋೖΛݟૹΔͷબ ࢶͱͯ͠ΞϦͱࢥ͏ - ͨͩ͠ɺޙ͔ΒಋೖͰ͖ΔΑ͏ʹඋ͓͑ͯ͘͜ͱॏཁ - ϓϩδΣΫτ͕ҭ͔ͬͯΒಥવʮΑ͠ ίϯϙʔωϯτͷ Visual
Testing Ζ͏ʂʯͱٸʹࢥཱ͍ͬͯɺθϩ͔ΒςετέʔεΛॻ͘ͷେม
ίϯϙʔωϯτςετͱ Storybook ίϯϙʔωϯτςετʹ Storybook Λ༻͍͍ͯΔཧ༝ - UI ίϯϙʔωϯτ։ൃج൫ͱͯ͠Չঢ়ଶ (ݸਓతʹଞͷπʔϧʹؤுͬͯ΄͍͕͠ɺStorybook ʹউͭͷ͕૬େมͳঢ়گʹͳ͍ͬͯ
Δͱࢥ͏) - Story ͕ςετέʔεͱͯ͠ྲྀ༻ՄೳͰ͋ΔͨΊɺʮͱΓ͋͑ͣ Story ͚ͩॻ ͘Α͏ʹ͓ͯ͘͠ʯ͕ίϯϙʔωϯτςετͷඋ͑ͱͳΔ - Storybook ͕ࣗಈςετʹؔ͢ΔػೳڧԽʹྗΛೖΕ͍ͯΔ - Jest / Vitest ࿈ܞ (compositeStories), test-runner, Chromatic, etc...
ίϯϙʔωϯτςετ with Storybook Storybook ͱ࿈ܞ͢ΔςετπʔϧςετϓϥοτϑΥʔϜ༷ʑͳͷ ͕͋ΔɻओཁͳͷΛհ (1/4) - Chromatic: https://www.chromatic.com/
Storybook ͷϗεςΟϯάࣗಈςετΛ݉Ͷඋ͑ͨ all-in-one ͳαʔϏ εɻStorybook ΦϑΟγϟϧ - Lost Pixel: https://www.lost-pixel.com/ VRT πʔϧɻChromatic ͷΑ͏ͳ SaaS ͱͯ͠ͷఏڙܗଶͷଞɺࣗલͷ CI ʹηϧϑϗετ͢Δ͜ͱՄೳͳπʔϧ
ίϯϙʔωϯτςετ with Storybook Storybook ͱ࿈ܞ͢ΔςετπʔϧςετϓϥοτϑΥʔϜ༷ʑͳͷ ͕͋ΔɻओཁͳͷΛհ (2/4) - Storycap: https://github.com/reg-viz/storycap
Storybook Λ Puppeteer ͰΫϩʔϧͯ͠ը૾Խ͢Δ CLI reg-suit reg-actions (͜ΕΒ reg-vizͷπʔϧ) ͱΈ߹ΘͤΔ͜ͱͰ ίϯϙʔωϯτ୯Ґͷ Visual Regression Test Λ࣮ݱ͢Δɻ Storybook x VRT ͱͯ͠ฮͷ෦ྨ (2017 ͔Β͋Δ)
ίϯϙʔωϯτςετ with Storybook Storybook ͱ࿈ܞ͢ΔςετπʔϧςετϓϥοτϑΥʔϜ༷ʑͳͷ ͕͋ΔɻओཁͳͷΛհ (3/4) - storybook/test-runner: https://storybook.js.org/docs/writing-tests/test-runner
Storybook ެࣜͷςετϥϯφʔɻࣗલ CI Ͱ Story ͷϨϯμϦϯά Play function Λ࣮ߦՄೳɻ jest-playwright Λ෦తʹར༻͍ͯ͠Δ - storycap-testrun: https://github.com/reg-viz/storycap-testrun storybook/test-runner Ͱར༻͢ΔεΫϦʔϯγϣοτϥΠϒϥϦɻ
ίϯϙʔωϯτςετ with Storybook Storybook ͱ࿈ܞ͢ΔςετπʔϧςετϓϥοτϑΥʔϜ༷ʑͳͷ ͕͋ΔɻओཁͳͷΛհ (4/4) - Jest /
Vitest: ୯ମςετͷπʔϧͰ͋Δ͕ɺStorybook ͕ఏڙ͢Δ composeStories ؔͱΈ߹ΘͤΔ͜ͱͰ Story ͷςετ͕Մೳɻ https://storybook.js.org/docs/writing-tests/import-stories-in-tests/ stories-in-unit-tests
͓͜ͱΘΓ - චऀ͕࣮ࡍʹӡ༻ͨ͜͠ͱͷ͋ΔίϯϙʔωϯτςετͷߏҎԼ: - Storybook + Storycap + reg-suit -
Storybook + Jest + compositeStories - Ҏ߱Ͱհ͢Δӡ༻ Tips ɺπʔϧͷબͱಠཱͨ͠༰ͱͳΔΑ͏ۃ ྗ৺͕͚͍ͯ·͕͢ɺ্هΛཹҙͯ͠Β͑Δͱॿ͔Γ·͢
ӡ༻ฤ
ӡ༻ฤ Εʂ ࣮ߦ࣌ؒ
Կ·Ͱ͑ΒΕΔʁ - Pull Request ࣌ͷ CI ࣮ߦ࣌ؒɺͲΕ͘Β͍·ͰզຫͰ͖·͔͢ʁ - ݸਓࠩ͋Δ͕ɺࣗͷ؍ଌൣғͰ 5ลΓʹᮢ͕͋Γͦ͏
- ίϯϙʔωϯτςετͷ࣮ߦ͕࣌ؒ͘ͳΕͳΔ΄ͲɺνʔϜͷϔΠ τ͕ཷ·͍ͬͯ͘
(ࢀߟ) ࣗಈςετ࣮ߦ࣌ؒਪҠ https://qiita.com/Quramy/items/46d0b09ae4d8887b0941 ߦ ίϯϙʔωϯτ έʔε $*࣮ߦ࣌ؒ
ฒྻ࣮ߦ (ϫʔΧʔϨϕϧ) - CI ͷ࣮ߦڥΛCPUΛ૿ڧͭͭ͠ɺ࣮ߦϒϥβ (worker) Λ૿͢ - GitHub Actions
Ͱ͋Εɺ Self Hosted Runner Ͱӡ༻͍ͯ͠Δਓ͚ - ίϯϙʔωϯτςετΛ࣮ߦ͢Δ CLI ͷΦϓγϣϯͰ worker Λมߋ: - Storycap CLI: --parallel Φϓγϣϯ - storybook/test-runner CLI: --max-workers Φϓγϣϯ
ฒྻ࣮ߦ (δϣϒϨϕϧ) - CI ͷ࣮ߦڥ͝ͱฒྻԽ͢Δύλʔϯ - GitHub Actions Ͱ͋Ε matrix
ͳͲͰ ฒྻδϣϒ࣮ߦՄೳ ※ ίϯϙʔωϯτςετ͕Δ·Ͱͷεςοϓ (ڥࣗମͷηοτΞοϓ npm i ͢Δ෦ ͳͲ) ͕େ͖͍ͱɺฒྻԽޮ͕Լ͕ΔͨΊ͕ඞཁ - storybook/test-runner Storycap ͷ --shard ΦϓγϣϯΛར༻͢Δ
ϥϯφʔΛ͍͚Δ - ࣮ϒϥβΛͬͨίϯϙʔωϯτςετ͍ͦͦ - શͯͷίϯϙʔωϯτͷςετͰɺৗʹϒϥβ͕ඞཁͱ͍͏Θ͚Ͱ ͳ͍ͣ (e.g. ϑΥʔϜόϦσʔγϣϯ aria ଐੑͷ֬ೝ)
- jsdom ͰेͳέʔεͰ͋ΕɺJest / Vitest + compositeStories ͷςε τίʔυͱ࣮ͯ͠ߦͰ͖Εɺ͘ͳΓʹ͍͘ - Storycap (= Puppeteer): 100 msec / story - Jest + jsdom: 10 msec / story
࣮ફฤ ௵ͤʂ Flakiness
Flaky Test μϝθολΠ - Flaky ͳςετͱ - ιʔείʔυʹมߋΛՃ͍͑ͯͳ͍ͷʹ ޭ/ࣦഊ ͕҆ఆ͠ͳ͍ঢ়ଶ
- ِཅੑ (False Positive) ࣗಈςετͷఢ - ಛʹ Visual Testing ݕূʹը૾Λ༻͍ΔͨΊ Flaky ςετʹؕΓ͍͢
VRT ʹ͓͚Δᮢͷௐ - ϒϥβʹίϯϙʔωϯτΛඳըͤ͞Δ߹্ɺશͳ pixel by pixel ͷ Ұக͍͠ -
e.g. CSS ͷ border-radius box-shadow ΞϯνΤΠϦΞε - [IMO] 100 ϐΫηϧ (ॎԣ 10px ͷਖ਼ํܗͷ໘ੵ) ఔͷࠩҟڐ༰ - 100 ఔͰِӄੑʹͳΔ͜ͱ໓ଟʹͳ͍ - [IMO] ը૾શମʹର͢ΔൺͰࢦఆ͢ΔͷͰ͋Εɺ 0.01% Λج४ʹ
෦తͳࠩ͠ସ͑ ίϯϙʔωϯτͷҰ෦͕ෆ҆ఆͳ߹ ( e.g. YouTube ຒࠐಈը, iframe) ɺ VRT ࣌ͷΈผ
div ʹࠩ͠ସ͑ͯɺFlaky Test ʹͳΒͳ͍Α͏ʹ͢Δ export function MyComponent() { return ( <div> {/* ͕͜͜ෆ҆ఆͳཁૉ */} <iframe style={{ height: 400, width: "100%" }} src="https://example.com/hogehoge" /> </div> ); } import { isScreenshot } from "storycap"; export function MyComponent() { return ( <div> {process.env.NODE_ENV !== "production" && isScreenshot() ? ( <div style={{ height: 400, background: "#888" }} /> ) : ( <iframe style={{ height: 400, width: "100%" }} src="https://example.com/hogehoge" /> )} </div> ); }
ͦΕͰμϝͳΒ skip - Ͳ͏ͯ͠ Flakiness Λ௵ͤͳ͍߹ɺͦͷέʔε(= Story) Λ ࣗಈςετର ֎ʹׂͯ͠Ε૭ԽΛࢭ͢Δ
- ίʔυΛมߋ͍ͯ͠ͳ͍ͷʹ CI Ͱ VRT ΛΒͤΔͨͼʹ͕ࠩग़ͯ͠· ͏ঢ়گΛ์ஔ͢ΔΑΓϚγ export const MyStory = { args: {}, // storybook/test-runner ͷ߹ tags: ["skip"], parameters: { screenshot: { // Storycap ͷ߹ skip: true, }, }, } satisfies Story;
͓ΘΓʹ - ίϯϙʔωϯτςετӡ༻ͷίπ - Slow Test / Flakey Test ݟա͝͞ͳ͍
- Off topics - Ұൠతͳࣗಈςετϊϋ (e.g. ςετίʔυͷೝෛՙରࡦ) ׆ ༻ͯ͠ɺΑΓշదͳϑϩϯτΤϯυςετΛࢦ͠·͠ΐ͏ - e.g. https://gihyo.jp/list/group/αόϯφศΓ- ~ ιϑτΣΞ։ൃͷ ߥΛੜ͖ൈ͘ ~
Thank you !