LESSON 29 ยท TESTING ยท JEST ยท VITEST

Testing ๐Ÿงช แˆแˆญแˆแˆญ!

Code แˆฐแˆญแ‰ฐแ‹ แ‹ฐแŒ‹แŒแˆ˜แ‹ แ‰ แŠฅแŒ… test แ‹ซแ‹ฐแˆญแŒ‰ แАแ‰ แˆญ? Automated tests แ‹ญแƒแ‰ โ€” แˆแˆŒแˆ แˆซแˆฑ test แ‹ซแ‹ฐแˆญแŒแˆแ‹Žแ‰ณแˆ!

โœ๏ธ แ‹จแˆฐแˆซแ‹: @AppMinds_ET ยท EthioCode SoftSelect
01
Testing แˆแŠ•แ‹ตแŠ• แАแ‹?

Testing = แŠฎแ‹ตแ‹Ž แ‰ แ‰ตแŠญแŠญแˆ แˆ˜แˆตแˆซแ‰ฑแŠ• แ‹จแˆšแ‹ซแˆจแŒ‹แŒแŒฅ automated program แАแ‹! แ‰ แŠฅแŒ… (Manual) แŠฅแ‹จแˆžแŠจแˆฉ "แˆฐแˆซ?" แŠจแˆ›แˆˆแ‰ต แ‹ญแˆแ‰… โ€” Test code แ‹ญแƒแ‰! แˆแˆŒแˆ deploy แŠจแˆ›แ‹ตแˆจแŒแ‹Ž แ‰ แŠแ‰ต แˆซแˆฑ แ‹ญแˆแ‰ตแˆฝแˆแ‹Žแ‰ณแˆ!

แ‹‹แŠ“แ‹ แŒฅแ‰…แˆ™: แŠ แ‹ฒแˆต feature แˆฒแŒจแˆแˆฉ แ‹จแ‹ตแˆฎแ‹แŠ• แŠฎแ‹ต แŠซแ‰ แˆ‹แˆน (แŠซแ‰‹แˆจแŒกแ‰ต)? Test แ‹ˆแ‹ฒแ‹ซแ‹แŠ‘ แ‹ญแАแŒแˆญแ‹Žแ‰ณแˆ!

Testing Pyramid โ€” 3 แ‹ฐแˆจแŒƒแ‹Žแ‰ฝ:

E2E Tests แˆ™แˆ‰ appแŠ• browser แ‹แˆตแŒฅ test แ‹ซแ‹ฐแˆญแŒ‹แˆ โ€” Playwright, Cypress แŒฅแ‰‚แ‰ต ยท แ‹˜แŒˆแˆแ‰ฐแŠ› ยท แ‹‹แŒ‹แ‰ธแ‹ แ‰ตแˆแ‰…
Integration Tests แ‰ฅแ‹™ componentsแŠ• แŠ แ‰ฅแˆฎ test แ‹ซแ‹ฐแˆญแŒ‹แˆ โ€” React Testing Library แˆ˜แŠซแŠจแˆˆแŠ› ยท แˆแŒฃแŠ•
Unit Tests แŠ แŠ•แ‹ต functionแŠ• แ‰ฅแ‰ป test แ‹ซแ‹ฐแˆญแŒ‹แˆ โ€” Jest, Vitest แ‰ฅแ‹™ ยท แ‰…แŒฝแ‰ แ‰ณแ‹Š ยท แ‰€แˆ‹แˆ‰
02
Testing แ‹“แ‹ญแАแ‰ถแ‰ฝ แŠฅแŠ“ Tools
๐Ÿ”ฌ
Unit Test
Jest ยท Vitest
แŠ แŠ•แ‹ตแŠ• function แ‰ฅแ‰ป test แ‹ซแ‹ฐแˆญแŒ‹แˆ! Input แˆฒแˆฐแŒ แ‹ โ€บ แ‹จแˆšแŒ แ‰ แ‰€แ‹แŠ• แ‹แŒคแ‰ต (Expected output) แ‹ซแˆ˜แŒฃแˆ? แ‰…แŒฝแ‰ แ‰ณแ‹Š แแ‰ฐแˆป!
๐Ÿ”—
Integration Test
RTL ยท Supertest
แ‹จแ‰ฐแˆˆแ‹ซแ‹ฉ แŠญแแˆŽแ‰ฝแŠ• แŠ แŒฃแˆแˆฎ test แ‹ซแ‹ฐแˆญแŒ‹แˆ! React component แŠจ API แŒ‹แˆญ แŠ แ‰ฅแˆฎ แ‹ญแˆฐแˆซแˆ?
๐ŸŒ
E2E Test
Playwright ยท Cypress
แ‰ แ‰ตแŠญแŠญแˆˆแŠ› browser แ‹แˆตแŒฅ! Login แฃ click แฃ fill แฃ submit โ€” แˆ™แˆ‰ แ‹จ user flowแŠ• test แ‹ซแ‹ฐแˆญแŒ‹แˆ!
๐Ÿ“ธ
Snapshot Test
Jest
แ‹จ UIแŠ• "แŽแ‰ถ" แ‹ซแАแˆณแˆ! แ‰  UI แˆ‹แ‹ญ แ‹ซแˆแ‰ณแˆฐแ‰  แˆˆแ‹แŒฅ แŠซแˆˆ แ‹ซแˆณแ‹ซแˆ โ€” unintended changesแŠ• แ‹ญแ‰†แŒฃแŒ แˆซแˆ! 
03
Unit Tests โ€” Jest / Vitest

