CupCode.cc
Section 04 · Module 01 · Lesson 02 · ~20–24 นาที

เขียน Test แรกด้วย Playwright

บทนี้จะพาเขียน test แรกแบบเข้าใจว่าแต่ละบรรทัดทำหน้าที่อะไร เพื่อให้คุณไม่รู้สึกว่า Playwright เป็นแค่สูตรลอกตามได้ แต่เป็นเครื่องมือที่อ่านและดัดแปลงต่อเองได้

เวลาเรียน: 20–24 นาที ต้องรู้มาก่อน: Lesson 01 - ติดตั้งและเริ่มต้น Playwright รูปแบบ: อ่าน + walkthrough + แบบฝึกพร้อมเฉลย

จบบทนี้แล้วคุณจะ...

  • เข้าใจโครงสร้างพื้นฐานของ test file ใน Playwright
  • ใช้ test(), expect() และ page เขียน test ที่อ่านง่ายได้
  • รู้ว่าการรัน test แล้วผลลัพธ์ที่เห็นใน terminal สื่อความหมายอะไร
  • แยกบทบาทของ Arrange, Act, Assert ใน Playwright ได้
  • เขียน test เริ่มต้นที่มี assertion มากกว่า 1 จุดอย่างมีเหตุผล
1 · โครงสร้างของ test หนึ่งตัว

Playwright test ที่ดีควรอ่านแล้วเข้าใจ flow ได้เกือบเหมือนอ่านภาษาคน

import { test, expect } from '@playwright/test';

test('should show the correct homepage title', async ({ page }) => {
  await page.goto('https://playwright.dev/');
  await expect(page).toHaveTitle(/Playwright/);
});
ส่วน หน้าที่
import { test, expect } นำ function หลักของ Playwright เข้ามาใช้
test('ชื่อ test', async ({ page }) => {}) ประกาศ test case หนึ่งตัว
page object ที่แทน browser tab
expect() ใช้ assertion เพื่อตรวจสอบผลลัพธ์
await ใช้กับ action และ assertion ที่ต้องรอผลแบบ async

ถ้าคุณเคยเรียน AAA มาก่อน จะเห็นว่า:

  • Arrange: page.goto(...)
  • Act: คลิกหรือกรอกข้อมูล
  • Assert: expect(...)
2 · เริ่มจาก test ที่สั้นแต่ครบ

เป้าหมายแรกไม่ใช่เขียนเยอะ แต่เขียนให้เข้าใจ flow

ตัวอย่าง test แรก:

import { test, expect } from '@playwright/test';

test('should display correct page title', async ({ page }) => {
  await page.goto('https://playwright.dev/');
  await expect(page).toHaveTitle(/Playwright/);
});

เมื่อรัน:

npx playwright test

คุณจะเห็นผลลัพธ์ประมาณนี้:

Running 3 tests using 3 workers

  ✓ [chromium] tests/example.spec.ts:3:5 (1.2s)
  ✓ [firefox] tests/example.spec.ts:3:5 (1.5s)
  ✓ [webkit] tests/example.spec.ts:3:5 (1.3s)

  3 passed (4.2s)

สิ่งที่ควรอ่านจาก output:

  • test ถูกรันใน browser อะไรบ้าง
  • test ไหนผ่านหรือ fail
  • ใช้เวลานานเท่าไร
3 · เพิ่ม assertion ให้มีความหมายมากขึ้น

แต่ยังต้องไม่เผลอไปเช็กทุกอย่างบนหน้า

import { test, expect } from '@playwright/test';

test('should display Playwright homepage correctly', async ({ page }) => {
  await page.goto('https://playwright.dev/');

  await expect(page).toHaveTitle(/Playwright/);

  const heading = page.getByRole('heading', { name: 'Playwright' });
  await expect(heading).toBeVisible();

  const getStartedLink = page.getByRole('link', { name: 'Get started' });
  await expect(getStartedLink).toBeVisible();
});

ตรงนี้สอนหลักสำคัญ 2 อย่าง:

  • title ผ่าน ไม่ได้แปลว่าหน้าใช้ได้ครบ
  • แต่ถ้า assert รายละเอียดเล็กน้อยเกินไป test จะเปราะและอ่านยาก
4 · จัดหลาย test ในไฟล์เดียวอย่างไร

ใช้ `test.describe()` เมื่อ test หลายตัวพูดเรื่องเดียวกัน

import { test, expect } from '@playwright/test';

test.describe('Playwright Homepage', () => {
  test('should have correct title', async ({ page }) => {
    await page.goto('https://playwright.dev/');
    await expect(page).toHaveTitle(/Playwright/);
  });

  test('should navigate to Get Started page', async ({ page }) => {
    await page.goto('https://playwright.dev/');
    await page.getByRole('link', { name: 'Get started' }).click();
    await expect(page).toHaveURL(/.*intro/);
  });
});

หลักคิดคือ:

  • 1 test ควรพิสูจน์ 1 behavior
  • test ใน describe เดียวกันควรพูดเรื่องเดียวกัน
  • อย่าเอา flow หลายเรื่องมาเบียดอยู่ใน test ยาวตัวเดียว
5 · เวลาทดสอบ fail ให้ดูอะไร

อย่าเพิ่งเดา ให้เริ่มจากหลักฐานที่ Playwright ให้มา

คำสั่งที่ใช้บ่อย:

npx playwright test --ui
npx playwright test --headed
npx playwright show-report

เวลาผลลัพธ์ fail ให้ไล่เช็กทีละข้อ:

  • locator ถูกไหม
  • หน้ายังโหลดไม่เสร็จหรือเปล่า
  • assertion กำลังเช็กสิ่งที่ผู้ใช้เห็นจริงหรือไม่
  • test กำลังพยายามทำหลายเรื่องเกินไปหรือเปล่า
Practice

แบบฝึก: เขียน test แรกให้ครบ flow สั้น ๆ

เขียน test ที่ตรวจสอบ 3 อย่างบนหน้า Playwright:

  1. title ของหน้าต้องมีคำว่า Playwright
  2. ต้องมีลิงก์ Get started ที่มองเห็นได้
  3. เมื่อคลิกลิงก์นั้นแล้ว URL ต้องมีคำว่า intro
ดูคำตอบแนะนำ
import { test, expect } from '@playwright/test';

test('should verify Playwright homepage', async ({ page }) => {
  await page.goto('https://playwright.dev/');

  await expect(page).toHaveTitle(/Playwright/);

  const getStartedBtn = page.getByRole('link', { name: 'Get started' });
  await expect(getStartedBtn).toBeVisible();

  await getStartedBtn.click();
  await expect(page).toHaveURL(/.*intro/);
});

สิ่งที่ต้องเอาติดตัวไปจากบทนี้

  • test() คือหน่วยพื้นฐานของ Playwright test file
  • page แทน browser tab ที่คุณใช้เปิดหน้า คลิก และโต้ตอบกับเว็บ
  • expect() ใช้ยืนยันผลลัพธ์ และเป็นหัวใจของการบอกว่า test ผ่านหรือไม่
  • test ที่ดีควรอ่านเป็น flow ได้ชัด และทดสอบเพียง behavior เดียวต่อหนึ่ง test
  • เวลา test fail ให้เริ่มจาก report, locator และ assertion ก่อนเดาสาเหตุอื่น