Jest là gì? Hướng dẫn cấu hình Jest với Typescript

Trong bài viết này, tôi sẽ giới thiệu cho bạn một cái nhìn tổng quan về Jest – một framework kiểm thử mạnh mẽ dành cho JavaScript. Nếu bạn chưa quen thuộc với khái niệm Unit Test, hãy tìm hiểu kỹ hơn qua bài viết về Unit Test trên comdy.vn.

1. Jest Là Gì?

Jest là một framework kiểm thử JavaScript được phát triển bởi Facebook, được thiết kế nhằm đơn giản hóa quá trình viết các bài kiểm thử. Ban đầu, Jest được tạo ra để kiểm thử cho các ứng dụng React, nhưng hiện nay, nó đã trở thành một công cụ không thể thiếu cho bất kỳ dự án JavaScript nào.

2. TDD và BDD Là Gì?

Trước khi đi sâu vào chi tiết về Jest, hãy cùng tìm hiểu về những phương pháp kiểm thử mà Jest hỗ trợ mạnh mẽ: Test-Driven Development (TDD) và Behavior-Driven Development (BDD).

2.1 Test-Driven Development (TDD)

TDD là phương pháp phát triển phần mềm mà trong đó các bài kiểm thử được viết trước khi viết mã nguồn. Phương pháp này tập trung vào việc phát triển phần mềm dựa trên yêu cầu tính năng, đảm bảo rằng mỗi yêu cầu đều được kiểm thử kỹ lưỡng.

Quy trình TDD bao gồm ba bước lặp đi lặp lại:

  1. Red (Viết kiểm thử thất bại): Bắt đầu với một bài kiểm thử không thành công, thể hiện yêu cầu mà mã cần phải thực hiện.
  2. Green (Viết mã để kiểm thử thành công): Viết mã tối thiểu cần thiết để đảm bảo bài kiểm thử thành công.
  3. Refactor (Cải tiến mã): Tối ưu hóa mã nguồn để đảm bảo rằng nó sạch sẽ và hiệu quả, một cách mà không làm mất tính đúng đắn của các bài kiểm thử.

3 bước viết TDD3 bước viết TDD

2.2 Behavior-Driven Development (BDD)

BDD mở rộng từ TDD và nhấn mạnh vào việc phát triển phần mềm dựa trên các hành vi mong muốn của người dùng. Trong BDD, các bài kiểm thử được viết theo dạng các tình huống cụ thể:

  • Given: Trạng thái ban đầu của hệ thống.
  • When: Hành động hoặc sự kiện diễn ra.
  • Then: Kết quả mong muốn sau khi hành động diễn ra.

Ví dụ với chức năng đăng nhập:

  • Given: Người dùng đang ở trang đăng nhập.
  • When: Người dùng nhập vào tên đăng nhập và mật khẩu hợp lệ.
  • Then: Người dùng sẽ được chuyển hướng đến trang chủ.

Các giai đoạn trong BDDCác giai đoạn trong BDD

3. Ưu và Nhược Điểm Của Jest

3.1 Ưu Điểm của Jest

  • Cấu Hình Đơn Giản: Jest không yêu cầu cấu hình phức tạp và có thể chạy ngay lập tức sau khi cài đặt (zero config).
  • Hiệu Năng Cao: Jest hỗ trợ kiểm thử đồng thời, giúp cải thiện tốc độ kiểm thử, đặc biệt cho các dự án lớn.
  • Kiểm Thử Snapshot: Đảm bảo rằng không có sự thay đổi bất ngờ nào trong quá trình phát triển.
  • Mocking: Hỗ trợ tốt cho việc mô phỏng các modules và hàm, giúp tách biệt các phần cần kiểm thử.
  • Đo Lường Độ Bao Phủ Mã: Hỗ trợ kiểm tra mức độ thực hiện của mã nguồn.
  • Tích Hợp Với CI/CD: Dễ dàng kết hợp với các công cụ như Jenkins trên comdy.vnGitHub Actions trên comdy.vn.