Jest = แ‰ แ‹“แˆˆแˆ แˆ‹แ‹ญ แ‰ตแˆแ‰ แ‹จ JavaScript test framework แАแ‹! แ‰  Facebook แ‹จแ‰ฐแˆฐแˆซ แАแ‹! describe() แฃ it() แฃ expect() โ€” แˆฆแˆตแ‰ฑ แ‰แˆแ แАแŒˆแˆฎแ‰ฝ!

math.test.js โ€” Unit Tests
// โ”€โ”€ FunctionแŠ• Test แˆ›แ‹ตแˆจแŒ โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
function add(a, b) { return a + b; }
function divide(a, b) {
  if (b === 0) throw new Error('แ‰ แ‹œแˆฎ แˆ›แŠซแˆแˆ แŠ แ‹ญแ‰ปแˆแˆ!');
  return a / b;
}

// โ”€โ”€ Tests โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
describe('Math functions', () => {

  it('add(2, 3) should return 5', () => {
    expect(add(2, 3)).toBe(5);  // โœ… Pass!
  });

  it('add negative numbers', () => {
    expect(add(-1, -2)).toBe(-3); // โœ… Pass!
  });

  it('divide normally', () => {
    expect(divide(10, 2)).toBe(5); // โœ… Pass!
  });

  it('แ‰ แ‹œแˆฎ แˆ›แŠซแˆแˆ โ€” Error แ‹ญแˆแŒฅแˆซแˆ', () => {
    expect(() => divide(5, 0))
      .toThrow('แ‰ แ‹œแˆฎ แˆ›แŠซแˆแˆ แŠ แ‹ญแ‰ปแˆแˆ!'); // โœ…
  });
});
04
React Component Tests โ€” RTL

React Testing Library (RTL) = React componentsแŠ• test แˆˆแˆ›แ‹ตแˆจแŒ! Render โ†’ Find โ†’ Click โ†’ Expect! แ‹จ UserแŠ• แŠ แŒ แ‰ƒแ‰€แˆ แ‰ แˆแˆณแˆŒแАแ‰ต แ‹ญแˆžแŠญแˆซแˆ!

Counter.test.jsx โ€” React Testing Library
import { render, screen, fireEvent } from '@testing-library/react';
import Counter from './Counter';

describe('Counter Component', () => {

  it('แ‰  0 แ‹ญแŒ€แˆแˆซแˆ', () => {
    render(<Counter />);
    // Screen แˆ‹แ‹ญ "Count: 0" แŠ แˆˆ?
    expect(screen.getByText('Count: 0')).toBeInTheDocument();
  });

  it('+ แ‰แˆแ แˆฒแŒซแŠ‘ count แ‹ญแŒจแˆแˆซแˆ', () => {
    render(<Counter />);
    const btn = screen.getByRole('button', { name: '+' });
    fireEvent.click(btn); // Click ๏ผ
    expect(screen.getByText('Count: 1')).toBeInTheDocument();
  });

  it('3 แŒŠแ‹œ click แˆฒแ‹ฐแˆจแŒ = Count: 3', () => {
    render(<Counter />);
    const btn = screen.getByRole('button', { name: '+' });
    fireEvent.click(btn);
    fireEvent.click(btn);
    fireEvent.click(btn);
    expect(screen.getByText('Count: 3')).toBeInTheDocument();
  });
});
05
Live Test Runner Simulator

Jest Simulator! TestsแŠ• แ‹ซแˆตแŠชแ‹ฑ (Run) โ€” Pass/Fail แˆ˜แˆ†แŠ‘แŠ• แ‹ซแˆณแ‹จแ‹Žแ‰ณแˆ! Bug แŠ แˆตแŒˆแ‰ฅแ‰ฐแ‹ แ‹ญแˆžแŠญแˆฉ!

๐Ÿงช Jest Test Runner
Ready
06
TDD โ€” Test Driven Development

