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
E2Eテストを継続するために
Search
Sponsored
·
Your Podcast. Everywhere. Effortlessly.
Share. Educate. Inspire. Entertain. You do you. We'll handle the rest.
→
Taketoshi Aono(青野健利 a.k.a brn)
December 04, 2018
1.1k
4
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
E2Eテストを継続するために
E2Eテストを継続していくためのあれこれ
Taketoshi Aono(青野健利 a.k.a brn)
December 04, 2018
More Decks by Taketoshi Aono(青野健利 a.k.a brn)
See All by Taketoshi Aono(青野健利 a.k.a brn)
document.write再考
brn
7
3.2k
Parsing Javascript
brn
14
9.6k
JSON & Object Tips
brn
1
600
CA 1Day Youth Bootcamp for Frontend LT
brn
0
1.1k
Modern TypeScript
brn
2
890
javascript - behind the scene
brn
3
820
tc39 proposals
brn
0
1k
プロダクト開発とTypeScript
brn
7
3k
React-Springでリッチなアニメーション
brn
1
780
Featured
See All Featured
The Cost Of JavaScript in 2023
addyosmani
55
10k
Organizational Design Perspectives: An Ontology of Organizational Design Elements
kimpetersen
PRO
1
830
Balancing Empowerment & Direction
lara
6
1.3k
Faster Mobile Websites
deanohume
310
32k
What's in a price? How to price your products and services
michaelherold
247
13k
Bash Introduction
62gerente
615
220k
Why Our Code Smells
bkeepers
PRO
340
58k
The untapped power of vector embeddings
frankvandijk
2
1.9k
The MySQL Ecosystem @ GitHub 2015
samlambert
251
13k
How STYLIGHT went responsive
nonsquared
100
6.3k
Practical Orchestrator
shlominoach
192
12k
Color Theory Basics | Prateek | Gurzu
gurzu
1
470
Transcript
None
Name !CSO ੨݈ར Occupation ϑϩϯτΤϯυΤϯδχΞɾ10 Company $ZCFSBHFOUΞυςΫελδΦ"*.FTTFOHFS OSS $POUSJCVUPSPG7
About IUUQJOGPCODI
"*ϝοηϯδϟʔʹ͍ͭͯ
None
"*ϝοηϯδϟʔ w גࣜձࣾ$ZCFS"HFOUΞυςΫελδΦͷࣄۀ෦ w #UP#UP$ͷ$IBU#PUࣄۀΛల։ w $IBU#PUͷ6*ɺࣗવݴޠॲཧΤϯδϯɺIEͷΦϖϨʔλʔΛશͯࣗલͰ࣋ͭ
&&ςετʹ͍ͭͯ
&&ςετͱ &OEUPFOEςετͷུޠ 8FCϑϩϯτΤϯυͷੈքͰɺػೳཁ݅ຖͷςετͰແ͘ɺͨ͠ ΞϓϦέʔγϣϯͷϢʔβʔΛϢʔβʔಉ༷ʹૢ࡞ͯ͠ػೳ͢Δ͜ͱ Λ֬ೝ͢Δςετ ࣮ࡍʹϒϥβΦʔτϝʔγϣϯπʔϧ 4FMFOJVN Λར༻ͯ͠ϒϥβ ͔Β6*Λૢ࡞͠ɺಈ࡞ͱ݁ՌͷϒϥοΫϘοΫεςετΛߦ͏
ϝϦοτ Ϣʔβʔ͕࣮ࡍʹ৮Δը໘Λࣗಈςετ͍ͯ͠Δ͚ͩͳͷͰɺςετͱ͠ ͯ࠷࣮֬ੑ͕ߴ͍ ͭ·Γेͳ&&ςετ͕͋Εͦͷૢ࡞Ͱ࣮֬ʹόά͕ى͖͍ͯͳ͍͜ ͱΛূ໌Ͱ͖Δ
σϝϦοτ ͍ ࣮ࡍʹϦΞϧͳΞϓϦέʔγϣϯΛಈ͔ͨ͢ΊɺΞχϝʔγϣϯɾ"1*ͷ ͕ͪ࣌ؒසൟʹൃੜ͠ɺਓؒͷૢ࡞ͷཧҎ্ͷ͕Ͱͳ͍ ·ͨɺ4FMFOJVNͷϒϥβΦʔτϝʔγϣϯπʔϧͷෆ҆ఆ͋͞Γɺ Ṗͷࣦഊ͕ൃੜͨ͠Γ͢ΔͷͰϦτϥΠ͕ඞࢸͳ্ɺ࣮ߦ͢ΔڥʹΑͬ ͯ݁Ռ͕มΘΔ͜ͱ͕͋Δ ͦͯ͠ɺԿΑΓϝϯςφϯε͕ͭΒ͍
ϝϯςφϯε
w $44ηϨΫλͰૢ࡞ରͷ%0.ΛબͿͨΊɺ6*ͷৄࡉ )5.-ͷߏ ͷมԽ·Ͱςετ ʹӨڹ͢Δ w TUZMFEDPNQPOFOUTͷΑ͏ͳ$44JO+4Λ͍ͬͯΔͱFF༻ͷηϨΫλΛผ్༻ҙ͢Δඞ ཁ͕͋Δ w
Ξαʔγϣϯ͠ͳ͚Ε͍͚ͳ͍߲͕ଟ͗ͯ͢ɺมߋՕॴ͕രൃతʹ૿͑ͯഁ͢Δ
͜ΕΒΛߟ͑ͣʹ&&Λ࣮͢Δͱ ͍͍ͩͨߋ৽͞Εͳ͘ͳΔ͔ɺ ௨ΔՕॴ͚ͩಈ͘ແҙຯͳςετ͕ग़དྷ্͕Δ
ղܾࡦ
·ͣɺղܾ͕؆୯ͳσϝϦοτ͔Βղܾ͍ͯ͘͠ w ͍ w &&ςετ࣮ߦ࣌ʹ+4ͰϑϥάΛཱͯͯΞχϝʔγϣϯΛఀࢭ͢Δ w ϒϥβΦʔτϝʔγϣϯπʔϧ͕ෆ҆ఆ w ϦτϥΠॲཧΛೖΕΔ w
#SPXTFS4UBDLͷ֎෦ڥΛར༻͢Δ ͬͯͳ͍
Ξχϝʔγϣϯͷఀࢭ ͲͷϒϥβΦʔτϝʔγϣϯπʔϧʹɺ͍͍ͩͨKBWBTDSJQUΛೖ͢Δ "1*͕͋ΔͣͳͷͰɺ ͷΑ͏ͳܗͰϑϥάΛϖʔδʹೖ͢Δ ྫQVQQFUFFS ͏߹ҎԼͷΑ͏ͳܗͰίʔυʹຒΊࠐΜͰ͓͘ ղܾࡦ await this.page.evaluate(`window.E2E_ENABLED
= true`); <div className={window.E2E_ENABLED ? "..." : "..."} />
ϦτϥΠॲཧ ݱঢ়ͷϒϥβΦʔτϝʔγϣϯπʔϧɺಉ࣮࣮ͯ͠ࡍʹϒϥβ Λ্ཱͪ͛Δ্ؔɺෆ҆ఆͳՕॴ͕ͬͯ͠·͏ ͦͷͨΊɺશମͷϦτϥΠॲཧΛೖΕΔ͜ͱͰɺ͋Δఔࣦഊڐ༰͢Δ ςετΊΔ ղܾࡦ
function runTest() { const browser = puppeteer.launch(...) const page =
browser.newPage(); ... let retryCount = 0; page.on('error', () => { if (++retryCount < 3) { setTimeout(runTest, 10); } }) page.on('pageerror', () => { if (++retryCount < 3) { setTimeout(runTest, 10); } }) }
֎෦αʔϏεͷར༻ 4FMFOJVNΛ͍ͬͯΕͦͷ··#SPXTFS4UBDLͷ֎෦αʔϏεΛར༻Ͱ ͖Δ ϩʔΧϧͰ࣮ߦ͢ΔΑΓΫϥυαʔϏεΛར༻ͨ͠΄͏͕ɺΑΓ҆ఆ͠ ͨςετڥΛಘΒΕΔ ͕ɺ࣌ؒͷؔͰ·ͩͬͯͳ͍ͷͰɺͦͷ͏ͪΓ͍ͨ ղܾࡦ
ϝϯςφϏϦςΟ
͜͜·Ͱൺֱతղܾ͕؆୯ͳ͕ͩͬͨɺ ࠜຊతʹ&&͕ϝϯςφϯε͠ਏ͍ͱ͍͏ղܾ͍ͯ͠ͳ͍ ͜ͷେ͖ͳʹରॲ͍ͯ͘͠
ϝϯςφϏϦςΟ ϝϯςφϏϦςΟΛ࣮ݱ͢ΔͨΊʹ࠷େࣄͳ͜ͱɺͰ͖Δ͚ͩߏʹ ཱͪೖΒͳ͍͜ͱͰ͋Δ ͦͷͨΊɺҎԼͷํ๏ͰϝϯςφϏϦςΟΛ֬อ͍ͯ͘͠ 7JTVBM3FHSFTTJPO5FTUΛಋೖ͢Δ ϒϥβૢ࡞ϨΠϠʔͷநԽ
7JTVBM3FHSFTTJPO5FTU 7JTVBM3FHSFTTJPO5FTUͱɺίʔυมߋલɾมߋޙͷεΫϦʔϯγϣοτ Λࠩൺֱͯ͠6*ʹ͕ແ͍͔֬ೝ͢ΔςετͰ͋Δ ֤ʑͷঢ়ଶΛ"TTFSUJPO͢ΔͷͰͳ͘6*ͷঢ়ଶΛࠩൺֱ͢Δ͜ͱͰίʔ υมߋͷӨڹΛ֬ೝ͢Δ 7JTVBM3FHSFTTJPO5FTUΛߦ͏πʔϧ৭ʑͱ͋Δ͕ɺࣗࣗ࡞͍ͯ͠Δ Ϣʔεέʔε͕νʔϜຖʹେ͖͘ҧ͏ͱࢥ͏ͷͰɺͦ͜νʔϜͰஅ ϝϯςφϏϦςΟ
มߋޙ มߋલ ൺֱ݁Ռ
7JTVBM3FHSFTTJPO5FTUΛߦ͏ͱΑ͘ൃੜ͢Δ w มԽ͕ແ͍ͣͳͷʹ͕ࠩൃੜ͢Δ w ظ͍ͯͨͣ͠ͷಈ࡞͕ߦΘΕ͍ͯͳ͍͕ɺԿ͕ى͖͔ͨΘ͔Βͳ͍ w ൺֱͷλΠϛϯά ϝϯςφϏϦςΟ7JTVBM3FHSFTTJPO5FTU
͕ࠩൃੜ͢Δ ͜Ε%J⒎Λߦ͏πʔϧͷͩͬͨΓϑΥϯτͷΞϯνΤΠϦΞεͩͬͨ Γ͢Δ ͳͷͰղܾࡦ w ""ΛΔ w #MJOL%J⒎Λ͏ ϝϯςφϏϦςΟ7JTVBM3FHSFTTJPO5FTU
""ΛΔ ϑΥϯτͷΞϯνΤΠϦΞεΛΔ͜ͱͰɺ͕ࠩൃੜͮ͠Β͘ͳΔ ϝϯςφϏϦςΟ7JTVBM3FHSFTTJPO5FTU͕ࠩൃੜ͢Δ
await page.evaluate( `(() => { const newStyle = document.createElement('style'); newStyle.type
= "text/css"; document.getElementsByTagName(‘head')[0] .appendChild(newStyle); const css = document.styleSheets[0]; const idx = document.styleSheets[0] .cssRules.length; css.insertRule( "body * {-webkit-font-smoothing: none ! important}”, idx ); })()`, );
#MJOL%J⒎Λ͏ ·ͨπʔϧͷͳέʔε͋Δ ৭ʑͬͯ࠷͕ى͖ͮΒ͔ͬͨͷ͕ɺ#MJOL%J⒎ͱ͍͏ը૾ࠩൺֱ πʔϧͩͬͨ IUUQTHJUIVCDPNZBIPPCMJOLEJ⒎ ࣍ͷϖʔδʹ৭ʑௐͯ͠ɺ࠷҆ఆͨ͠ઃఆΛࡌ͓ͤͯ͘ ϝϯςφϏϦςΟ7JTVBM3FHSFTTJPO5FTU͕ࠩൃੜ͢Δ
new BlinkDiff({ imageA: baselineImage, imageB: image, thresholdType: BlinkDiff.THRESHOLD_PERCENT, threshold: 0.0001,
imageOutputPath: failedFilePath, verbose: true, perceptual: true, delta: 25, })
ࣦഊͨ͠ཧ༝͕Θ͔Βͳ͍ 7JTVBM3FHSFTTJPO5FTUΛߦ͏ͱසൟʹ͜ͷέʔεʹૺ۰͢Δ ୯७ͳղܾࡦແ͍͕ɺଥڠҊ͍͔ͭ͋͘Δ ࠷γϯϓϧͳํ๏࣮ࡍʹϒϥβΛ(6*͖Ͱಈ࡞ͤ͞Δ͜ͱͩΖ͏ ͏Ұͭ෦తͳςετ࠶࣮ߦΛ༰қʹઃܭ͢Δ͜ͱ ޙड़ ϝϯςφϏϦςΟ7JTVBM3FHSFTTJPO5FTU
ൺֱͷλΠϛϯά جຊతʹɺϚʔδલʹ֤ݸਓͷϩʔΧϧͰ%PDLFS্Ͱ࣮ߦͨ݁͠ՌΛίϛοτ͢Δ εΫϦʔϯγϣοτGBJMFEDVSSFOUNBTUFSͷͭͷσΟϨΫτϦʹผΕ͓ͯΓɺ ϩʔΧϧͰ࣮ߦͨ݁͠ՌDVSSFOUɺࣦഊͨࠩ͠ൺֱը૾GBJMFEɺϦϞʔτͷ࠷ ৽ঢ়ଶNBTUFSʹͦΕͧΕอଘ͞ΕΔ ίϛοτ࣌ʹQSFDPNNJUϑοΫͰɺDVSSFOU͔ΒNBTUFSίϐʔ͞ΕͯϦϞʔτʹ ө͞ΕΔ ϚʔδͷλΠϛϯάͰ$*ͰNBTUFSͱൺֱͯ͠ͳ͚ΕϚʔδ ͕͋Ε࠶ϩʔΧϧͰ࣮ߦͯ͠ίϛοτ ͱ͍͏ӡ༻Λ͍ͯ͠Δ
ϝϯςφϏϦςΟ7JTVBM3FHSFTTJPO5FTU
8FC6* ࠩൺֱ݁ՌΛ8FCͷ6*Ͱ֬ೝɺঝೝͰ͖ΔΑ͏ʹͯ͋͠Δ ϝϯςφϏϦςΟ7JTVBM3FHSFTTJPO5FTU
None
ϒϥβૢ࡞ϨΠϠʔͷநԽ ͏ҰͭϝϯςφϏϦςΟͷͨΊʹॏཁͳͷɺ&&ςετͷίʔυ࣭Ͱ ͋Δ 7JTVBM3FHSFTTJPO5FTUʹΑͬͯɺͰ͖Δ͚ͩߏʹཱͪೖΒͳ͍Α͏ͳςε τ͕هड़Ͱ͖ΔΑ͏ʹͳ͕ͬͨɺϒϥβΛૢ࡞͢ΔͨΊʹͲ͏ͯ͠ ͋ΔఔߏʹཱͪೖΔඞཁ͕͋Δ ·ͨϒϥβΦʔτϝʔγϣϯπʔϧ༷ʑͳͷ͕͋Γɺ۩ମతͳૢ࡞ Λߦ͏ίʔυΛ͢Δ͜ͱͰπʔϧҠߦΛ༰қʹ͍ͨ͠ ئ ϝϯςφϏϦςΟ
(SBQI#BTFE1BHF0CKFDU 1BHF0CKFDUύλʔϯΛ׆༻ͭͭ͠ɺ࣮ߦܭըΛࣄલʹཱͯΔํࣜΛ࡞Γɺ উखʹ(SBQI#BTFE1BHF0CKFDUͱ໊͚ͨ 1BHF0CKFDUύλʔϯͱಉ͡Α͏ʹɺQVCMJDϝιου͕ૢ࡞Λද͠ɺ෦ͷૢ ࡞શͯӅṭ͞Ε͍ͯΔঢ়ଶʹͳ͍ͬͯΔ ͔͠͠ɺ1BHF0CKFDUύλʔϯΛ͞Βʹ֦ுͯ͠ɺૢ࡞Λ(SBQIͷϊʔυͱ͠ ͯѻ͏͜ͱͰૢ࡞ؒͷґଘؔΛཧͰ͖ΔΑ͏ʹͨ͠ ϝϯςφϏϦςΟϒϥβૢ࡞ϨΠϠʔͷநԽ
0QFSBUJPO Ϣʔβʔૢ࡞ͦͷͷ ϙοϓΞοϓΛ։͘ͱ͔ɺνΣοΫϘοΫεΛνΣοΫ͢Δͱ͍ͬͨߦಈ ͦΕΛͲ͏࣮ݱ͢Δ͔ʹؔ৺͕ͳ͍ ·੍ͨΛهड़͢Δ͜ͱͰɺࣄલݕ͕ࠪߦΘΕਖ਼͍͠ॱংͰ0QFSBUJPO͕࣮ ߦ͞Ε͍ͯΔͷΛݕࠪͰ͖Δ ϝϯςφϏϦςΟϒϥβૢ࡞ϨΠϠʔͷநԽ
&YFDVUJPO 0QFSBUJPOΛ࣮ݱ͢Δखஈ 1VQQFUFFSͷίʔυͱ͔4FMFOJVNͷίʔυ͕ฒͿ ϝϯςφϏϦςΟϒϥβૢ࡞ϨΠϠʔͷநԽ
0QFSBUJPO Ϣʔβʔૢ࡞ͷநԽ &YFDVUJPO ࣮ࡍͷίʔυ 0QFSBUJPO Ϣʔβʔૢ࡞ͷநԽ &YFDVUJPO ࣮ࡍͷίʔυ 0QFSBUJPO Ϣʔβʔૢ࡞ͷநԽ
&YFDVUJPO ࣮ࡍͷίʔυ operation( // ૢ࡞ͷ໊લ 'name', // ࣮ࡍͷॲཧ async () => { ... }, // ͜ͷॲཧͷ੍ Restriction.of( Restriction.Type.SUCCESSOR, // ࣄલʹߦ͏͖ॲཧͷ໊લ 'other-op-name' ), )
4DSFFOTIPU εΫϦʔϯγϣοτΛࡱΔͱɺݱࡏͷ0QFSBUJPO໊͕ϋΠϑϯͰ݁߹͞Εͨ ໊લͰอଘ͞ΕΔ 0QFSBUJPOͷॱ൪Λม͑ΔͱεΫϦʔϯγϣοτͷ໊લมΘΔ PQFOEP@TPNFUIJOHDMPTFQOHΈ͍ͨͳ໊લ ϝϯςφϏϦςΟϒϥβૢ࡞ϨΠϠʔͷநԽ
1BSUJBM&YFDVUJPO 0QFSBUJPO୯ҐͰ&&Λղ͠ɺ੍݅Λهड़Ͱ͖ΔΑ͏ʹͨ݁͠Ռ ಛఆͷ0QFSBUJPOͷΈΛඞཁ࠷ݶͷύεͰ࣮ߦͰ͖ΔΑ͏ʹͳͬͨ ϝϯςφϏϦςΟϒϥβૢ࡞ϨΠϠʔͷநԽ
0QFSBUJPO" 0QFSBUJPO# 0QFSBUJPO$ 0QFSBUJPO% 0QFSBUJPO& 0QFSBUJPO' 0QFSBUJPO( ΦϖϨʔγϣϯ(&ʹґଘ͓ͯ͠Γ &#ʹґଘ͍ͯ͠Δ ͜ΕΒࣄલʹ໌͍ͯ͠ΔͷͰɺ
(ͷΈΛ࣮ߦ͍ͨ͠߹ɺ #ɾ&ɾ(ͷॱংͰ0QFSBUJPO͕࣮ߦ͞ΕΔ
·ͱΊ &&ςετΛܧଓ͢ΔͨΊʹؤு͍ͬͯΔ͜ͱΛॻ͍͖ͯ·͕ͨ͠ɺ ࠷ޙΓɺ$*ͷཧɾϨϏϡʔମ੍ͷϓϩηε͕େࣄʹͳΓ·͢ ϓϩηε͕Ξτϓοτ࣭ΛܾΊΔͷͰɺͦ͏͍͏ϓϩηεߏஙಉ࣌ ʹؤு͍͖ͬͯ·͠ΐ͏
3FDSVUJOH "*ϝοηϯδϟʔͰϑϩϯτΤϯδχΞΛେืूͰ͢ʂ ҎԼʹϐϯͱ͘Δํ5XJUUFSͰͳΜͰ͔͚͍ͯͩ͘͞ʂ w 5ZQF4DSJQU w 3Y+4 w 3FBDU