Unit Testing ด้วย Jasmine และ Karma (Angular default)

Unit Testing คือการทดสอบหน่วยย่อยของโปรแกรม เช่น Component, Service หรือ Function เพื่อยืนยันว่าแต่ละส่วนทำงานถูกต้องก่อนนำไปรวมกับระบบใหญ่

Timeline/ประวัติศาสตร์

%%{init: {"theme": "base", "themeVariables": {"primaryColor": "#fabd2f", "primaryTextColor": "#282828", "primaryBorderColor": "#b57614", "lineColor": "#7c6f64", "secondaryColor": "#83a598", "tertiaryColor": "#b8bb26", "background": "#fbf1c7", "mainBkg": "#ebdbb2", "fontFamily": "Tahoma, sans-serif"}}}%%
flowchart LR
  subgraph Era1["ยุค Manual Test / ทดสอบด้วยมือ"]
    A["เปิดเว็บแล้วลองกด
Manual checking"] end subgraph Era2["ยุค Unit Test / Automated Test"] B["Jasmine
describe it expect"] C["Karma
รันใน Browser"] end subgraph Era3["ยุค Angular Testing Utility"] D["TestBed
สร้าง test module"] E["HttpClientTestingModule
mock HTTP"] end A --> B --> C --> D --> E

แนวคิดสำคัญ

ตารางเครื่องมือทดสอบ

เครื่องมือ หน้าที่ ตัวอย่าง
Jasmine เขียน test case describe, it, expect
Karma รัน test Browser runner
TestBed สร้าง Angular test module configureTestingModule
Fixture ควบคุม Component detectChanges()
Spy Mock method spyOn()

Mermaid Diagram: Angular Unit Test Flow

%%{init: {"theme": "base", "themeVariables": {"primaryColor": "#fabd2f", "primaryTextColor": "#282828", "primaryBorderColor": "#b57614", "lineColor": "#7c6f64", "secondaryColor": "#83a598", "tertiaryColor": "#b8bb26", "background": "#fbf1c7", "mainBkg": "#ebdbb2", "fontFamily": "Tahoma, sans-serif"}}}%%
flowchart TD
  A["Test Spec
ไฟล์ .spec.ts"] --> B["TestBed
ตั้งค่า module"] B --> C["ComponentFixture
สร้าง component"] C --> D["detectChanges
render template"] D --> E["expect
ตรวจผลลัพธ์"] E --> F["Karma Browser
รัน test"]

Code Example

// lesson-card.component.ts
// Component ตัวอย่างสำหรับทดสอบ
import { Component, Input } from '@angular/core';

@Component({
  selector: 'app-lesson-card',
  template: `<h2>{{ title }}</h2><button (click)="complete()">Done</button>`
})
export class LessonCardComponent {
  @Input() title = '';
  completed = false;

  complete(): void {
    this.completed = true;
  }
}
// lesson-card.component.spec.ts
// Unit test ด้วย Jasmine + TestBed
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { LessonCardComponent } from './lesson-card.component';

describe('LessonCardComponent', () => {
  let fixture: ComponentFixture<LessonCardComponent>;
  let component: LessonCardComponent;

  beforeEach(async () => {
    await TestBed.configureTestingModule({
      declarations: [LessonCardComponent]
    }).compileComponents();

    fixture = TestBed.createComponent(LessonCardComponent);
    component = fixture.componentInstance;
  });

  it('should render lesson title', () => {
    component.title = 'Angular Testing';
    fixture.detectChanges();

    const heading = fixture.nativeElement.querySelector('h2');
    expect(heading.textContent).toContain('Angular Testing');
  });

  it('should mark lesson as completed', () => {
    component.complete();
    expect(component.completed).toBeTrue();
  });
});

// ตัวอย่างการใช้งาน:
// ng test --code-coverage

วิดีโอแนะนำ

กิจกรรมท้ายบท

  1. สร้าง component LessonCardComponent
  2. เขียน test ตรวจ title
  3. เขียน test ตรวจ method complete()
  4. รัน ng test --code-coverage

กลับสัปดาห์ที่ 14