Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
上手に付き合うコンポーネントテスト
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
TypeScript LSP の今までとこれから
quramy
1
2k
フロントエンドテストの育て方
quramy
12
3.8k
App Router 悲喜交々
quramy
8
730
Patched fetch did not work
quramy
6
790
GraphQL あるいは React における自律的なデータ取得について
quramy
18
5.8k
Next.js App Router
quramy
15
3.9k
Fragment Composition of GraphQL
quramy
17
4.8k
reg-viz VRT tools
quramy
4
1.7k
NoInfer
quramy
0
380
Other Decks in Programming
See All in Programming
AI時代のUIはどこへ行く?その2!
yusukebe
22
7.5k
AI 時代のソフトウェア設計の学び方
masuda220
PRO
29
13k
LaravelLive Japan の裏方のすべて — 第188回 PHP勉強会@東京 (2026-06-24)
suguruooki
2
110
コンテキストの使い捨てをやめる — ビジネスルール駆動開発と miko —
ioki
0
230
Agentic UI
manfredsteyer
PRO
0
190
AIだと陥りがちなJakarta EE最新技術への移行時の落とし穴と解決策
tnagao7
0
120
Mujeres en SEO Summit 2026 - Greatest Disaster Hits en Web Performance
guaca
0
200
Snowflake Summitでの新機能 CoCo / CoWork / snowflake-summit-2026-overall-what-new-coco
tatsuhiro
1
170
脅威をエンジニアリングの糧にして――現場編 / Turning Threats into Engineering Fuel — Field Edition
nrslib
0
300
Language Server 使ってる? 〜VSCode と Zed の場合〜 / Are you using a Language Server? ~For VS Code and Zed~
handlename
0
800
TSKaigi Night Talks 2026_TypeScriptでサプライチェーンの整合性を型に閉じ込める
geekplus_tech
0
400
Skillsは効率化、Agentsは"自分の拡張"——Builder時代のエージェント編成(CC Night 2026)
wemra
1
150
Featured
See All Featured
So, you think you're a good person
axbom
PRO
2
2.1k
StorybookのUI Testing Handbookを読んだ
zakiyama
31
6.8k
Jamie Indigo - Trashchat’s Guide to Black Boxes: Technical SEO Tactics for LLMs
techseoconnect
PRO
0
180
Navigating the Design Leadership Dip - Product Design Week Design Leaders+ Conference 2024
apolaine
1
360
Public Speaking Without Barfing On Your Shoes - THAT 2023
reverentgeek
1
430
CSS Pre-Processors: Stylus, Less & Sass
bermonpainter
360
30k
Redefining SEO in the New Era of Traffic Generation
szymonslowik
1
340
Claude Code どこまでも/ Claude Code Everywhere
nwiizo
65
56k
Responsive Adventures: Dirty Tricks From The Dark Corners of Front-End
smashingmag
254
22k
How to Talk to Developers About Accessibility
jct
2
250
Game over? The fight for quality and originality in the time of robots
wayneb77
1
200
Performance Is Good for Brains [We Love Speed 2024]
tammyeverts
12
1.7k
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 !