Ưu điểm của JestƯu điểm của Jest

3.2 Nhược Điểm của Jest

  • Thời Gian Chạy Từ Tốn: Nếu không tối ưu tốt, trong một số dự án lớn, tốc độ kiểm thử có thể bị giảm.
  • Khả Năng Tương Thích: Mặc dù Jest tương thích với nhiều công cụ, nhưng có thể xảy ra xung đột với các thư viện khác trong một số trường hợp hiếm hoi.
  • Quản Lý Snapshot Có Thể Khó Khăn: Việc duy trì Snapshot có thể trở nên phức tạp nếu không quản lý tốt.

4. Tính Năng Của Jest

4.1 Sử Dụng Matchers

Dùng để kiểm tra giá trị mong muốn với giá trị trả về của hàm thực hiện.

test('hai cộng hai bằng bốn', () => {
  expect(2 + 2).toBe(4);
});

4.2 Kiểm Tra Tính Đúng Đắn

Phân biệt các giá trị false, null, undefined để xử lý không đồng nhất.

test('null', () => {
  const n: null = null;
  expect(n).toBeNull();
  expect(n).toBeDefined();
  expect(n).not.toBeUndefined();
  expect(n).toBeFalsy();
});

4.3 Kiểm Tra Số

So sánh các số với điều kiện lớn hơn, nhỏ hơn hoặc bằng nhau.

test('hai cộng hai', () => {
  const value: number = 2 + 2;
  expect(value).toBeGreaterThan(3);
  expect(value).toBeLessThanOrEqual(4);
});

4.4 Kiểm Tra Chuỗi

Kiểm tra sự có mặt hay không trong một chuỗi.

test('không có chữ I trong từ team', () => {
  expect('team').not.toMatch(/I/);
});

4.5 Kiểm Tra Mảng

Kiểm tra phần tử có trong mảng.

test('danh sách mua sắm có bia', () => {
  const shoppingList: string[] = ['bia', 'sữa', 'bánh mì'];
  expect(shoppingList).toContain('bia');
});

4.6 Kiểm Tra Exception

Kiểm tra nếu function có ném ra exception với nội dung đúng.

function compileAndroidCode(): never {
  throw new Error('Lỗi biên dịch Android');
}

test('kiểm tra biên dịch Android', () => {
  expect(() => compileAndroidCode()).toThrow('Lỗi biên dịch Android');
});

4.7 Kiểm Tra Callbacks

Kiểm thử các function bất đồng bộ thông qua callback.

function fetchData(callback: (data: string) => void): void {
  callback('bơ đậu phộng');
}

test('dữ liệu là bơ đậu phộng', (done: jest.DoneCallback) => {
  fetchData((data: string) => {
    expect(data).toBe('bơ đậu phộng');
    done(); // Gọi `done()` khi callback được gọi.
  });
});

4.8 Kiểm Tra Promise

Kiểm thử các function bất đồng bộ trả về Promise.

function fetchData(): Promise<string> {
  return Promise.resolve('bơ đậu phộng');
}

test('dữ liệu là bơ đậu phộng', () => {
  return fetchData().then(data => {
    expect(data).toBe('bơ đậu phộng');
  });
});

4.9 Async/Await

Dùng cú pháp async / await để kiểm thử.

async function fetchData(): Promise<string> {
  return 'bơ đậu phộng';
}

test('dữ liệu là bơ đậu phộng', async () => {
  const data = await fetchData();
  expect(data).toBe('bơ đậu phộng');
});

4.10 Mock Function

Kiểm thử hàm và giá trị trả về.

const myMock = jest.fn().mockReturnValue('giá trị mặc định');

test('hàm mock trả về giá trị mặc định', () => {
  expect(myMock()).toBe('giá trị mặc định');
});

4.11 Mock Implementations

Jest cho phép mô phỏng toàn bộ triển khai của một hàm.

const myMock = jest.fn((x: number, y: number) => x + y);

test('mock implementation của phép cộng', () => {
  expect(myMock(1, 2)).toBe(3);
});

