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

HTML Reports และ Screenshots

เวลาเรียน: 15–20 นาที ต้องรู้มาก่อน: Module 07 รูปแบบ: อ่าน + Code Lab + แบบฝึก

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

  • ใช้ built-in HTML reporter ของ Playwright
  • ตั้งค่า reporters หลายแบบ (list, dot, json, junit)
  • เปิดใช้ automatic screenshots on failure
  • ตั้งค่า video recording
  • อ่าน HTML report แล้ววิเคราะห์ปัญหาได้
1 · ทำไม Report สำคัญ?

เมื่อ test suite มี 100+ tests:

  • terminal output อ่านยาก — scroll หาไม่เจอ
  • ไม่เห็น pattern ของ failure
  • ไม่มี screenshot ให้ดูว่า UI ตอน fail หน้าตาเป็นยังไง
  • แชร์ผลให้ทีมลำบาก

HTML Report แก้ปัญหาทั้งหมดนี้ — interactive, มี screenshots, filter ได้, แชร์ได้

2 · Built-in HTML Reporter
// playwright.config.ts
import { defineConfig } from '@playwright/test';

export default defineConfig({
  reporter: 'html',
});

เปิด report:

npx playwright show-report

Report จะแสดง:

  • สรุป pass/fail/skip
  • แต่ละ test มี duration, steps, screenshots
  • filter ตาม status, project, file
  • click เข้าไปดู detail ของแต่ละ test ได้
3 · Multiple Reporters

ใช้ได้หลาย reporter พร้อมกัน:

// playwright.config.ts
import { defineConfig } from '@playwright/test';

export default defineConfig({
  reporter: [
    // terminal output ขณะรัน
    ['list'],

    // HTML report สำหรับคนดู
    ['html', { open: 'never', outputFolder: 'playwright-report' }],

    // JSON สำหรับ tool อื่นอ่าน
    ['json', { outputFile: 'test-results/results.json' }],

    // JUnit XML สำหรับ CI (Jenkins, GitLab, etc.)
    ['junit', { outputFile: 'test-results/junit.xml' }]
  ],
});
Reporter ใช้สำหรับ Output
list ดูขณะรัน terminal
dot CI — output น้อย terminal (จุดๆ)
html วิเคราะห์ failure HTML folder
json tool integration JSON file
junit CI dashboard XML file
4 · Automatic Screenshots on Failure
// playwright.config.ts
import { defineConfig } from '@playwright/test';

export default defineConfig({
  use: {
    // screenshot เมื่อ test fail
    screenshot: 'only-on-failure',

    // หรือ screenshot ทุก test (ใช้ storage เยอะ)
    // screenshot: 'on',
  },
});

ค่าที่ใช้ได้:

  • 'off' — ไม่ถ่าย (default)
  • 'on' — ถ่ายทุก test
  • 'only-on-failure' — ถ่ายเฉพาะ test ที่ fail (แนะนำ)

Screenshot จะแนบใน HTML report อัตโนมัติ — click ดูได้เลย

5 · Video Recording
// playwright.config.ts
import { defineConfig } from '@playwright/test';

export default defineConfig({
  use: {
    video: 'retain-on-failure',
  },
});

ค่าที่ใช้ได้:

  • 'off' — ไม่อัด (default)
  • 'on' — อัดทุก test
  • 'retain-on-failure' — อัดทุกตัว แต่เก็บเฉพาะที่ fail (แนะนำ)
  • 'on-first-retry' — อัดเฉพาะตอน retry ครั้งแรก

Video จะเป็น .webm อยู่ใน test-results/ folder

