1. Testing là gì và tại sao Backend cần Testing?

Software Testing là quá trình kiểm tra phần mềm để xác minh rằng hệ thống hoạt động đúng theo yêu cầu, phát hiện lỗi và hạn chế những thay đổi làm hỏng chức năng đã tồn tại.

Trong Backend, một chức năng thường không chỉ bao gồm một đoạn code đơn lẻ. Ví dụ, API tạo đơn hàng có thể liên quan đến:

  • Controller nhận và kiểm tra HTTP request.
  • Service thực hiện logic nghiệp vụ.
  • Repository truy vấn database.
  • Transaction đảm bảo các thao tác dữ liệu nhất quán.
  • Message broker nhận sự kiện để xử lý tiếp.
  • Một dịch vụ bên ngoài xử lý thanh toán.

Nếu chỉ kiểm tra bằng cách gọi API thủ công và thấy kết quả đúng một lần, chúng ta chưa thể chắc chắn chức năng sẽ tiếp tục hoạt động đúng khi code thay đổi, dữ liệu khác đi hoặc dependency gặp sự cố.

Testing giải quyết những vấn đề nào?

Phát hiện lỗi sớm: Lỗi trong một hàm tính toán thường dễ xác định và sửa hơn lỗi chỉ xuất hiện khi nhiều thành phần phối hợp.

Bảo vệ chức năng cũ: Khi refactor hoặc thêm tính năng, bộ test có thể phát hiện hành vi trước đây đã bị thay đổi ngoài ý muốn.

Làm rõ yêu cầu nghiệp vụ: Một test tốt mô tả rõ điều gì phải xảy ra khi đầu vào hợp lệ, dữ liệu thiếu hoặc một điều kiện đặc biệt xuất hiện.

Hỗ trợ refactor: Khi có các test đáng tin cậy, developer có thể thay đổi cấu trúc bên trong mà vẫn kiểm tra được hành vi bên ngoài.

Giảm rủi ro triển khai: Test có thể được chạy tự động trong CI/CD trước khi đưa code lên môi trường staging hoặc production.

2. Unit Testing là gì?

Unit Testing là kiểm thử một đơn vị logic nhỏ của chương trình trong phạm vi được kiểm soát.

Đơn vị đó thường là một hàm, method hoặc một nhóm logic nhỏ có trách nhiệm rõ ràng. Phạm vi cụ thể phụ thuộc vào ngôn ngữ, kiến trúc và cách tổ chức code.

Ví dụ, một hàm tính phí vận chuyển:

func CalculateShippingFee(total float64) float64 {
    if total >= 500_000 {
        return 0
    }

    return 30_000
}

Ta có thể kiểm thử:

  • Đơn hàng dưới 500.000 đồng phải chịu phí 30.000 đồng.
  • Đơn hàng đúng 500.000 đồng được miễn phí.
  • Đơn hàng trên 500.000 đồng được miễn phí.

Đặc điểm của Unit Test

Một unit test tốt thường có các đặc điểm:

  • Nhanh: Có thể chạy nhiều lần trong thời gian ngắn.
  • Tập trung: Kiểm tra một hành vi hoặc quy tắc cụ thể.
  • Dễ xác định nguyên nhân lỗi: Khi test thất bại, phạm vi cần kiểm tra tương đối nhỏ.
  • Có tính lặp lại: Cùng điều kiện đầu vào và trạng thái ban đầu phải cho kết quả ổn định.
  • Ít phụ thuộc môi trường: Thông thường không cần database thật, mạng hoặc dịch vụ bên ngoài.

Unit test không bắt buộc chỉ được kiểm tra đúng một dòng code. Điều quan trọng là phạm vi kiểm thử phải rõ ràng và tránh kéo theo quá nhiều thành phần không liên quan.

3. Integration Testing là gì?

Integration Testing là kiểm thử sự phối hợp giữa nhiều thành phần để xác minh rằng chúng hoạt động đúng khi kết nối với nhau.

Ví dụ, một integration test cho chức năng tạo đơn hàng có thể kiểm tra:

  1. Service nhận yêu cầu tạo đơn hàng.
  2. Repository ghi đơn hàng vào database.
  3. Database áp dụng các constraint.
  4. Transaction commit thành công.
  5. Khi đọc lại, dữ liệu được lưu đúng như mong đợi.

Khác với unit test chỉ kiểm tra logic trong phạm vi nhỏ, integration test tập trung vào các ranh giới kết nối giữa thành phần.

4. AAA Pattern: Arrange, Act, Assert

AAA là cách tổ chức test phổ biến, gồm ba giai đoạn.

Arrange: Chuẩn bị dữ liệu đầu vào, dependency và trạng thái ban đầu.

Act: Thực hiện hành động cần kiểm thử.

Assert: Kiểm tra kết quả thực tế có đúng với kết quả mong đợi hay không.

Ví dụ:

func TestDiscountForPremiumCustomer(t *testing.T) {
    // Arrange
    customer := Customer{
        Tier: "premium",
    }
    total := int64(1_000_000)

    // Act
    got := CalculateDiscount(customer, total)

    // Assert
    want := int64(100_000)

    if got != want {
        t.Fatalf("got %d, want %d", got, want)
    }
}

AAA giúp test dễ đọc vì người xem có thể nhanh chóng xác định:

  • Điều kiện ban đầu là gì?
  • Hành động nào đang được kiểm tra?
  • Điều kiện thành công được định nghĩa ra sao?

Không cần ép buộc mọi test phải có ba khối tách biệt rõ ràng. Với test đơn giản, điều quan trọng vẫn là tính dễ hiểu.

