ฉันชอบดูการทดสอบยูนิตของฉันทำงาน (และผ่าน) มาโดยตลอด การทดสอบนั้นรวดเร็ว และการทดสอบที่ผ่านทำให้ฉันมั่นใจได้ว่าแต่ละชิ้นส่วนจะทำงานได้ตามที่ควรจะเป็น ในทางกลับกัน ฉันมักจะประสบปัญหาในการจัดลำดับความสำคัญของการทดสอบแบบครบวงจรสำหรับเบราว์เซอร์ เนื่องจากการเขียนและรันการทดสอบนั้นช้ามาก
โชคดีที่เครื่องมือสำหรับการทดสอบในเบราว์เซอร์แบบครบวงจรได้รับการพัฒนาและรวดเร็วขึ้นมากในช่วงหลายปีที่ผ่านมา และด้วยการตั้งค่าเบราว์เซอร์แบบไม่มีส่วนหัว ฉันสามารถรันการทดสอบเบราว์เซอร์เป็นส่วนหนึ่งของ CI ได้
เมื่อไม่นานนี้ ฉันพบ โพสต์บล็อกของ Heroku ที่พูดถึงการทดสอบในเบราว์เซอร์โดยอัตโนมัติด้วย Chrome แบบไม่มีส่วนหัวภายใน CI ของ Heroku Heroku มี buildpack ที่ติดตั้ง Chrome แบบไม่มีส่วนหัว ซึ่งคุณสามารถเรียกใช้สำหรับการทดสอบใน CI ได้
ตัวอย่างการตั้งค่าจากโพสต์บล็อกเป็นแอป React ที่ทดสอบกับ Puppeteer และ Jest ถือเป็นจุดเริ่มต้นที่ดี … แต่จะเกิดอะไรขึ้นหากฉันใช้ Playwright แทน Puppeteer เป็นไปได้หรือไม่
ฉันจึงตัดสินใจลองตรวจสอบดู ปรากฏว่าใช่ คุณสามารถทำสิ่งนี้กับ Playwright ได้เช่นกัน! ดังนั้น ฉันจึงได้รวบรวมขั้นตอนที่คุณต้องทำเพื่อให้การทดสอบ Playwright ทำงานบนเบราว์เซอร์ Chrome แบบไม่มีส่วนหัวที่ใช้ใน Heroku CI ในโพสต์นี้ ฉันจะแนะนำคุณทีละขั้นตอนในการตั้งค่า
การทดสอบแบบครบวงจรจะบันทึกว่าผู้ใช้โต้ตอบกับแอปของคุณในเบราว์เซอร์อย่างไร โดยจะตรวจสอบเวิร์กโฟลว์ทั้งหมด Playwright ทำให้กระบวนการนี้ราบรื่นมากด้วยการทดสอบใน Chrome, Firefox และ Safari แน่นอนว่าการรันการทดสอบเบราว์เซอร์ทั้งหมดใน CI นั้นค่อนข้างหนัก ดังนั้นโหมด headless จึงช่วยได้
Buildpack Chrome สำหรับการทดสอบ จาก Heroku จะติดตั้ง Chrome บนแอป Heroku เพื่อให้คุณสามารถรันการทดสอบ Playwright ใน Heroku CI ได้ด้วยการตั้งค่าที่น้ำหนักเบาจริงๆ
เนื่องจากฉันเพิ่งลองใช้สิ่งนี้ ฉันจึงฟอร์ กรีโพอของ GitHub ที่อ้างถึงครั้งแรก ในโพสต์บล็อกของ Heroku แอปพลิเคชันนี้เป็นแอป React ธรรมดาที่มีลิงก์ อินพุตข้อความ และปุ่มส่ง มีการทดสอบสามแบบ:
ง่ายมาก ตอนนี้ฉันแค่ต้องเปลี่ยนโค้ดเพื่อใช้ Playwright แทน Puppeteer และ Jest โอ้ ฉันยังต้องการใช้ pnpm แทน npm ด้วย นี่คือลิงก์ไปยัง รีโพอ GitHub ที่แยกออกมาของฉัน
มาดูขั้นตอนต่างๆ ที่ฉันทำในการปรับเปลี่ยนโค้ดกัน ฉันเริ่มต้นด้วยรีโพอที่แยกออกมา ซึ่งเหมือนกับรีโพอ heroku-examples
ฉันต้องการใช้ pnpm แทน npm (แล้วแต่ความชอบส่วนบุคคล) ดังนั้น นี่คือสิ่งที่ฉันทำก่อน:
~/project$ corepack enable pnpm ~/project$ corepack use pnpm@latest Installing [email protected] in the project… … Progress: resolved 1444, reused 1441, downloaded 2, added 1444, done … Done in 14.4s ~/project$ rm package-lock.json ~/project$ pnpm install # just to show everything's good Lockfile is up to date, resolution step is skipped Already up to date Done in 1.3s
ถัดไป ฉันลบ Puppeteer และ Jest และเพิ่ม Playwright
~/project$ pnpm remove \ babel-jest jest jest-puppeteer @testing-library/jest-dom ~/project$ $ pnpm create playwright Getting started with writing end-to-end tests with Playwright: Initializing project in '.' ✔ Do you want to use TypeScript or JavaScript? · JavaScript ✔ Where to put your end-to-end tests? · tests ✔ Add a GitHub Actions workflow? (y/N) · false ✔ Install Playwright browsers (can be done manually via 'pnpm exec playwright install')? (Y/n) · false ✔ Install Playwright operating system dependencies (requires sudo / root - can be done manually via 'sudo pnpm exec playwright install-deps')? (y/N) · false Installing Playwright Test (pnpm add --save-dev @playwright/test)… … Installing Types (pnpm add --save-dev @types/node)… … Done in 2.7s Writing playwright.config.js. Writing tests/example.spec.js. Writing tests-examples/demo-todo-app.spec.js. Writing package.json.
ฉันยังลบส่วนการกำหนดค่า Jest ออกจาก package.json
ด้วย
คุณสามารถรันการทดสอบ Playwright ได้ใน Chrome, Firefox และ Safari เนื่องจากฉันเน้นที่ Chrome ฉันจึงลบเบราว์เซอร์อื่นออกจากส่วน projects
ของไฟล์ playwright.config.js
ที่สร้างขึ้น:
/* Configure projects for major browsers */ projects: [ { name: 'chromium', use: { ...devices['Desktop Chrome'] }, }, // { // name: 'firefox', // use: { ...devices['Desktop Firefox'] }, // }, // // { // name: 'webkit', // use: { ...devices['Desktop Safari'] }, // }, ], …
โค้ดต้นฉบับมีไฟล์ทดสอบ Puppeteer ที่ src/tests/puppeteer.test.js
ฉันย้ายไฟล์นั้นไปที่ tests/playwright.spec.js
จากนั้นฉันอัปเดตการทดสอบเพื่อใช้ข้อตกลงของ Playwright ซึ่งแมปไว้ได้ค่อนข้างชัดเจน ไฟล์ทดสอบใหม่มีลักษณะดังนี้:
const ROOT_URL = 'http://localhost:8080'; const { test, expect } = require('@playwright/test'); const inputSelector = 'input[name="name"]'; const submitButtonSelector = 'button[type="submit"]'; const greetingSelector = 'h5#greeting'; const name = 'John Doe'; test.beforeEach(async ({ page }) => { await page.goto(ROOT_URL); }); test.describe('Playwright link', () => { test('should navigate to Playwright documentation page', async ({ page }) => { await page.click('a[href="https://playwright.dev/"]'); await expect(page.title()).resolves.toMatch('| Playwright'); }); }); test.describe('Text input', () => { test('should display the entered text in the text input', async ({ page }) => { await page.fill(inputSelector, name); // Verify the input value const inputValue = await page.inputValue(inputSelector); expect(inputValue).toBe(name); }); }); test.describe('Form submission', () => { test('should display the "Hello, X" message after form submission', async ({ page }) => { const expectedGreeting = `Hello, ${name}.`; await page.fill(inputSelector, name); await page.click(submitButtonSelector); await page.waitForSelector(greetingSelector); const greetingText = await page.textContent(greetingSelector); expect(greetingText).toBe(expectedGreeting); }); });
start-server-and-test
ออก ใช้ webServer ของ Playwright แทน เพื่อทดสอบแอป React ของฉัน ฉันต้องเปิดมันขึ้นมา (ที่ http://localhost:8080
) ในกระบวนการแยกต่างหากก่อน จากนั้นจึงจะสามารถรันการทดสอบได้ ซึ่งจะเป็นเช่นนี้ไม่ว่าฉันจะใช้ Puppeteer หรือ Playwright ก็ตาม สำหรับ Puppeteer ตัวอย่างของ Heroku จะใช้แพ็คเกจ start-server-and-test
อย่างไรก็ตาม คุณสามารถกำหนดค่า Playwright ให้เปิดใช้งานแอปก่อนเรียกใช้การทดสอบได้ ซึ่งสะดวกมาก!
ฉันลบ start-server-and-test
ออกจากโปรเจ็กต์ของฉันแล้ว
~/project$ pnpm remove start-server-and-test
ใน playwright.config.js
ฉันยกเลิกการแสดงความเห็นในส่วน webServer ที่ด้านล่าง และปรับเปลี่ยนให้มีลักษณะดังนี้:
/* Run your local dev server before starting the tests */ webServer: { command: 'pnpm start', url: 'http://127.0.0.1:8080', reuseExistingServer: !process.env.CI, },
จากนั้น ฉันจึงลบสคริปต์ test:ci
ออกจากไฟล์ package.json
เดิม สคริปต์ทดสอบของฉันมีลักษณะดังนี้:
"scripts": { … "test": "playwright test --project=chromium --reporter list" },
Playwright ติดตั้งไฟล์ไบนารีเบราว์เซอร์เวอร์ชันล่าสุดเพื่อใช้ในการทดสอบ ดังนั้น ฉันจึงจำเป็นต้องให้ Playwright ติดตั้ง Chromium เวอร์ชันของตนในเครื่องของตัวเอง
~/project$ pnpm playwright install chromium Downloading Chromium 130.0.6723.31 (playwright build v1140) from https://playwright.azureedge.net/builds/chromium/1140/chromium-linux.zip 164.5 MiB [====================] 100%
หมายเหตุ: บิลด์แพ็ก Chrome for Testing บน Heroku จะติดตั้งเบราว์เซอร์ที่เราจะใช้สำหรับการทดสอบ เราจะตั้งค่า CI เพื่อให้ Playwright ใช้เบราว์เซอร์นั้นแทนที่จะใช้เวลาและทรัพยากรในการติดตั้งเบราว์เซอร์ของตัวเอง
เมื่อเป็นเช่นนั้น ฉันก็พร้อมแล้ว ถึงเวลาที่จะทดสอบในระดับท้องถิ่น
~/project$ pnpm test > playwright test --project=chromium --reporter list Running 3 tests using 3 workers ✓ 1 [chromium] > playwright.spec.js:21:3 > Text input > should display the entered text in the text input (911ms) ✘ 2 [chromium] > playwright.spec.js:14:3 > Playwright link > should navigate to Playwright documentation page (5.2s) ✓ 3 [chromium] > playwright.spec.js:31:3 > Form submission > should display the "Hello, X" message after form submission (959ms) ... - waiting for locator('a[href="https://playwright.dev/"]') 13 | test.describe('Playwright link', () => { 14 | test('should navigate to Playwright documentation page', async ({ page }) => { > 15 | await page.click('a[href="https://playwright.dev/"]'); | ^ 16 | await expect(page.title()).resolves.toMatch('| Playwright'); 17 | }); 18 | });
โอ้! ถูกต้องแล้ว ฉันแก้ไขการทดสอบของฉันเพื่อให้ลิงก์ในแอปนำฉันไปยังเอกสารของ Playwright แทนที่จะเป็นของ Puppeteer ฉันจำเป็นต้องอัปเดต src/App.js
ที่บรรทัด 19:
<Link href="https://playwright.dev/" rel="noopener"> Playwright Documentation </Link>
ตอนนี้ถึงเวลาที่จะทำการทดสอบอีกครั้งแล้ว…
~/project$ pnpm test > playwright test --project=chromium --reporter list Running 3 tests using 3 workers ✓ 1 [chromium] > playwright.spec.js:21:3 > Text input > should display the entered text in the text input (1.1s) ✓ 2 [chromium] > playwright.spec.js:14:3 > Playwright link > should navigate to Playwright documentation page (1.1s) ✓ 3 [chromium] > playwright.spec.js:31:3 > Form submission > should display the "Hello, X" message after form submission (1.1s) 3 passed (5.7s)
ผ่านการทดสอบแล้ว! ต่อไปก็ถึงเวลาที่จะพาเราเข้าสู่ Heroku CI
ฉันทำตามคำแนะนำในโพสต์บล็อกของ Heroku เพื่อตั้งค่าแอปของฉันในท่อ CI ของ Heroku
ใน Heroku ฉันสร้างไปป์ไลน์ใหม่และเชื่อมต่อเข้ากับ GitHub repo ของฉัน
จากนั้น ฉันเพิ่มแอปของฉันลงในการจัดเตรียม
จากนั้นฉันไปที่แท็บ การทดสอบ และคลิก เปิดใช้งาน Heroku CI
ในที่สุด ฉันได้แก้ไขไฟล์ app.json
เพื่อลบสคริปต์ทดสอบที่ตั้งค่าให้เรียกใช้ npm test:ci
ฉันได้ลบ test:ci
ออกจากไฟล์ package.json
ของฉันแล้ว สคริปต์ test
ใน package.json
เป็นสคริปต์ที่ต้องใช้ และ Heroku CI จะค้นหาสคริปต์นั้นตามค่าเริ่มต้น
ไฟล์ app.json
ของฉันซึ่งต้องใช้ Chrome for Testing buildpack มีลักษณะดังนี้:
{ "environments": { "test": { "buildpacks": [ { "url": "heroku-community/chrome-for-testing" }, { "url": "heroku/nodejs" } ] } } }
ฉันส่งโค้ดของฉันไปที่ GitHub และการดำเนินการดังกล่าวทำให้เกิดการทดสอบใน Heroku CI
การทดสอบล้มเหลว แต่ฉันไม่กังวล ฉันรู้ว่าจะต้องมีการกำหนดค่า Playwright บางอย่าง
เมื่อค้นหาในบันทึกการทดสอบ ฉันพบสิ่งนี้:
Error: browserType.launch: Executable doesn't exist at /app/.cache/ms-playwright/chromium-1140/chrome-linux/chrome
Playwright กำลังมองหาอินสแตนซ์เบราว์เซอร์ Chrome ฉัน สามารถ ติดตั้งได้โดยใช้คำสั่ง playwright install chromium
ซึ่งเป็นส่วนหนึ่งของการตั้งค่าการทดสอบ CI แต่การทำเช่นนี้จะขัดกับจุดประสงค์ทั้งหมดของการมี Chrome for Testing buildpack Chrome ได้รับการติดตั้งแล้ว ฉันเพียงแค่ต้องชี้ไปที่มันอย่างถูกต้อง
เมื่อมองย้อนกลับไปที่บันทึกการตั้งค่าการทดสอบของฉันสำหรับ Heroku ฉันพบบรรทัดเหล่านี้:
Installed Chrome dependencies for heroku-24 Adding executables to PATH /app/.chrome-for-testing/chrome-linux64/chrome /app/.chrome-for-testing/chromedriver-linux64/chromedriver Installed Chrome for Testing STABLE version 130.0.6723.91
ฉันต้องการใช้เบราว์เซอร์ที่ /app/.chrome-for-testing/chrome-linux64/chrome
ฉันเพียงแค่ต้องการให้ Playwright ค้นหาเบราว์เซอร์นั้น
หมายเหตุ: หากคุณไม่สนใจรายละเอียดปลีกย่อยในหัวข้อนี้ คุณสามารถข้ามส่วนนี้ไปได้เลย และเพียงแค่คัดลอก app.json
ฉบับเต็มด้านล่าง ซึ่งควรจะช่วยให้คุณมีข้อมูลที่จำเป็นในการเริ่มต้นใช้งาน Playwright บน Heroku CI
ในเอกสารของ Playwright ฉันพบว่าคุณสามารถตั้งค่าตัวแปรสภาพแวดล้อมที่แจ้งให้ Playwright ทราบว่าคุณใช้ ตำแหน่งที่กำหนดเองสำหรับการติดตั้งเบราว์เซอร์ทั้งหมด หรือไม่ ตัวแปรสภาพแวดล้อมดังกล่าวคือ PLAYWRIGHT_BROWSERS_PATH
ฉันจึงตัดสินใจเริ่มต้นจากตรงนั้น
ใน app.json
ฉันตั้งค่าตัวแปร env
ดังนี้:
{ "environments": { "test": { "env": { "PLAYWRIGHT_BROWSERS_PATH": "/app/.chrome-for-testing" }, ...
ฉันส่งโค้ดของฉันไปที่ GitHub เพื่อดูว่าจะเกิดอะไรขึ้นกับการทดสอบของฉันใน CI
ตามที่คาดไว้ มันล้มเหลวอีกครั้ง อย่างไรก็ตาม ข้อผิดพลาดในบันทึกแสดงดังนี้:
Error: browserType.launch: Executable doesn't exist at /app/.chrome-for-testing/chromium-1140/chrome-linux/chrome
นั่นทำให้ฉันเกือบจะถึงเป้าหมายแล้ว ฉันจึงตัดสินใจว่าจะทำสิ่งนี้:
mkdir -p "$PLAYWRIGHT_BROWSERS_PATH/chromium-1140/chrome-linux"
ln -s \ $PLAYWRIGHT_BROWSERS_PATH/chrome-linux64/chrome \ $PLAYWRIGHT_BROWSERS_PATH/chromium-1140/chrome-linux/chrome
อย่างไรก็ตาม ฉันกังวลว่านี่จะเป็นอนาคตหรือไม่ ในที่สุด Playwright จะใช้ Chromium เวอร์ชันใหม่ และจะไม่ดูเหมือนโฟลเดอร์ chromium-1140
อีกต่อไป ฉันจะหาคำตอบได้อย่างไรว่า Playwright จะมีลักษณะอย่างไร
นั่นคือตอนที่ฉันค้นพบว่าคุณสามารถทำการทดลองติดตั้งเบราว์เซอร์ได้
~/project$ pnpm playwright install chromium --dry-run browser: chromium version 130.0.6723.31 Install location: /home/alvin/.cache/ms-playwright/chromium-1140 Download url: https://playwright.azureedge.net/builds/chromium/1140/chromium-linux.zip Download fallback 1: https://playwright-akamai.azureedge.net/builds/chromium/1140/chromium-linux.zip Download fallback 2: https://playwright-verizon.azureedge.net/builds/chromium/1140/chromium-linux.zip
บรรทัด “ตำแหน่งการติดตั้ง” มีความสำคัญมาก และถ้าเราตั้งค่า PLAYWRIGHT_BROWSERS_PATH
ต่อไปนี้คือสิ่งที่เราจะเห็น:
~/project$ PLAYWRIGHT_BROWSERS_PATH=/app/.chrome-for-testing \ pnpm playwright install chromium --dry-run browser: chromium version 130.0.6723.31 Install location: /app/.chrome-for-testing/chromium-1140 ...
นั่นคือสิ่งที่ฉันต้องการ ด้วยเวทมนตร์อัน awk
เล็กน้อย ฉันจึงทำสิ่งนี้ได้:
~/project$ CHROMIUM_PATH=$( \ PLAYWRIGHT_BROWSERS_PATH=/app/.chrome-for-testing \ pnpm playwright install --dry-run chromium \ | awk '/Install location/ {print $3}' ) ~/project$ echo $CHROMIUM_PATH /app/.chrome-for-testing/chromium-1140
เมื่อจัดการทุกอย่างเรียบร้อยแล้ว ฉันเพียงแค่ต้องเพิ่มสคริปต์ test-setup
ลงใน app.json
เนื่องจาก PLAYWRIGHT_BROWSERS_PATH
ถูกตั้งค่าไว้ใน env
แล้ว สคริปต์ของฉันจึงง่ายขึ้นเล็กน้อย นี่คือไฟล์ app.json
สุดท้ายของฉัน:
{ "environments": { "test": { "env": { "PLAYWRIGHT_BROWSERS_PATH": "/app/.chrome-for-testing" }, "buildpacks": [ { "url": "heroku-community/chrome-for-testing" }, { "url": "heroku/nodejs" } ], "scripts": { "test-setup": "CHROMIUM_PATH=$(pnpm playwright install --dry-run chromium | awk '/Install location/ {print $3}'); mkdir -p \"$CHROMIUM_PATH/chrome-linux\"; ln -s $PLAYWRIGHT_BROWSERS_PATH/chrome-lin ux64/chrome $CHROMIUM_PATH/chrome-linux/chrome" } } } }
ฉันจะอธิบายสั้นๆ ว่า test-setup
ทำอะไร:
การคำนวณสำหรับ PLAYWRIGHT_BROWSERS_PATH
ใช้ playwright install -- dry-run
ด้วย awk
เพื่อระบุโฟลเดอร์รูทที่ Playwright จะค้นหาเบราว์เซอร์ Chrome ตั้งค่านี้เป็นค่าสำหรับตัวแปร CHROMIUM_PATH
สร้างโฟลเดอร์ใหม่ (และโฟลเดอร์หลักที่จำเป็น) ให้กับ CHROMIUM_PATH/chrome-linux
ซึ่งเป็นโฟลเดอร์จริงที่ Playwright จะค้นหาไบนารี chrome
สร้างลิงก์เชิงสัญลักษณ์ในโฟลเดอร์นั้นสำหรับให้ Chrome ชี้ไปที่การติดตั้ง Heroku buildpack ของ Chrome ( /app/.chrome-for-testing/chrome-linux64/chrome
)
ด้วยไฟล์ app.json
ที่อัปเดตแล้ว Playwright จึงสามารถใช้การติดตั้ง Chrome จาก buildpack ได้ ถึงเวลาที่จะรันการทดสอบอีกครั้ง
ความสำเร็จ!
สคริปต์ test-setup
ทำงานได้ตามที่คาดหวัง
Playwright สามารถเข้าถึงไบนารี chrome
และรันการทดสอบซึ่งผ่าน
การทดสอบแบบครบวงจรสำหรับเว็บแอปพลิเคชันของฉันเริ่มยุ่งยากน้อยลง ดังนั้นฉันจึงให้ความสำคัญกับสิ่งนี้มากขึ้นเรื่อยๆ ในช่วงไม่กี่วันที่ผ่านมา นั่นหมายความว่าฉันต้องใช้ Playwright มากขึ้นด้วย เพราะมันมีความยืดหยุ่นและรวดเร็ว และตอนนี้ ฉันได้ทำงาน (เพื่อฉัน และเพื่อคุณ !) เพื่อให้มันทำงานได้กับ Chrome for Testing buildpack ใน Heroku CI แล้ว ฉันจึงสามารถเริ่มสร้างชุดทดสอบอัตโนมัติของเบราว์เซอร์ของฉันได้อีกครั้ง
โค้ดสำหรับการแนะนำนี้อยู่ใน ที่เก็บ GitHub ของฉัน
สนุกกับการเขียนโค้ด!