ผลต่างระหว่างรุ่นของ "01204223/unit testing"

จาก Theory Wiki
ไปยังการนำทาง ไปยังการค้นหา
แถว 65: แถว 65:
 
})
 
})
 
</syntaxhighlight>
 
</syntaxhighlight>
 +
 +
โค้ดดังกล่าวจะทำให้มีการเรียกฟังก์ชัน cleanup เมื่อสิ้นสุดการรันในแต่ละเทสเคส
  
 
=== Test แรก ===
 
=== Test แรก ===
 +
 +
เพื่อความง่ายเราจะเริ่มจากการทดสอบ component TodoItem ก่อน เพราะว่าเป็น component ที่ไม่ได้มีการเรียก API
 +
 +
เราจะเก็บเทสทั้งหมดไว้ในไดเร็กทอรี frontent/src/__tests__/ ดังนั้นให้สร้างไฟล์ frontent/src/__tests__/TodoItem.test.jsx ดังนี้
 +
 +
<syntaxhighlight lang="javascript">
 +
import { render, screen } from '@testing-library/react'
 +
import { vi } from 'vitest'
 +
import TodoItem from '../TodoItem.jsx'
 +
 +
describe('TodoItem', () => {
 +
  it('renders with no comments correctly', () => {
 +
    // เดี๋ยวจะเพิ่มโค้ดตรงนี้
 +
  })
 +
})
 +
</syntaxhighlight>
 +
 +
โค้ดสำหรับเทสด้านบนยังไม่มีอะไร แต่ให้ลองเรียก
 +
 +
npm test
 +
 +
มาเพื่อดูผลลัพธ์ก่อน จะเห็นผลลัพธ์ดังนี้
 +
 +
> first-react-app@0.0.0 test
 +
> vitest run
 +
 +
 +
  RUN  v4.0.18 /home/jittat/prog/test/flask-react-todo-start/frontend
 +
 +
  ✓ src/__tests__/TodoItem.test.jsx (1 test) 4ms
 +
    ✓ TodoItem (1)
 +
      ✓ renders with no comments correctly 1ms
 +
 +
  Test Files  1 passed (1)
 +
      Tests  1 passed (1)
 +
    Start at  03:28:38
 +
    Duration  1.15s (transform 63ms, setup 167ms, import 51ms, tests 4ms, environment 682ms)
 +
 +
สังเกตข้อความที่พิมพ์ออกมาในส่วน TodoItem จะมีลักษณะคล้ายกับ specification (TodoItem renders with no comments correctly)  ในการเขียนเทส เราจะพยายามใส่คำอธิบายแต่ละเทสในลักษณะนี้ เพื่อให้เราสามารถอ่านผลลัพธ์ได้เข้าใจง่าย
  
 
== ทดสอบโค้ด backend ==
 
== ทดสอบโค้ด backend ==

รุ่นแก้ไขเมื่อ 20:33, 12 กุมภาพันธ์ 2569

หน้านี้เป็นส่วนหนึ่งของ 01204223

เราจะหัดใช้ Unit testing ในการควบคุมคุณภาพโปรแกรมที่เราเขียน ปกติถ้าเมื่อเราเขียนโปรแกรม เราจะทดสอบว่าโปรแกรมทำงานถูกต้องโดยทดลองรันและตรวจสอบผล แต่เมื่อโปรแกรมใหญ่ขึ้นเรื่อย ๆ เราจะไม่สามารถทดสอบทุก ๆ ส่วนที่เราเขียนมาได้ การพัฒนาระบบตรวจสอบอัตโนมัติเป็นแนวปฏิบัติพื้นฐานในการรักษาคุณภาพซอฟต์แวร์ รวมถึงอาจจะใช้ในการขับเคลื่อนการพัฒนาด้วยก็ได้

การทดสอบระบบมีได้หลายระดับ Unit testing เป็นการทดสอบซอฟต์แวร์ในหน่วยย่อย (unit) เช่น หนึ่งฟังก์ชัน หรือหนึ่ง component (ใน react)     ส่วน Integration testing หรือ End-to-end testing เป็นการทดสอบการทำงานของส่วนย่อย ๆ ที่เชื่อมต่อกัน    ในที่นี้เราจะเน้นแค่ unit testing ก่อน เพราะว่าเป็นจุดเริ่มต้นที่ดีรวมทั้งมักจะทำได้ง่ายกว่า

ในการพัฒนาเว็บแอพลิเคชัน แต่ละ unit ที่เราต้องการทดสอบมักทำงานร่วมกับส่วนอื่นๆ เช่น ถ้าพิจารณาส่วนหลังบ้าน โค้ดโดยมากก็จะทำงานกับฐานข้อมูล (database) ในขณะที่โค้ดหน้าบ้านก็จะต้องมีการเรียก API ดังนั้นการจะทดสอบแต่ละ unit จะต้องมีการสร้างหรือจำลองส่วนอื่น ๆ ของระบบเพื่อทำให้โค้ดที่เราต้องการทดสอบสามารถทำงานได้ และมีพฤติกรรมที่คงเส้นคงวาทำให้เราสามารถตรวจสอบความถูกต้องได้    เราจะได้ลองใช้เทคนิคที่เรียกว่า mock ในการจำลองการทำงานของส่วนอื่น ๆ ระหว่างที่โค้ดที่เราเทสทำงาน

