Slide 1

Slide 1 text

͍Βͳ͍$44Λ
 1VQQFUFFSͰফ͢ !QJSPTJLJDL 8FC (PPHMF*0ͷ8FCΛ·ͱΊΔձ

Slide 2

Slide 2 text

ࣗݾ঺հ w !QJSPTJLJDL w αΠϘ΢ζגࣜձࣾ
 ϑϩϯτΤϯυΤΩεύʔτνʔϜ w طʹ͝ଘ஌ͩͱࢥ͍·͕͢ɺ
 ࡢ೔ɺ௕ঁ͕࢈·Ε·ͨ͠!

Slide 3

Slide 3 text

࠷ۙ΍͍ͬͯΔ࢓ࣄ w ڊେͳ$44ͷTUZMFEDPNQPOFOUTԽ w ສߦ͋Δ͕ɺશͯͷελΠϧ͕ඞཁͳΘ͚Ͱ͸ͳ͍ w ͦͷଞͷ໰୊ w NJODTTͱ͍͏֦ுࢠͳͷʹѹॖ͞Ε͍ͯͳ͍ w CPPUTUSBQ΍GPOUBXFTPNFͷελΠϧΛ্ॻ͖͍ͯ͠Δ w ৄࡉ౓͕ߴ͗͢ΔελΠϧ͕݁ߏ͋ΔFUD

Slide 4

Slide 4 text

Ͳ͏ઓ͑͹Α͍ͷ͔ Θ͔ΒΜ

Slide 5

Slide 5 text

.PEFSO8FC5FTUJOHBOE"VUPNBUJPOXJUI1VQQFUFFS IUUQTXXXZPVUVCFDPNXBUDI W.CO"5-$V,* 1VQQFUFFSͰ +4ɾ$44ͷΧόϨοδ͕ औΕ·͢

Slide 6

Slide 6 text

͜ͷػೳΛ࢖͑͹ ࢖ͬͯͳ͍ελΠϧΛ ୳͠ग़ͤΔͷͰ͸ʁ

Slide 7

Slide 7 text

1VQQFUFFSͰ $44ͷΧόϨοδΛऔಘ const puppeteer = require('puppeteer'); (async () => { // ブラウザの起動 const browser = await puppeteer.launch(); const page = await browser.newPage(); // カバレッジの収集を開始 await page.coverage.startCSSCoverage(); // カバジッジを取りたいページを徘徊 await page.goto(…); … // カバレッジの収集を終了 const cssCoverage = await page.coverage.stopCSSCoverage(); … })();

Slide 8

Slide 8 text

QVQQFUFFSUPJTUBOCVMͰ OZD͕ॲཧՄೳͳϑΥʔϚοτʹม׵ const pti = require('puppeteer-to-istanbul'); // .nyc_output/*を生成 pti.write(cssCoverage);

Slide 9

Slide 9 text

)5.-ܗࣜͷϨϙʔτΛੜ੒ w OQYOZDSFQPSUSFQPSUFSIUNM w DPWFSBHFҎԼʹ)5.-Λग़ྗ w PQFODPWFSBHFJOEFYIUNM

Slide 10

Slide 10 text

εΫγϣషΔ

Slide 11

Slide 11 text

खಈͰফ͢ͷਏͦ͏ ΧόϨοδ͔ΒࣗಈͰ ফͤͳ͍͔ʁ

Slide 12

Slide 12 text

OZD@PVUQVUͷத਎ w PVUKTPO w ֤ϑΝΠϧͷΧόϨοδ৘ใ w KTDTTKT w $44ϑΝΠϧͦͷ΋ͷ w ֦ுࢠ͕KTʹͳ͍ͬͯΔͷ͸Ṗ

Slide 13

Slide 13 text

OZD@PVUQVUPVUKTPOͷ TϑΟʔϧυ͕࢖͑ͦ͏ // .nyc_output/out.jsonの構造 { "ファイルパス": { "path": "ファイルパス", "s": { "行数": 0 or 1 // 1の場合、カバレッジ有り … }, … }, … }

Slide 14

Slide 14 text

ෆཁͳߦΛফ͢ॲཧʢΠϝʔδʣ const fs = require('fs'); const readline = require('readline'); // out.jsonのsフィールドから不要な行を消す処理のイメージ const removeUnusedLines = (filePath, s) => new Promise(resolve => { const reader = readline.createInterface({ input: fs.createReadStream(filePath) }); let currentLine = 0; const lines = []; // ファイルから1行ずつ読む reader.on('line', line => { // カバレッジがある行を残す if (s[currentLine++]) { lines.push(line); } }); reader.on('close', () => resolve(lines)); });

Slide 15

Slide 15 text

݁Ռ w ΧόϨοδ͕໿͔͠ͳ͔ͬͨ w ສߦˠߦ w ·ͩଟ͍͕ΪϦΪϦઓ͑Δߦ਺ʹͳͬͨ

Slide 16

Slide 16 text

ϋϚͬͨͱ͜Ζ

Slide 17

Slide 17 text

QBHFHPUPͷͨͼʹ ΧόϨοδ͕Ϧηοτ͞ΕΔ w ҎԼͷΑ͏ʹରॲ w HPUPຖʹΧόϨοδΛੜ੒ w QUPJXSJUF͸ҰͭͷΧόϨοδ͔͠ड͚෇͚ͳ͍ͷͰ w ෳ਺ͷΧόϨοδΛϚʔδͯ͠
 ҰͭͷΧόϨοδΛੜ੒

Slide 18

Slide 18 text

QVQQFUFFS͕ग़ྗ͢Δ ΧόϨοδͷߏ଄ [ { url: "ファイルのURL", text: "ファイルの中身", ranges: [ // カバレッジの開始位置・終了位置の配列 { start: 0, end: 100 }, … ] }, … ]

Slide 19

Slide 19 text

ෳ਺ͷΧόϨοδΛϚʔδ { url: "ファイルA", text: "…", ranges: [ { start: 0, end: 100 }, { start: 201, end: 300 } ] } { url: "ファイルA", text: "…", ranges: [ { start: 101, end: 200 }, { start: 250, end: 350 } ] } ΧόϨοδͦͷ ΧόϨοδͦͷ { url: "ファイルA", text: "…", ranges: [ { start: 0, end: 100 }, { start: 101, end: 200 }, { start: 201, end: 350 } ] }

Slide 20

Slide 20 text

ΧόϨοδ͕ൃੜ͠ͳ͍ w !NFEJBએݴɺ!GPOUGBDFએݴʹ͸
 ΧόϨοδ͕ൃੜ͠ͳ͍ w *TTVFʹొ࿥͞Ε͍͕ͯͨόά͔࢓༷͔͸෼͔Βͳ͍ w ҎԼͷΑ͏ʹରॲ w !GPOUGBDFએݴ͸ΧόϨοδ͋Γͳؔ͠ΘΒͣ࢒͢ w !NFEJBએݴ಺ͷελΠϧʹΧόϨοδ͕͋Δ৔߹͸
 ࢒͢

Slide 21

Slide 21 text

͓ΘΓ w 1VQQFUFFS͸&&ςετҎ֎ͷ࢖͍ํ΋Ͱ͖Δʂ w ࠷ऴతʹ͸εΫγϣΛऔ͓͍ͬͯͯ
 ը૾ࠩ෼Λग़ͤΔΑ͏ʹͯ͠ΑΓ࣮֬ʹෆཁͳελΠϧΛ ফͤΔΑ͏ʹͨ͠

Slide 22

Slide 22 text

͋Γ͕ͱ͏ ͍͟͝·ͨ͠