ãã®èšäºã¯ã€ã¿ãªã¢ã®ããã°ã©ããŒValentino Gagliardiã«ãã£ãŠæžãããŸããã 圌ã¯ãPuppeteerã®ãªãªãŒã¹åŸããã«ããã®ã©ã€ãã©ãªãšJestã䜿çšããŠWebã€ã³ã¿ãŒãã§ã€ã¹ã®ãã¹ããèªååããããšã«èå³ãæã€ããã«ãªã£ããšèšããŸãã ãã®åŸã圌ã¯å®éšãå§ããŸããã

ããã§ã¯ãWebãã©ãŒã ããã¹ãããäŸã«ãã£ãŠãPuppeteerãšJestã§äœæ¥ããåºæ¬ã«ã€ããŠèª¬æããŸãã ãŸãããŠãŒã¶ãŒã€ã³ã¿ãŒãã§ãŒã¹ã䜿çšããŠããŸãã¯äœ¿çšããã«Chromiumã䜿çšããæ©èœãããã³WebããŒãžã®ãã¹ããšäœæ¥ç°å¢ã®æŽçã®ããŸããŸãªåŽé¢ã«é¢ããããã€ãã®æçšãªããšã«ã€ããŠã説æããŸãã Valentinoã¯ãPuppeteerã¯æ¯èŒçæ°ããããŒã«ã§ãããAPIã¯å€æŽãããå¯èœæ§ãé«ããã®ã®ãWebéçºè
ã®æŠåšåº«ã§æ£åœãªäœçœ®ãå ããå¯èœæ§ããããšèããŠããŸãã
åé¡ã®ãã¹ãã®ããã€ãã®æ©èœã«ã€ããŠ
æè¿ãã€ã³ã¿ãŒãã§ã€ã¹ãã¹ããæžããã®ãšåæã«
ã Kent S. Doddsã
data-*
å±æ§ã䜿çšããŠãã¹ãã®å®å®æ§ãæ¹åãããšãã
èšäºã«åºäŒããŸããã ããã¯ãäžèšã§èšãã°ãã»ãšãã©ãã¹ãŠã®HTMLèŠçŽ ã«èšå®ã§ããã«ã¹ã¿ã å±æ§ã§ãã JavaScriptããã°ã©ã ãšã®ããŒã¿äº€æãæŽçãããšãã«ç¹ã«åœ¹ç«ã¡ãŸãã
ã±ã³ãã®è³æã¯éåžžã«æééãã«æ¥ãŸãããããã¯ã次ã®æ§é ã䜿çšããããã§ãã
await page.waitForSelector("#contact-form"); await page.click("#name"); await page.type("#name", user.name);
ããã§ã¯ãäž»ã«ãµãŒããŒããã°ã©ãã³ã°ãæ±ã£ãŠããããšã«æ³šæããŠãã ããã ãããŠãç§ã¯ãŸã ãã¹ãã§ã®
data-*
ã®äœ¿çšããã£ã³ããŒã³ããŠããŸããããããã«ãããããããããã¯çŽ æŽãããã¢ãããŒãã§ããããšãèªããªããã°ãªããŸããã ããã¯ç¹ã«å€§èŠæš¡ãªã¢ããªã±ãŒã·ã§ã³ã§åœ¹ç«ã¡ãŸãããããã§ã¯ãåçŽãªäŸã§ã¯ãèŠçŽ ã«ã¢ã¯ã»ã¹ããå€å
žçãªæ¹æ³ã䜿çšããŸãã
ãã£ãŒãããã¯ãã©ãŒã ã®ãã¹ã
ãããã£ãŠãç§ãã¡ã®ç®æšã¯ãç§ãåãçµãã§ãã
ãã®ããŒãžã®ãã£ãŒãããã¯ãã©ãŒã ããã¹ãããããšã§ãã ãã©ãŒã ã¯æ¬¡ã®ãšããã§ãã
次ã®èŠçŽ ãå«ãŸããŸãã
- ååãå
¥åããããã®ãã£ãŒã«ãã
- ã¡ãŒã«ã¢ãã¬ã¹ãå
¥åãããã£ãŒã«ãã
- é»è©±å
¥åãã£ãŒã«ãã
- ä»»æã®ããã¹ããå
¥åããé åã
- ãŠãŒã¶ãŒãããŒã¿åŠçã®ã«ãŒã«ã«åæããããã«èšå®ããããšã«ãããã§ãã¯ããã¯ã¹ã
- ãã¿ã³éä¿¡ãã©ãŒã ã
ãã¹ãäžããã©ãŒã ã®ç¶æ
ã確èªããå¿
èŠããããŸããã€ãŸãããµã€ã蚪åè
ããã©ãŒã ã䜿çšããŠäŒç€Ÿã«ãªã¯ãšã¹ããéä¿¡ã§ããããšã確èªããå¿
èŠããããŸãã
ãããžã§ã¯ãã®ã»ããã¢ãã
å§ããããã«ããã¹ãã®èªååã«äœ¿çšããããŒã«ã詳ããèŠãŠã¿ãŸãããã
Jestã¯ãFacebookãéçºãããã¹ããã¬ãŒã ã¯ãŒã¯ã§ãã Jestã¯ãèªåãã¹ãçšã®ãã©ãããã©ãŒã ãšãã¹ããŒãã¡ã³ããäœæã§ããããŒã¹ã©ã€ãã©ãªïŒExpectïŒãæäŸããŸãã
Puppeteerã¯Node.jsã®ã©ã€ãã©ãªã§ããŠãŒã¶ãŒã€ã³ã¿ãŒãã§ã€ã¹ãªãã§Chromiumãã©ãŠã¶ãå¶åŸ¡ã§ããŸãã ãã®ããŒã«ã¯éåžžã«æ°ãããããè©ŠããŠã¿ãŠãç¹å®ã®ãããžã§ã¯ãã§å¿
èŠãã©ãããå¿
èŠã«å¿ããŠæ¢åã®ãšã³ã·ã¹ãã ã«çµ±åããæ¹æ³ã«ã€ããŠèããŠã¿ãŸãããã
Fakerã¯ãã©ã³ãã ããŒã¿ãçæã§ããNode.jsã®ã©ã€ãã©ãªã§ãã ãããã®äžã«ã¯ãååãé»è©±çªå·ãäœæããããŸãã ã¡ãªã¿ã«ãããã¯PHPã®Fakerã®ãããªãã®ã§ãã
å®éšãããããžã§ã¯ããæ¢ã«ããå Žåã¯ã次ã®ã³ãã³ãã§å¿
èŠãªã©ã€ãã©ãªãã€ã³ã¹ããŒã«ã§ããŸãã
npm i jest puppeteer faker
Puppeteerã®ã€ã³ã¹ããŒã«ã«ã¯æéãããããŸããããã¯ããšããããã©ã€ãã©ãªã®ã€ã³ã¹ããŒã«äžã«Chromiumãã©ãŠã¶ãŒãã€ã³ã¹ããŒã«ãããããã§ãã
Chromiumã¯ãGoogle Chromeã®åºç€ã§ãããªãŒãã³ãœãŒã¹ã®ãŠã§ããã©ãŠã¶ã§ãã ChromiumãšChromeã®æ©èœã¯ã»ãŒåãã§ãããäž»ãªéãã¯ã©ã€ã»ã³ã¹æ©èœã«ãããŸãã
å¿
èŠãªãã®ããã¹ãŠã€ã³ã¹ããŒã«ããããã
package.json
Jestãæ§æããŸãã
test
ã³ãã³ãã¯ãJestå®è¡å¯èœãã¡ã€ã«ãæãå¿
èŠããããŸãã
"scripts": { "test": "jest" }
ããã«ãJestã§ã¯ããã®æ§é ã䜿çšããããšã奜ã¿ãŸãã
import puppeteer from "puppeteer";
ããã§ãJestã«Babelãå¿
èŠã§ãã
npm i babel-core babel-jest babel-preset-env
Babelã®ã€ã³ã¹ããŒã«åŸããããžã§ã¯ããã©ã«ããŒã«æ¬¡ã®å
容ã®
.babelrc
ãã¡ã€ã«ãäœæããŸãã
{ "presets": ["env"] }
ããã§æºåãå®äºãããã¹ãã®äœæãéå§ã§ããŸãã
ãã¹ããæžã
ãããžã§ã¯ããã©ã«ãã«æ°ãããã£ã¬ã¯ããªãäœæããŸãã
test
ãŸãã¯
spec
ãšåŒã¶ããšãã§ããŸãã 次ã«ããã®ãã£ã¬ã¯ããªã§
form.spec.js
ãã¡ã€ã«ãäœæããŸãã
ããã§ãã€ã³ããŒãã»ã¯ã·ã§ã³ããå§ããŠããã¹ãã³ãŒããéšåçã«æ€èšããããšãææ¡ããŸãã 以äžã«ããã®ãã¹ãŠã®ã³ãŒãå
šäœã瀺ããŸãã
ãŸããFakerãšPuppeteerãã€ã³ããŒãããŸãã
import faker from "faker"; import puppeteer from "puppeteer";
次ã«ããã©ãŒã ã®URLãèšå®ããŸãã ãããããæ¬çªãµã€ãã«æ¥ç¶ãã代ããã«ãéçºäžã®ããŒã«ã«ã§äœ¿çšå¯èœãªãã©ãŒã ã®ããŒãžã§ã³ããã¹ãããããšã«ããŸãã
const APP = "https://www.change-this-to-your-website.com/contact-form.html"
次ã«ãFakerã䜿çšããŠããããŒãŠãŒã¶ãŒãäœæããŸãã
const lead = { name: faker.name.firstName(), email: faker.internet.email(), phone: faker.phone.phoneNumber(), message: faker.random.words() };
次ã«ãPuppeteerã§äœæ¥ããããã«å¿
èŠãªããã€ãã®å€æ°ãå®çŸ©ããŸãã
let page; let browser; const width = 1920; const height = 1080;
次ã«ãPuppeteerã®åäœãèšå®ããŸãã
beforeAll(async () => { browser = await puppeteer.launch({ headless: false, slowMo: 80, args: [`--window-size=${width},${height}`] }); page = await browser.newPage(); await page.setViewport({ width, height }); }); afterAll(() => { browser.close(); });
ããã§ã¯ãJest
beforeAll
ããã³
afterAll
ã䜿çšã
afterAll
ã ãã¹ããå®è¡ããåã«ãPuppeteerã䜿çšããŠãã©ãŠã¶ãŒãèµ·åããå¿
èŠããããããæåã®ãã®ãå¿
èŠã§ãã ãã©ãŠã¶ãèµ·åããåŸãæ°ããããŒãžãéãããšãã§ããŸãã ãã¹ããå®äºãããããã©ãŠã¶ãéããå¿
èŠããããŸãã ããã¯ã
browser.close()
ã³ãã³ãã䜿çšããŠ
afterAll
ã¡ãœããã§å®è¡ãããŸãã
afterAll
ãš
afterAll
ã ãã«éå®ãããªãããšã«æ³šæããŠãã ããã Jestã®ãã®ä»ã®æ©èœã«ã€ããŠã¯ããã®ã©ã€ãã©ãªã®
ããã¥ã¡ã³ããã芧ãã ããã ãããã®å Žåã§ããåã
ã®ãã¹ãããšã«ãã©ãŠã¶ãŒãéãããéãããããã®ã§ã¯ãªãã1ã€ã®ãã©ãŠã¶ãŒã€ã³ã¹ã¿ã³ã¹ã䜿çšããŠãã¹ãã¹ã€ãŒãå
šäœãå®è¡ããããšããå§ãããŸãã
ããã§ãäžèšã®ã³ãŒãã¹ããããã«ã€ããŠããã€ãã³ã¡ã³ãããããšæããŸãã ã€ãŸãã
headless: false
ãã©ã¡ãŒã¿ãŒã䜿çšããŠãã©ãŠã¶ãŒããŠã£ã³ããŠã¢ãŒãã§èµ·åããããšã«æ³šæããŠãã ããã ãã®å Žåãããã¯ããããªã®ç»é¢ã§äœãèµ·ãã£ãŠããããèšé²ãããã¹ãããã»ã¹ã衚瀺ã§ããããã«ããããã«è¡ãããŸãã 説æããããŒã«ã䜿çšããŠå®éã®ãã¹ããå®è¡ãããšãéåžžãäœãèµ·ãã£ãŠããã®ãã芳å¯ããå¿
èŠã¯ãããŸããã ã€ã³ã¿ãŒãã§ãŒã¹ãªãã§ãã©ãŠã¶ãèµ·åããã«ã¯ã
launch()
ã¡ãœãããåŒã³åºããšãã«äœ¿çšãããã©ã¡ãŒã¿ãåé€ããã ãã§ãã
åãããšã¯
setViewPort()
ã³ãã³ãã«ã
setViewPort()
ãŸããããã®ã³ãã³ããåé€ã§ããŸãã ãŸãã¯ãããã«è¯ãããšã«ã2ã€ã®ç°ãªããã¹ãç°å¢ãã»ããã¢ããã§ããŸãã 1ã€ã¯èŠèŠçãªãããã°ã«äœ¿çšãããŸãïŒããã«ã€ããŠã¯ä»¥äžã§èª¬æããŸãïŒã2ã€ç®ã¯ãŠãŒã¶ãŒã€ã³ã¿ãŒãã§ã€ã¹ãªãã§ãã©ãŠã¶ãŒãæäœããããã§ãã
次ã«ããã¹ãã³ãŒããèšè¿°ããŸãã
describe("Contact form", () => { test("lead can submit a contact request", async () => { await page.waitForSelector("[data-test=contact-form]"); await page.click("input[name=name]"); await page.type("input[name=name]", lead.name); await page.click("input[name=email]"); await page.type("input[name=email]", lead.email); await page.click("input[name=tel]"); await page.type("input[name=tel]", lead.phone); await page.click("textarea[name=message]"); await page.type("textarea[name=message]", lead.message); await page.click("input[type=checkbox]"); await page.click("button[type=submit]"); await page.waitForSelector(".modal"); }, 16000); });
Jestã§async / awaitã³ã³ã¹ãã©ã¯ã
ã䜿çšããå¯èœæ§ã«æ³šæããŠãã ããã ããã§ã¯ãNode.jsã®ææ°ããŒãžã§ã³ã®1ã€ã䜿çšããŠãã¹ããå®è¡ãããããšãåæãšããŠããŸãã
ãããã®ãã¹ããæ€èšããŠãã ããã ãœãããŠã§ã¢å¶åŸ¡ãã©ãŠã¶ãå®è¡ããæé ã¯æ¬¡ã®ãšããã§ãã
- APPå®æ°ã§æå®ãããã¢ãã¬ã¹ã«ç§»åããŸãã
- ãã£ãŒãããã¯ãã©ãŒã ã®è¡šç€ºãåŸ
ã£ãŠããŸãã
- ãã£ãŒã«ããã¯ãªãã¯ããŠãããŒã¿ãå
¥åããŸãã
- ãã§ãã¯ããã¯ã¹ããªã³ã«ããŸãã
- ãã©ãŒã ãéä¿¡ããŸãã
- ã¢ãŒãã«ãŠã£ã³ããŠã衚瀺ãããã®ãåŸ
æ©ããŠããŸãã
Jasmine
test()
é¢æ°ã¯ã2çªç®ã®ãã©ã¡ãŒã¿ãŒãšããŠãã¿ã€ã ã¢ãŠãïŒ16000ïŒãæž¡ãããããšã«æ³šæããŠãã ããã ããã«ããããã©ãŠã¶ãããŒãžã§ã©ã®ããã«æ©èœããããæ£ç¢ºã«ç£èŠã§ããŸãã
ç»é¢ã«è¡šç€ºããããã©ãŠã¶ã䜿çšããŠãã¹ãããã¿ã€ã ã¢ãŠããèšå®ããªããšã次ã®ãšã©ãŒãçºçããŸãã
Timeout - Async callback was not invoked within timeout specified by jasmine.DEFAULT_TIMEOUT_INTERVAL
ã€ã³ã¿ãŒãã§ã€ã¹ãªãã§ãã©ãŠã¶ãèµ·åããŠãã¹ããå®è¡ããå Žåãã¿ã€ã ã¢ãŠããåé€ã§ããŸãã
ããã§ãã¹ãŠã®æºåãæŽãã次ã®ã³ãã³ãã§ãã¹ããéå§ã§ããŸãã
npm test
ãã®åŸããã©ãŠã¶ãç£èŠããã ãã§ããã©ãŠã¶èªäœãããŒãžã§åäœããŸãã
èå³ãããå Žåããã®ç»é¢ã®ãããªã¯ã
recordmydesktop
ãšæ¬¡ã®ã³ãã³ãã䜿çšããŠFedoraã§èšé²ãããŸããã
recordmydesktop --width 1024 --height 768 -x 450 -y 130 --no-sound
ãã ããããã ãã§ã¯ãããŸããã
ä»ã®ã€ã³ã¿ãŒãã§ãŒã¹èŠçŽ ã®ãã¹ã
ãã©ãŒã ãç解ããã®ã§ãä»ã®ããŒãžèŠçŽ ããã¹ãã§ããŸãã
<title></title>
ããŠãç¶æ³ã確èªããŸãããã ãåãã®ãšãããæå³ã®ããããŒãžã¿ã€ãã«ãå¿
èŠã§ãã
describe("Testing the frontend", () => { test("assert that <title> is correct", async () => { const title = await page.title(); expect(title).toBe( "Gestione Server Dedicati | Full Managed | Assistenza Sistemistica" ); });
ããã²ãŒã·ã§ã³ããŒã¯ã©ãã§ããïŒ åœŒå¥³ã¯ããŒãžã«ååšããå¿
èŠããããŸãã ãã®å ŽåãJestãšPuppeteerã«ç¢ºèªããŠãã ããã
// test("assert that a div named navbar exists", async () => { const navbar = await page.$eval(".navbar", el => (el ? true : false)); expect(navbar).toBe(true); }); //
ç¹å®ã®èŠçŽ ã«å«ãŸããã¹ãããã¹ããå«ãŸããŠãããã©ããã確èªã§ããŸãã
// test("assert that main title contains the correct text", async () => { const mainTitleText = await page.$eval("[data-test=main-title]", el => el.textContent); expect(mainTitleText).toEqual("GESTIONE SERVER, Full Managed"); }); //
æ€çŽ¢ãšã³ãžã³æé©åã®ããã«ããŒãžããã¹ãããã®ã¯ã©ãã§ããïŒ ããšãã°ã
æ£èŠãªã³ã¯ã確èªããŸãã
describe("SEO", () => { test("canonical must be present", async () => { await page.goto(`${APP}`); const canonical = await page.$eval("link[rel=canonical]", el => el.href); expect(canonical).toEqual("https://www.servermanaged.it/"); }); });
åãååã«ãããä»ã®å€ãã®ãã¹ããäœæã§ããŸãã
ãã®çµæããã¹ãŠã®ãã¹ããæ£åžžã«å®äºããŸãããããã¯ãç·è²ã®å¿å°ããã¡ãã»ãŒãžã§å€æã§ããŸãã
èŠèŠçãªãããã°
Puppeteerã䜿çšãããšããŠãŒã¶ãŒã€ã³ã¿ãŒãã§ãŒã¹ã䜿çšããŠããŸãã¯äœ¿çšããã«èµ·åããChromiumã§äœæ¥ãèªååã§ãããšæ¢ã«è¿°ã¹ãŸããã 次ã®ã³ãŒãã¹ãããããæãåºããŠãã ããã
beforeAll(async () => { browser = await puppeteer.launch({ // headless: false, slowMo: 80, args: [`--window-size=1920,1080`] }); page = await browser.newPage(); /// });
ããã«ãã°ã©ãã£ã«ã«ã€ã³ã¿ãŒãã§ã€ã¹ã§ãã©ãŠã¶ãŒãèµ·åãããšãã¯ãJasmineã¿ã€ã ã¢ãŠããã©ã¡ãŒã¿ãŒãæž¡ãå¿
èŠãããããšã«æ³šæããå¿
èŠããããŸãã ããããªããšããã¹ããããã«äºæããçµäºããŸãã ã¿ã€ã ã¢ãŠãã¯ã
test()
ã¡ãœããã®2çªç®ã®åŒæ°ã§ãã
describe("Contact form", () => { test( "lead can submit a contact request", async () => { ///// }, 16000 // <<< - Jasmine )
èªåãã¹ãã§ã¯ããã©ãŠã¶ãŠã£ã³ããŠã衚瀺ããå¿
èŠã¯ãããŸãããããããªããšãå°ãªããšãããã€ãã®æ·±å»ãªãã¹ãã¹ã€ãŒãã®å®è¡ã«æéãããããŸãã ãã ããã³ãŒãããå¶åŸ¡ããããã©ãŠã¶ãŒã§äœãèµ·ããããèŠããšäŸ¿å©ãªå ŽåããããŸãã ã€ã³ã¿ãŒãã§ã€ã¹ã®ãããã©ãŠã¶ãšãªããã©ãŠã¶ã䜿çšããŠããã¹ããç°¡åã«åãæ¿ããæ¹æ³ã¯ïŒ
ãã®åé¡ã¯ãè£å©é¢æ°ãäœæããããšã§è§£æ±ºã§ããŸãã ãããå®è¡ããŠã
testingInit.js
ãã¡ã€ã«ã«å
¥ããŸãããã
export const isDebugging = () => { let debugging_mode = { puppeteer: { headless: false, slowMo: 80, args: [`--window-size=1920,1080`] }, jasmine: 16000 }; return process.env.NODE_ENV === "debug" ? debugging_mode : false; };
次ã«ããã¹ãã³ãŒãã䜿çšããŠãã¡ã€ã«ããã¢ã¯ã»ã¹ããæåã«ã€ã³ããŒãããŠããããã©ãŠã¶ã®èµ·åæã«äœ¿çšããŸãã
/// import { isDebugging } from "./testingInit.js"; /// beforeAll(async () => { browser = await puppeteer.launch(isDebugging().puppeteer)); // <<< page = await browser.newPage(); /// });
ã¿ã€ã ã¢ãŠããèšå®ãããšãã«åãé¢æ°ã圹ç«ã¡ãŸãã
describe("Contact form", () => { test( "lead can submit a contact request", async () => { ///// }, isDebugging().jasmine // <<< - Jasmine )
ãã®åŸãã€ã³ã¿ãŒãã§ãŒã¹ã®ãªããã©ãŠã¶ãŒã§ãã¹ããéå§ããã«ã¯ã次ã®ã³ãã³ããå®è¡ããã ãã§ååã§ãã
npm test
ããžã¥ã¢ã«ã¢ãŒãã§ãã¹ããå®è¡ããã«ã¯ã次ãå®è¡ããå¿
èŠããããŸãã
NODE_ENV=debug npm test
ãŸãšã
ãŸã ãPuppeteerãŸãã¯ãã®APIã䜿çšããããšã«äžå®ããããããããŸããã åãããŸããã ãããŠããã®ãããžã§ã¯ãã®ç®æ°ããããã®å®çšçãªé©çšæ§ã«çåãæ±ããŠãããªããããšãã°
ãµã€ãã¬ã¹ãã芧ãã ãã ã ãã ããPuppeteerã¯éçºè
ã«çã«ç¡éã®å¯èœæ§ãäžããŸãã ãã®ã©ã€ãã©ãªã«åºã¥ããŠãã¹ããã¬ãŒã ã¯ãŒã¯ãäœæãããŠããŸãã ãã¡ãããæéã®çµéãšãšãã«ãPuppeteer APIã¯å€æŽãããå¯èœæ§ããããŸãããããã§èª¬æããåºæ¬çãªããšã¯ã©ãã«ãè¡ãåœãããŸããã ããã«ãPuppeteerã¯Jestãšãçžæ§ãè¯ãããšã«æ³šæããŠãã ããã ããã«ãå€ãã¯Puppeteer
E2Eãã¹ããå®è¡ã
ãŸã ã
芪æãªãèªè
ïŒ Webã€ã³ã¿ãŒãã§ãŒã¹ã®ãã¹ããã©ã®ããã«èªååããŸããïŒ