- 1. ทำไมต้องทำ Unit Test
- 2. Framework แยกตามภาษา
- 3. ตารางเปรียบเทียบ Framework
- 4. เลือก Framework อย่างไร
- 5. Unit Test Framework กับ Mocking Framework ต่างกันอย่างไร
- 6. ตัวอย่าง Test Pyramid
- 7. แนวทางที่แนะนำในปี 2026
- 8. การนำ Unit Test เข้า CI/CD
- 9. Code Coverage
- 10. สรุป
#1. ทำไมต้องทำ Unit Test
ประโยชน์หลักของ Unit Test ได้แก่
- ตรวจสอบ logic ของโปรแกรมแบบอัตโนมัติ
- ลด regression bug เมื่อมีการแก้ไขโค้ด
- ช่วยให้ refactor ได้มั่นใจมากขึ้น
- ใช้เป็น executable specification ของระบบ
- ทำงานร่วมกับ CI/CD ได้ดี
- ช่วยออกแบบโค้ดให้มี coupling ต่ำและ testability สูงขึ้น
โครงสร้างพื้นฐานของ Unit Test มักเขียนในรูปแบบ Arrange – Act – Assert (AAA)
Arrange -> เตรียมข้อมูลและ dependency
Act -> เรียกฟังก์ชันหรือเมธอดที่ต้องการทดสอบ
Assert -> ตรวจสอบผลลัพธ์
ตัวอย่างแนวคิด
Input: add(2, 3)
Expected: 5
#2. Framework แยกตามภาษา
#JavaScript / TypeScript
#Vitest
Vitest เป็น testing framework ที่ทำงานร่วมกับ ecosystem ของ Vite ได้โดยตรง เหมาะกับโครงการสมัยใหม่ที่ใช้ JavaScript หรือ TypeScript โดยเฉพาะ React, Vue และ frontend stack ที่ใช้ Vite
จุดเด่น
- syntax คล้าย Jest
- ทำงานเร็วและ integrate กับ Vite ได้ดี
- รองรับ TypeScript
- mocking
- snapshot testing
- code coverage
- watch mode
ติดตั้ง
npm install -D vitest
ตัวอย่าง
import { describe, it, expect } from 'vitest'
function add(a: number, b: number) {
return a + b
}
describe('add()', () => {
it('should return 5', () => {
expect(add(2, 3)).toBe(5)
})
})
รัน
npx vitest
เหมาะกับ
- React + Vite
- Vue + Vite
- Node.js
- TypeScript
#Jest
Jest เป็น testing framework ที่มี ecosystem ใหญ่ และใช้แพร่หลายใน JavaScript/TypeScript
จุดเด่น
- assertions ในตัว
- mocking
- snapshot testing
- test isolation
- parallel execution
- ecosystem ใหญ่
ตัวอย่าง
function multiply(a, b) {
return a * b
}
test('2 * 3 = 6', () => {
expect(multiply(2, 3)).toBe(6)
})
เหมาะกับ
- Node.js
- React
- JavaScript/TypeScript project เดิมที่ใช้ Jest อยู่แล้ว
#React Testing Library
React Testing Library ไม่ใช่ test runner โดยตัวมันเอง แต่เป็น utility สำหรับทดสอบ React Component โดยเน้นพฤติกรรมที่ผู้ใช้มองเห็น
มักใช้งานร่วมกับ
Vitest + React Testing Library
หรือ
Jest + React Testing Library
ตัวอย่าง
render(<LoginButton />)
expect(
screen.getByRole('button', { name: /login/i })
).toBeInTheDocument()
#Python
#pytest
pytest เป็น framework ยอดนิยมของ Python เพราะ syntax สั้น อ่านง่าย และมี plugin ecosystem ขนาดใหญ่
จุดเด่น
- fixtures
- parametrization
- mocking ผ่าน plugin หรือ unittest.mock
- plugin ecosystem ใหญ่
- integration กับ coverage และ CI ง่าย
ติดตั้ง
pip install pytest
ตัวอย่าง
def add(a, b):
return a + b
def test_add():
assert add(2, 3) == 5
รัน
pytest
ตัวอย่าง Parameterized Test
import pytest
@pytest.mark.parametrize(
"a,b,expected",
[
(1, 2, 3),
(2, 3, 5),
(10, 20, 30),
],
)
def test_add(a, b, expected):
assert a + b == expected
เหมาะกับ
- Python application
- FastAPI
- Flask
- Django
- Data Science / ML utility code
#unittest
unittest เป็น testing framework ที่มากับ Python Standard Library และได้รับแนวคิดจาก xUnit/JUnit style
ตัวอย่าง
import unittest
class CalculatorTest(unittest.TestCase):
def test_add(self):
self.assertEqual(2 + 3, 5)
if __name__ == '__main__':
unittest.main()
ข้อดีคือไม่ต้องติดตั้ง dependency เพิ่ม
#Java
#JUnit
JUnit เป็นมาตรฐานหลักของ Java ecosystem สำหรับการทำ Unit Test และทำงานร่วมกับ Maven, Gradle และ IDE ได้ดี
ปัจจุบัน JUnit รุ่นใหม่ประกอบด้วยแนวคิดหลัก เช่น JUnit Platform และ JUnit Jupiter
ตัวอย่าง
import static org.junit.jupiter.api.Assertions.assertEquals;
import org.junit.jupiter.api.Test;
class CalculatorTest {
@Test
void addShouldReturnFive() {
assertEquals(5, 2 + 3);
}
}
Maven
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<scope>test</scope>
</dependency>
รัน
mvn test
เหมาะกับ
- Java
- Spring Boot
- Quarkus
- Jakarta EE
#Mockito
Mockito ไม่ใช่ Unit Test Framework หลัก แต่เป็น mocking framework ที่นิยมใช้คู่กับ JUnit
ตัวอย่าง
UserRepository repository = mock(UserRepository.class);
when(repository.findById(1L))
.thenReturn(Optional.of(user));
รูปแบบที่พบบ่อย
JUnit + Mockito
#Kotlin
#Kotest
Kotest เป็น testing framework สำหรับ Kotlin ที่รองรับหลาย test style รวมถึง property-based testing
ตัวอย่างแนวคิด
class CalculatorTest : StringSpec({
"2 + 3 should be 5" {
2 + 3 shouldBe 5
}
})
เหมาะกับ
- Kotlin
- Kotlin Multiplatform
- Backend Kotlin
บน JVM สามารถทำงานบน JUnit Platform ได้
#PHP
#PHPUnit
PHPUnit เป็น testing framework หลักของ PHP ecosystem
ตัวอย่าง
use PHPUnit\Framework\TestCase;
class CalculatorTest extends TestCase
{
public function testAdd(): void
{
$this->assertEquals(5, 2 + 3);
}
}
รัน
./vendor/bin/phpunit
เหมาะกับ
- PHP
- Laravel
- Symfony
- CodeIgniter
#Pest
Pest เป็น testing framework สำหรับ PHP ที่ให้ syntax กระชับและอ่านง่าย และทำงานบน PHPUnit
ตัวอย่าง
test('2 + 3 = 5', function () {
expect(2 + 3)->toBe(5);
});
รัน
./vendor/bin/pest
สำหรับ Laravel รูปแบบที่นิยมคือ
Laravel + Pest
หรือ
Laravel + PHPUnit
#C# / .NET
#xUnit.net
xUnit.net เป็น testing framework ที่นิยมมากใน .NET ecosystem
ตัวอย่าง
public class CalculatorTests
{
[Fact]
public void Add_ReturnsFive()
{
Assert.Equal(5, 2 + 3);
}
}
รัน
dotnet test
#NUnit
NUnit เป็น framework ที่ได้รับแนวคิดจาก xUnit family และรองรับ .NET อย่างกว้างขวาง
ตัวอย่าง
[TestFixture]
public class CalculatorTests
{
[Test]
public void Add_ReturnsFive()
{
Assert.That(2 + 3, Is.EqualTo(5));
}
}
#MSTest
MSTest เป็น testing framework ของ Microsoft สำหรับ .NET
ตัวอย่าง
[TestClass]
public class CalculatorTests
{
[TestMethod]
public void Add_ReturnsFive()
{
Assert.AreEqual(5, 2 + 3);
}
}
เหมาะกับองค์กรที่ใช้ Microsoft ecosystem และ Visual Studio
#Go
#testing package
Go มี testing framework อยู่ใน Standard Library โดยตรง จึงไม่จำเป็นต้องติดตั้ง framework เพิ่มสำหรับ Unit Test พื้นฐาน
ตัวอย่าง
package calculator
import "testing"
func TestAdd(t *testing.T) {
result := Add(2, 3)
if result != 5 {
t.Errorf("expected 5, got %d", result)
}
}
รัน
go test ./...
แนวทางที่นิยมมากใน Go คือ Table-Driven Test
func TestAdd(t *testing.T) {
tests := []struct {
a int
b int
expected int
}{
{1, 2, 3},
{2, 3, 5},
{10, 20, 30},
}
for _, tt := range tests {
result := Add(tt.a, tt.b)
if result != tt.expected {
t.Errorf("expected %d, got %d", tt.expected, result)
}
}
}
#Rust
#cargo test + libtest
Rust มี test support มากับ toolchain โดยใช้ attribute #[test]
ตัวอย่าง
fn add(a: i32, b: i32) -> i32 {
a + b
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_add() {
assert_eq!(add(2, 3), 5);
}
}
รัน
cargo test
Rust แยก unit test และ integration test ได้ชัดเจน โดย integration test มักอยู่ในโฟลเดอร์ tests/
#3. ตารางเปรียบเทียบ Framework
| ภาษา / Platform | Framework | เหมาะกับ | จุดเด่น |
|---|---|---|---|
| JavaScript / TypeScript | Vitest | Vite, React, Vue | เร็ว, Vite-native |
| JavaScript / TypeScript | Jest | Node, React | ecosystem ใหญ่ |
| React | React Testing Library | Component Test | ทดสอบผ่านพฤติกรรมผู้ใช้ |
| Python | pytest | Python app, FastAPI, ML | fixture, plugin, parametrize |
| Python | unittest | Python Standard Library | ไม่ต้องติดตั้งเพิ่ม |
| Java | JUnit | Java, Spring Boot | มาตรฐาน Java |
| Java | Mockito | Mock dependency | mocking ยอดนิยม |
| Kotlin | Kotest | Kotlin, KMP | DSL, property testing |
| PHP | PHPUnit | PHP | มาตรฐาน PHP |
| PHP | Pest | Laravel / PHP | syntax กระชับ |
| .NET | xUnit.net | ASP.NET Core, .NET | modern .NET ecosystem |
| .NET | NUnit | .NET | mature ecosystem |
| .NET | MSTest | Microsoft stack | integration กับ Microsoft tools |
| Go | testing | Go | built-in |
| Rust | cargo test / libtest | Rust | built-in |
#4. เลือก Framework อย่างไร
หลักการเลือกควรเริ่มจาก ecosystem ของภาษาและ framework ที่ใช้จริง
React + Vite
|
v
Vitest + React Testing Library
Node.js / TypeScript
|
+--> Vitest
|
+--> Jest
Python
|
+--> pytest <- แนะนำสำหรับโครงการใหม่ทั่วไป
|
+--> unittest <- built-in
Java / Spring Boot
|
v
JUnit + Mockito
Laravel
|
+--> Pest
|
+--> PHPUnit
ASP.NET Core
|
+--> xUnit.net
+--> NUnit
+--> MSTest
Go
|
v
testing package
Rust
|
v
cargo test
#5. Unit Test Framework กับ Mocking Framework ต่างกันอย่างไร
สองอย่างนี้ไม่เหมือนกัน
#Unit Test Framework
มีหน้าที่
- ค้นหา test
- รัน test
- assertions
- lifecycle
- report result
ตัวอย่าง
JUnit
pytest
Vitest
Jest
PHPUnit
xUnit.net
NUnit
MSTest
#Mocking Framework
ใช้จำลอง dependency
ตัวอย่าง
Mockito
Moq
unittest.mock
vi.mock()
jest.mock()
ตัวอย่าง architecture
Unit Test
|
v
UserService
/ \
/ \
UserRepository EmailService
| |
v v
Mock Mock
หลักสำคัญคือ Unit Test ควรพยายามไม่พึ่งพา
Database
External API
File System
Network
Message Queue
#6. ตัวอย่าง Test Pyramid
/\
/ \
/ E2E\
/------\
/Integration\
/------------\
/ Unit Tests \
/________________\
โดยทั่วไปควรมี Unit Test จำนวนมากกว่า Integration Test และ E2E Test เพราะ Unit Test เร็วและให้ feedback ได้เร็วกว่า
#7. แนวทางที่แนะนำในปี 2026
สำหรับโครงการใหม่ สามารถใช้ baseline ดังนี้
| Technology | Suggested Stack |
|---|---|
| React + Vite | Vitest + React Testing Library |
| Node.js | Vitest หรือ Jest |
| Python | pytest |
| Java / Spring Boot | JUnit + Mockito |
| Kotlin | Kotest หรือ JUnit |
| Laravel | Pest หรือ PHPUnit |
| ASP.NET Core | xUnit.net / NUnit / MSTest |
| Go | testing package |
| Rust | cargo test |
#8. การนำ Unit Test เข้า CI/CD
ตัวอย่าง pipeline
Developer
|
v
git push
|
v
CI Pipeline
|
+--> Install Dependencies
|
+--> Lint
|
+--> Unit Test
|
+--> Code Coverage
|
+--> Build
|
v
Deploy
ตัวอย่าง GitHub Actions
name: Unit Test
on:
push:
pull_request:
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 22
- run: npm ci
- run: npm test
#9. Code Coverage
Unit Test มักใช้ร่วมกับ Code Coverage
ตัวอย่างเครื่องมือ
| ภาษา | Coverage Tool |
|---|---|
| JavaScript / TypeScript | Vitest Coverage, Jest Coverage, Istanbul |
| Python | coverage.py, pytest-cov |
| Java | JaCoCo |
| PHP | PHPUnit Coverage + Xdebug/PCOV |
| .NET | Coverlet |
| Go | go test -cover |
| Rust | cargo-llvm-cov |
ไม่ควรตีความว่า Coverage สูง = Software Quality สูงเสมอไป
สิ่งสำคัญคือ test ต้องตรวจสอบ behavior และ business logic ที่สำคัญอย่างมีความหมาย
#10. สรุป
ไม่มี Unit Test Framework ตัวเดียวที่ดีที่สุดสำหรับทุกภาษา ควรเลือกให้ตรงกับ ecosystem ของโครงการ
แนวทางที่ใช้ได้ดีคือ
JavaScript/TypeScript -> Vitest / Jest
Python -> pytest
Java -> JUnit + Mockito
Kotlin -> Kotest / JUnit
PHP/Laravel -> Pest / PHPUnit
.NET -> xUnit.net / NUnit / MSTest
Go -> testing
Rust -> cargo test
หากต้องการเริ่มต้นให้ได้ผลเร็ว ควรเริ่มจาก
- ทดสอบ business logic ก่อน
- เขียน test ให้เป็นอิสระต่อกัน
- Mock เฉพาะ dependency ภายนอก
- ใช้ AAA หรือ Given–When–Then
- รัน test ทุกครั้งใน CI
- เก็บ coverage เป็น metric ประกอบ ไม่ใช่เป้าหมายเดียว
#References
- Vitest Documentation: https://vitest.dev/
- Jest Documentation: https://jestjs.io/
- React Testing Library: https://testing-library.com/docs/react-testing-library/intro/
- pytest Documentation: https://docs.pytest.org/
- Python unittest: https://docs.python.org/3/library/unittest.html
- JUnit Documentation: https://docs.junit.org/
- Kotest Documentation: https://kotest.io/
- PHPUnit Documentation: https://docs.phpunit.de/
- Pest Documentation: https://pestphp.com/
- xUnit.net: https://xunit.net/
- NUnit Documentation: https://docs.nunit.org/
- MSTest: https://learn.microsoft.com/dotnet/core/testing/unit-testing-mstest-intro
- Go testing package: https://pkg.go.dev/testing
- Rust cargo test: https://doc.rust-lang.org/cargo/commands/cargo-test.html