TDD = แˆ˜แŒ€แˆ˜แˆชแ‹ซ Test แ‹ญแƒแ‰ (Red) แฃ แ‰ แˆ˜แ‰€แŒ แˆ Code แ‹ญแƒแ‰! แ‹ญแˆ… แŠ แˆฐแˆซแˆญ developerแ‹ แŒฅแˆซแ‰ต แ‹ซแˆˆแ‹ แŠฎแ‹ต แŠฅแŠ•แ‹ฒแ…แ แ‹ซแ‹ฐแˆญแŒˆแ‹‹แˆ! Red โ†’ Green โ†’ Refactor cycle แ‹ญแ‰ฃแˆ‹แˆ!

TDD แˆ‚แ‹ฐแ‰ต โ€” 3 แ‹ฐแˆจแŒƒ:

๐Ÿ”ด
1. RED
แˆ˜แŒ€แˆ˜แˆชแ‹ซ Test แ‹ญแƒแ‰ โ€” แŠฎแ‹ฑ แˆณแ‹ญแŠ–แˆญ! แˆตแˆˆแ‹šแˆ… Fail แ‹ซแ‹ฐแˆญแŒ‹แˆ (Red)แข
๐ŸŸข
2. GREEN
Testแ‹แŠ• pass แˆˆแˆ›แ‹ตแˆจแŒ แ‹จแˆšแ‹ซแˆตแ‰ฝแˆ แŠ แАแˆตแ‰ฐแŠ› แŠฎแ‹ต (minimum code) แ‹ญแƒแ‰!
๐Ÿ”ต
3. REFACTOR
แŠฎแ‹ฑแŠ• แ‹ซแ…แ‹ฑ (Refactor) โ€” Tests แˆแˆ‰ แŠ แˆแŠ•แˆ pass แ‹ซแ‹ฐแˆญแŒ‹แˆ‰!
07
แ‹‹แŠ“ แ‹‹แŠ“ แАแŒฅแ‰ฆแ‰ฝ
1
๐Ÿงช Testing = Code Quality แ‹‹แˆตแ‰ตแŠ“

แŠ แ‹ฒแˆต feature แˆฒแŒจแˆแˆฉ แ‹จแ‹ตแˆฎแ‹แŠ• แŠฎแ‹ต แŠ แ‰ แˆ‹แˆนแ‰ต? npm test แ‹ˆแ‹ฒแ‹ซแ‹แŠ‘ แ‹ญแАแŒแˆญแ‹Žแ‰ณแˆ! Manual testing แ‰ฅแ‰ปแ‹แŠ• แ‰ แ‰‚ แŠ แ‹ญแ‹ฐแˆˆแˆ!

2
๐Ÿ”ฌ Unit Tests โ€” Jest/Vitest

describe() แˆ˜แˆ˜แ‹ฐแ‰ขแ‹ซ ยท it() test case ยท expect().toBe() แˆ›แˆจแŒ‹แŒˆแŒซ (assertion)! แˆˆแˆ˜แŒ€แˆ˜แˆญ แ‰€แˆ‹แˆ แАแ‹!

3
โš›๏ธ React Tests โ€” Testing Library

render() โ†’ screen.getByText() โ†’ fireEvent.click() โ†’ expect()! แ‹จ UserแŠ• แŠ แŒ แ‰ƒแ‰€แˆ แ‹ญแ‹ˆแŠญแˆ‹แˆ!

4
๐ŸŒ E2E โ€” Playwright

แ‰ แ‰ตแŠญแŠญแˆˆแŠ› browser แ‹แˆตแŒฅ! Login แฃ navigate แฃ form fill แฃ submit โ€” แˆ™แˆ‰ แ‹จ user flow! แŠจ CI/CD แŒ‹แˆญ แŠ แ‰ฅแˆฎ แ‹ญแˆฐแˆซแˆ!

5
๐Ÿ”ด TDD โ€” Test First!

แˆ˜แŒ€แˆ˜แˆชแ‹ซ Test แ‹ญแƒแ‰แฃ แ‰ แˆ˜แ‰€แŒ แˆ แŠฎแ‹ต แ‹ญแƒแ‰! Redโ†’Greenโ†’Refactor cycle! แ‹จแ‰ฐแˆปแˆˆ แ‹ฒแ‹›แ‹ญแŠ• แฃ แŠ แАแˆตแ‰ฐแŠ› bugs (แˆตแˆ…แ‰ฐแ‰ถแ‰ฝ)!

08
Quiz
โ“ Jest แ‹แˆตแŒฅ แŠ แŠ•แ‹ต function แ‰ตแŠญแŠญแˆˆแŠ›แ‹แŠ• value return แˆ›แ‹ตแˆจแŒ‰แŠ• แˆˆแˆ›แˆจแŒ‹แŒˆแŒฅ แ‹จแ‰ตแŠ›แ‹แŠ• แ‹ญแŒ แ‰€แˆ›แˆ‰?
What Jest method checks that a function returns the expected value?
Atest.check(result)
Bassert.equal(value)
Cexpect(result).toBe(expected) โœ…
Dverify(result === expected)