6 · Manual Screenshot ใน Test
test('capture specific state', async ({ page }) => {
  await page.goto('/dashboard');

  // ถ่าย screenshot แบบ manual
  await page.screenshot({ path: 'screenshots/dashboard.png' });

  // ถ่ายเฉพาะ element
  await page.locator('.chart-panel').screenshot({
    path: 'screenshots/chart.png'
  });

  // ถ่ายทั้งหน้า (scroll down ด้วย)
  await page.screenshot({
    path: 'screenshots/full-page.png',
    fullPage: true
  });
});
7 · Config ที่แนะนำสำหรับทีม
// playwright.config.ts
import { defineConfig } from '@playwright/test';

export default defineConfig({
  reporter: [
    ['list'],
    ['html', { open: 'never' }],
    ['junit', { outputFile: 'test-results/junit.xml' }]
  ],
  use: {
    screenshot: 'only-on-failure',
    video: 'retain-on-failure',
    trace: 'retain-on-failure',  // จะเรียนใน lesson ถัดไป
  },
  // เก็บ artifacts ใน folder นี้
  outputDir: 'test-results',
});
แบบฝึกหัด: วิเคราะห์ HTML Report

สถานการณ์: ทีมรัน test suite แล้วได้ HTML report ที่แสดงผลดังนี้:

Test Results: 45 passed, 3 failed, 2 skipped

Failed Tests:
1. [chromium] auth/login.spec.ts:15
   "successful login" — Timeout 30000ms exceeded
   Screenshot: login page ยังแสดง loading spinner

2. [chromium] cart/checkout.spec.ts:42
   "complete payment" — expect(locator).toContainText('สำเร็จ')
   Received: "เกิดข้อผิดพลาด: ไม่สามารถเชื่อมต่อ payment gateway"
   Screenshot: error modal ปรากฏบนหน้า checkout

3. [firefox] products/search.spec.ts:28
   "search returns results" — expect(locator).toHaveCount(5)
   Received: 0
   Screenshot: search results area ว่างเปล่า (Firefox only)

คำถาม:

  1. แต่ละ failure น่าจะเกิดจากอะไร?
  2. failure ไหนคือ bug จริง? failure ไหนคือ test environment issue?
  3. ควรจัดลำดับความสำคัญในการแก้อย่างไร?
ดูคำตอบแนะนำ

1. สาเหตุที่น่าจะเป็น:

  • Test 1 (login timeout): อาจเป็น backend ช้า หรือ loading state ไม่หายไป — ดูจาก screenshot ที่ยังมี spinner
  • Test 2 (payment error): payment gateway เชื่อมต่อไม่ได้ — อาจเป็น test environment ไม่ได้ config mock หรือ gateway จริงล่ม
  • Test 3 (search Firefox): fail เฉพาะ Firefox — อาจเป็น browser compatibility bug จริง หรือ timing issue

2. Bug จริง vs Environment issue:

  • Test 1: น่าจะ environment — backend ช้าหรือล่ม ลอง retry ก่อน
  • Test 2: น่าจะ environment — payment gateway ในtest env ไม่ควรใช้ของจริง ควร mock
  • Test 3: น่าจะ bug จริง — fail เฉพาะ Firefox แสดงว่ามี browser compatibility issue

3. ลำดับความสำคัญ:

  1. Test 3 (Firefox bug) — bug จริง ต้องแก้ code
  2. Test 2 (payment) — ต้อง mock payment gateway ใน test env
  3. Test 1 (timeout) — ตรวจ backend stability หรือเพิ่ม timeout

สิ่งที่ต้องจำ

  • HTML reporter เป็น built-in — ใช้ง่าย แชร์ได้ มี screenshots + filter
  • ใช้หลาย reporters พร้อมกัน — list สำหรับ terminal, html สำหรับคน, junit สำหรับ CI
  • screenshot: 'only-on-failure' คือค่าที่ดีที่สุดสำหรับทีมส่วนใหญ่
  • video: 'retain-on-failure' อัดทุกตัว แต่เก็บเฉพาะที่ fail — ประหยัด storage
  • อ่าน report เป็นจะช่วยให้ debug เร็วขึ้น 10 เท่า เมื่อเทียบกับอ่าน log ใน terminal