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
E2Eテストを継続するために
Search
Taketoshi Aono(青野健利 a.k.a brn)
December 04, 2018
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
6
3.2k
Parsing Javascript
brn
14
9.5k
JSON & Object Tips
brn
1
570
CA 1Day Youth Bootcamp for Frontend LT
brn
0
1.1k
Modern TypeScript
brn
2
880
javascript - behind the scene
brn
3
810
tc39 proposals
brn
0
990
プロダクト開発とTypeScript
brn
7
3k
React-Springでリッチなアニメーション
brn
1
770
Featured
See All Featured
Why Your Marketing Sucks and What You Can Do About It - Sophie Logan
marketingsoph
0
170
The Limits of Empathy - UXLibs8
cassininazir
1
360
No one is an island. Learnings from fostering a developers community.
thoeni
21
3.8k
Easily Structure & Communicate Ideas using Wireframe
afnizarnur
194
17k
CoffeeScript is Beautiful & I Never Want to Write Plain JavaScript Again
sstephenson
162
16k
New Earth Scene 8
popppiees
3
2.3k
Making Projects Easy
brettharned
120
6.7k
JAMstack: Web Apps at Ludicrous Speed - All Things Open 2022
reverentgeek
1
480
WCS-LA-2024
lcolladotor
0
650
Game over? The fight for quality and originality in the time of robots
wayneb77
1
200
Navigating the moral maze — ethical principles for Al-driven product design
skipperchong
2
390
Designing for Timeless Needs
cassininazir
1
260
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