5. Test Case và Test Scenario

Hai thuật ngữ này thường được sử dụng gần nhau nhưng có thể phân biệt như sau:

  • Test scenario: Mô tả tình huống hoặc luồng cần kiểm thử.
  • Test case: Mô tả điều kiện, đầu vào, hành động và kết quả mong đợi cụ thể.

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

Scenario: Đăng nhập bằng thông tin hợp lệ.

Các test case có thể gồm:

  • Email và mật khẩu hợp lệ.
  • Email không tồn tại.
  • Mật khẩu sai.
  • Tài khoản bị khóa.
  • Thiếu email.
  • Mật khẩu rỗng.
  • Người dùng gửi request với định dạng không hợp lệ.

Một test case tốt cần có kết quả mong đợi rõ ràng. Nếu chỉ ghi “test đăng nhập”, người viết test vẫn chưa xác định được chính xác cần kiểm tra điều gì.

6. Contract Testing là gì?

Trong kiến trúc microservices, một service thường gọi service khác qua HTTP hoặc message broker.

Contract Testing kiểm tra rằng bên cung cấp và bên sử dụng giao tiếp với nhau theo một hợp đồng đã xác định.

Ví dụ, service đơn hàng kỳ vọng API khách hàng trả về:

{
  "id": 123,
  "status": "active"
}

Nếu service khách hàng đổi tên status thành account_status mà không có kế hoạch tương thích, consumer có thể gặp lỗi.

Contract test giúp phát hiện sự khác biệt giữa hợp đồng mà consumer mong đợi và giao diện mà provider cung cấp.

Contract testing không thay thế hoàn toàn integration test hoặc E2E test. Nó tập trung vào sự tương thích giữa các bên, đặc biệt hữu ích khi các service được phát triển và triển khai độc lập.

7. Kết luận

Unit Testing và Integration Testing giải quyết hai vấn đề khác nhau nhưng bổ trợ chặt chẽ cho nhau.

Unit Testing giúp xác minh các quy tắc và logic trong phạm vi nhỏ, chạy nhanh và dễ xác định nguyên nhân lỗi. Integration Testing giúp xác minh các thành phần phối hợp đúng, đặc biệt ở những ranh giới như database, HTTP, message broker và dịch vụ bên ngoài.

Một chiến lược testing tốt không dựa vào số lượng test hay coverage đơn thuần. Nó cần xác định đúng hành vi cần bảo vệ, chọn phạm vi test phù hợp, kiểm soát dependency và đảm bảo kết quả có thể lặp lại.

Bài viết khác

BÀI 5: TÌM HIỂU CHUYÊN SÂU VỀ LANGUAGE SWITCHING TRONG FLUTTER

1. Language Switching là gì? Trong một ứng dụng hỗ trợ nhiều ngôn ngữ, việc có sẵn các bản dịch chưa đủ để tạo ra trải nghiệm đa ngôn ngữ hoàn chỉnh. Ứng dụng còn cần xác định ngôn ngữ nào sẽ được sử dụng và cho phép thay đổi ngôn ngữ khi cần thiết. […]

TÌM HIỂU CHUYÊN SÂU VỀ UTC & LOCAL TIME CONVERSION TRONG FLUTTER

1. UTC & Local Time Conversion là gì? Trong một ứng dụng Flutter, thời gian xuất hiện ở rất nhiều chức năng như ngày tạo tài khoản, thời gian đặt hàng, lịch sử giao dịch, lịch hẹn, thời gian gửi thông báo và thời hạn của chương trình khuyến mãi. Khi ứng dụng chỉ chạy […]

TÌM HIỂU CHUYÊN SÂU VỀ DATE / NUMBER / CURRENCY FORMATTING TRONG FLUTTER

1. Date / Number / Currency Formatting là gì? Trong một ứng dụng Flutter, dữ liệu thường được lưu trữ và xử lý dưới dạng số, ngày giờ hoặc các kiểu dữ liệu có cấu trúc. Tuy nhiên, dữ liệu dùng để tính toán không nhất thiết giống với cách dữ liệu được hiển thị […]

TÌM HIỂU CHUYÊN SÂU VỀ LOCALIZATION (l10n) TRONG FLUTTER

1. Localization (l10n) là gì? Khi một ứng dụng được sử dụng ở nhiều quốc gia, sự khác biệt không chỉ nằm ở ngôn ngữ mà còn ở cách người dùng đọc ngày tháng, số, tiền tệ, đơn vị đo lường và các thông tin trên giao diện. Ví dụ, một ứng dụng bán hàng […]

TÌM HIỂU CHUYÊN SÂU VỀ INTERNATIONALIZATION (i18n) TRONG FLUTTER

1. Internationalization (i18n) là gì? Trong quá trình phát triển ứng dụng, lập trình viên thường xây dựng giao diện bằng một ngôn ngữ ban đầu, chẳng hạn như tiếng Việt. Khi ứng dụng được sử dụng bởi người dùng ở nhiều quốc gia, việc chỉ hỗ trợ một ngôn ngữ có thể khiến người […]

TÌM HIỂU CHUYÊN SÂU VỀ APP RELEASE & DEPLOYMENT TRONG FLUTTER

1. App Release & Deployment là gì? Trong quá trình phát triển ứng dụng Flutter, sau khi hoàn thành các chức năng, lập trình viên cần đưa ứng dụng đến người dùng thực tế. Ví dụ, một nhóm đã xây dựng xong ứng dụng bán hàng với những chức năng như đăng nhập, xem sản […]

Leave a Reply

Your email address will not be published. Required fields are marked *