ทดสอบ React component

สำหรับส่วนหน้าบ้าน เราจะใช้ Vitest เป็นเครื่องมือในการรันเทสสำหรับ React component เราจะติดตั้ง vitest รวมทั้งไลบรารีอื่น ๆ โดยสั่ง

npm install -D vitest jsdom @testing-library/react @testing-library/jest-dom @testing-library/user-event

ในไดเร็กทอรี frontend

ไลบรารีที่เราติดตั้งมีหน้าที่ดังนี้

  • vitest เป็นระบบเทส
  • jsdom ใช้สำหรับจำลองหน้าจอ (dom) โดยไม่มี browser
  • @testing-library/xxx เป็นเครื่องมือต่าง ๆ สำหรับทดสอบ react

เมื่อติดตั้งเสร็จ ให้ไปแก้ไฟล์ package.json เพื่อระบุว่าเมื่อสั่ง test ให้เรียก vitest โดยดูในส่วน "scripts" และเพิ่มบรรทัดดังด้านล่างเข้าไป

// ในไฟล์ frontend/package.json

  "scripts": {
    // ละไว้
    // ** ระหว่างที่เพิ่ม อย่าลืมเติม , ท้ายบรรทัดก่อนหน้าด้วย
    "test": "vitest run"
  },

เมื่อแก้เสร็จ เราจะสามารถสั่งรันเทสได้โดยสั่ง

npm test

แต่เนื่องจากตอนนี้เราไม่มีเทสเคสเลย vitest จะบอกว่าไม่มี test files และจบการทำงาน (หมายเหตุ: เราสามารถสั่งให้ vitest ดูการแก้ไขไฟล์แล้วรันเทสใหม่ได้ แต่ในที่นี้เราเลือกจะให้รันเทสตอนที่เราสั่งก่อนเท่านั้น)

เราจะต้องไปเพิ่ม config ของ test ในไฟล์ vite.config.js ดังนี้

import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'

// https://vite.dev/config/
export default defineConfig({
  plugins: [react()],
  // ** เพิ่มส่วนด้านล่างนี้ **
  test: {
    globals: true,                          // ทำให้เรียกฟังก์ชันเกี่ยวกับการเทสได้โดยไม่ต้องประกาศ
    environment: 'jsdom',                   // รันเทสแบบไม่มี browser
    setupFiles: './src/setupTests.js',      // ระบุโค้ดสำหรับเตรียมต่าง ๆ
  },
})

จากนั้นให้เพิ่มไฟล์ src/setupTests.js ดังนี้

import '@testing-library/jest-dom/vitest'
import { afterEach } from 'vitest'
import { cleanup } from '@testing-library/react'

afterEach(() => {
  cleanup()
})

โค้ดดังกล่าวจะทำให้มีการเรียกฟังก์ชัน cleanup เมื่อสิ้นสุดการรันในแต่ละเทสเคส

Test แรก

เพื่อความง่ายเราจะเริ่มจากการทดสอบ component TodoItem ก่อน เพราะว่าเป็น component ที่ไม่ได้มีการเรียก API

เราจะเก็บเทสทั้งหมดไว้ในไดเร็กทอรี frontent/src/__tests__/ ดังนั้นให้สร้างไฟล์ frontent/src/__tests__/TodoItem.test.jsx ดังนี้

import { render, screen } from '@testing-library/react'
import { vi } from 'vitest'
import TodoItem from '../TodoItem.jsx'

describe('TodoItem', () => {
  it('renders with no comments correctly', () => {
    // เดี๋ยวจะเพิ่มโค้ดตรงนี้
  })
})

โค้ดสำหรับเทสด้านบนยังไม่มีอะไร แต่ให้ลองเรียก

npm test

มาเพื่อดูผลลัพธ์ก่อน จะเห็นผลลัพธ์ดังนี้

> first-react-app@0.0.0 test
> vitest run


 RUN  v4.0.18 /home/jittat/prog/test/flask-react-todo-start/frontend

 ✓ src/__tests__/TodoItem.test.jsx (1 test) 4ms
   ✓ TodoItem (1)
     ✓ renders with no comments correctly 1ms

 Test Files  1 passed (1)
      Tests  1 passed (1)
   Start at  03:28:38
   Duration  1.15s (transform 63ms, setup 167ms, import 51ms, tests 4ms, environment 682ms)

สังเกตข้อความที่พิมพ์ออกมาในส่วน TodoItem จะมีลักษณะคล้ายกับ specification (TodoItem renders with no comments correctly) ในการเขียนเทส เราจะพยายามใส่คำอธิบายแต่ละเทสในลักษณะนี้ เพื่อให้เราสามารถอ่านผลลัพธ์ได้เข้าใจง่าย

ทดสอบโค้ด backend