4.12 Kiểm Tra Snapshot

Đảm bảo giao diện hoặc kết quả của function không thay đổi ngoài mong muốn.

test('snapshot', () => {
  const user = { name: 'John', age: 30 };
  expect(user).toMatchSnapshot();
});

4.13 Tổ Chức Bài Kiểm Thử

Sử dụng describe để nhóm các bài kiểm thử theo chủ đề.

describe('tương ứng thành phố với món ăn', () => {
  test('Vancouver có sushi', () => {
    expect(true).toBe(true);
  });

  test('Toronto có poutine', () => {
    expect(true).toBe(true);
  });
});

4.14 Thiết Lập và Dọn Dẹp Môi Trường

Dùng beforeAllafterAll để thiết lập và dọn dẹp môi trường cho tất cả các bài kiểm thử.

beforeAll(() => {
  console.log('Thiết lập trước tất cả các bài kiểm thử');
});

afterAll(() => {
  console.log('Dọn dẹp sau tất cả các bài kiểm thử');
});

5. Hướng Dẫn Cấu Hình Jest Trong Dự Án TypeScript

5.1 Khởi Tạo Dự Án TypeScript

npm init -y
npm install ts-node typescript --save-dev
npx tsc --init

Đây là nội dung của tệp tsconfig.json:

{
  "compilerOptions": {
    "target": "es6",
    "module": "commonjs",
    "moduleResolution": "node",
    "sourceMap": true,
    "outDir": "./dist",
    "rootDir": "./src",
    "strict": true,
    "esModuleInterop": true,
    "skipLibCheck": true,
    "forceConsistentCasingInFileNames": true
  },
  "exclude": ["node_modules"]
}

5.2 Cài Đặt Jest

npm install jest @types/jest ts-jest --save-dev
  • jest: Thư viện chính của Jest – trình chạy test.
  • @types/jest: Định nghĩa kiểu cho Jest.
  • ts-jest: Tích hợp Jest cho TypeScript.

5.3 Cấu Hình Jest

Tạo một tệp mới jest.config.ts tại thư mục gốc của dự án:

import type { Config } from 'jest';

const config: Config = {
  preset: 'ts-jest',
  testEnvironment: 'node',
  testMatch: ['**/*.test.ts'],
  moduleFileExtensions: ['js', 'ts'],
};

export default config;

Thêm câu lệnh "test": "jest" vào phần script trong tệp package.json.

{
  "name": "200lab_jest_demo",
  "version": "1.0.0",
  "description": "",
  "main": "src/index.ts",
  "scripts": {
    "build": "tsc",
    "test": "jest"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "@types/jest": "^29.5.12",
    "jest": "^29.7.0",
    "ts-jest": "^29.2.5",
    "ts-node": "^10.9.2",
    "typescript": "^5.5.4"
  }
}

5.4 Tạo Mới Test Case

Tạo tệp src/math.test.tssrc/math.ts.

src/math.ts

export function add(a: number, b: number): number {
  return a + b;
}

src/math.test.ts

import { add } from './math';

describe('Các hàm Toán học', () => {
  test('phải trả về 5 cho add(2, 3)', () => {
    expect(add(2, 3)).toBe(5);
  });

  test('phải trả về 0 cho add(-2, 2)', () => {
    expect(add(-2, 2)).toBe(0);
  });
});

Cuối cùng, chạy lệnh npm test để xem kết quả.

Kiểm thử với JestKiểm thử với Jest

6. Kết Luận

Bài viết này đã cung cấp cho bạn cái nhìn tổng quan về Jest và cách sử dụng Jest trong dự án TypeScript của bạn. Hy vọng với những kiến thức này, bạn có thể áp dụng vào các dự án của mình một cách hiệu quả hơn. Nếu bạn muốn mở rộng thêm kiến thức của mình, hãy tham khảo những bài viết thú vị khác trên comdy.vn, chẳng hạn như:

Để lại một bình luận

Email của bạn sẽ không được hiển thị công khai. Các trường bắt buộc được đánh dấu *