Testing Levels
Duy Văn | 24/11/2024
Khái niệm
Ý tưởng về test levels có thể được hiểu thông qua một số điều sau:
- Đầu tiên, rõ ràng trong một sản phẩm phần mềm có rất nhiều thành phần, các thành phần này đều là các sản phẩm làm việc của ai đấy, ví dụ như requirement doc do BA viết, design doc thiết kế sản phẩm phần mềm do cả team dev làm ra, từng dòng code và các module của sản phẩm phần mềm do dev code ra, v.v…
Tất cả các thành phần này đều cần được kiểm thử, vì khả năng là ai đấy có sai sót, kết quả là trong các sản phẩm làm việc này sẽ có lỗi - Nhưng, các thành phần này không thể được kiểm thử bằng cùng một cách, vì cái thì là doc, cái thì là code, mỗi thứ có một kiểu kiểm thử riêng. Và, chúng nó không thể được test bởi cùng một người
Vậy nên, chúng ta có một khái niệm là Test levels
| Test levels là nhóm các hoạt động kiểm thử được tổ chức và quản lý, để phục vụ cho các giai đoạn cụ thể trong quá trình phát triển phần mềm | Test levels are groups of test activities that are organized and managed, so that they service specific stages in the software development process |
Hiểu khái niệm này rất đơn giản, bản chất của lối suy nghĩ này hình thành từ V-model

V-Model là mô hình phát triển phần mềm, được luận ra từ Waterfall, nhưng tập trung vào việc nêu bật lên các bước trong khâu kiểm thử và vai trò của chúng. Cụ thể, trong V-Model, sẽ có 4 bước được thực hiện khi ý tưởng sản phẩm phần mềm được tạo ra:
- User requirements - Yêu cầu của người dùng
- System requirements - Yêu cầu hệ thống
- Overall Design / High Level Design - Thiết kết tổng quan của sản phẩm
- Component Design / Low Level Design - Thiết kế chi tiết của sản phẩm
Các ý tưởng này được tạo ra trong quá trình phát triển sản phẩm phần mềm, đối tượng của các ý tưởng này chính là các sản phẩm làm việc.
V-Model nhấn mạnh vào khâu kiểm thử và nêu bật ra được, bước kiểm thử nào sẽ xác minh tính chính xác của các sản phẩm làm việc so với ý tưởng, cụ thể:
- Unit Test - phục vụ Component Design : Xác minh các module, các thành phần của code đúng như theo thiết kế chi tiết
- Integration Test - phục vụ High Level Design: Xác minh các module, các thành phần của code đúng như theo thiết kết tổng quan
- System Test - phục vụ System Requirement: Xác minh sản phẩm phần mềm đúng như theo yêu cầu hệ thống
- User Acceptance Test - phục vụ User Requirement: Xác minh sản phẩm phần mềm đúng như theo yêu cầu của người dùng
Typical question: What are test levels? - Test levels là gì?
Typical question: What is V-Model? - Mô hình V-Model là gì?
Vậy thì từng level này, ai sẽ là người thực hiện nó?
Unit Test
Unit Test hay kiểm thử đơn vị, là nhóm các hoạt động kiểm thử để xác minh tính chính xác của các đơn vị nhỏ nhất của sản phẩm phần mềm, là code - các hàm(function), method, các lớp (class),… theo thiết kế chi tiết.
Tóm lại, Unit Test là test code, thực tế mà nói việc kiểm thử các dòng code có rất nhiều vấn đề.
Ai sẽ làm Unit Test ? - Cả Dev và Tester đều có thể làm Unit Test, nhưng vấn đề ở chỗ, Tester thì có Manual Tester và Automation Tester. Manual Tester thì thường đ* biết code, chốt thế cho nó vuông, còn Automation Test thì biết code nhưng cũng bục mặt ngồi viết script. Thế thì chỉ có mỗi ông Dev là phải làm Unit Test thôi, mà dev làm cũng nhanh hơn, gọn hơn, gần như là tìm và debug tại chỗ.
- Sửa lỗi nhanh hơn
- Thiết kế codebase của sản phẩm phần mềm đẹp hơn
- Mang tính “ngăn ngừa” nhiều, vì rõ ràng nếu xử lý được bug từ giai đoạn code, thì sẽ ngăn được bug trên sản phẩm phần mềm
Và logic chung là : Anh viết ra code thì anh phải đảm bảo nó đúng thì anh mới được merge chứ, nên là theo logic đấy, Dev thường là người làm Unit Test.
Cái Unit Test sẽ nhìn thế nào, thực tế mà nói bản chất Unit Test là Auto, tức là các dev sẽ viết script để đưa function, method chạy với một đống các test case để đánh giá tính chính xác của đầu ra (output) với mỗi đầu vào (input), pass hết thì đúng, còn có test case fail thì vẫn là có gì đấy chưa ổn. Nếu bạn nào từng luyện công Leetcode hay Codewar thì sẽ hiểu, khi viết ra function thì web sẽ cho chạy test case để đánh giá tính chính xác của code bạn viết, Unit Test về cơ bản là vậy.
Unit Test thì sẽ cần được thực hiện không chỉ dựa theo thiết kế chi tiết, mà đôi khi còn phụ thuộc vào chính cách viết code của dev. Thiết kế chi tiết có thể coi là yêu cầu “cứng”, buộc code viết ra phải đúng như vậy, còn logic của dev sử dụng để viết code là yêu cầu “mềm”, mỗi dev có kiểu viết code riêng. Ví dụ:
Dev A khi viết code thì viết rất gọn, cần đúng một function, còn dev B cũng viết code để thực hiện cùng việc A đang làm, nhưng quyết định vì khả năng duy trì code về sau mà tách nó ra làm 3 functions, 1 function chính gọi 2 function con, hiệu quả tương đương code của A. Nhưng bây giờ Unit Test của B sẽ khác của A, do B ngoài test xác minh thiết kế như của A thì còn phải test xem 2 function con kia có lỗi không.
Và khi nào thì Unit Test có thể kết thúc? Tức là khi nào Dev sẽ coi code đã qua Unit Test:
- Chạy cho đúng đầu ra với mỗi đầu vào, theo như thiết kế chi tiết
- Bao quát (cover) toàn bộ code
- Không có bất cứ lỗi nào được ném ra, tức là mọi trường hợp ngoại (exception), trường hợp biên (edge case) đã được xử lý (handle)
- Có thể bao gồm pass cả code review
Rồi khi đấy code sẽ được coi là pass Unit Test và nhập (merge) vào codebase.
Các bug thường bắt được khi thực hiện Unit Test:
- Sai về output, không đúng với thiết kế
- Sai về logic (ví dụ: đôi khi có thể cho ra đúng output, nhưng không tối ưu)
- Không xử lý hết các exception và edge case
Typical question: Who is responsible for Unit Test? - Ai là người chịu trách nhiệm với Unit Test?
Typical question: What is the purpose of Unit Test? - Mục đích của Unit Test là gì?
Typical question: What are the typical bugs that can be caught by Unit Test? - Các bug nào thường bắt được bởi Unit Test?
Typical question: When can we consider that the code has passed Unit Test? - Khi nào thì chúng ta có thể coi là code đã qua Unit Test?
Integration Test
| Integration Test hay kiểm thử tích hợp là nhóm các hoạt động kiểm thử nhằm mục đích xác minh tính chính xác của các module hay thành phần của sản phẩm phần mềm (hay các hệ thống con) khi được đưa vào tích hợp thông qua các giao diện | Integration Test is the group of testing activities to verify the correctness of modules and components (or subsystems) when they are put in integration through interfaces |
Về logic, các dev sau khi đã tạo ra được các module nhỏ hoạt động tốt không lỗi, thì sau đó cần phải ghép các module này với nhau dể thành một phần lớn hơn của sản phẩm. Các module nhỏ có thể hoạt động tốt, nhưng đấy là khi chúng nó đang ở một mình, vấn đề sẽ xảy ra khi chúng nó được tích hợp vào với nhau, gọi qua lại lẫn nhau.
Vấn đề trọng tâm của Integration Test là tìm ra các lỗi về giao diện (interface) giữa các module/component:
| Lỗi | ||
|---|---|---|
| Lỗi về data | Mất mát, sai, hoặc sai mã hoá | Missing data, Wrong data, Wrong encoding of data |
| Lỗi về giao thức trong liên lạc | Failure và không xử lý chính xác failure | Failure and Incorrect handling of communication protocol |
| Lỗi về timing | Sai chuỗi gọi giao diện Sai thời gian gọi giao diện | Wrong sequence and wrong timing of interface calls |
| Lỗi về cấu trúc tin nhắn | Sai về cấu trúc tin nhắn giữa các hệ thống con | Wrong message structures between sybsystems |
Typical question: What are the typical bugs that can be caught by Integration Test? - Các bug nào thường bắt được bởi Integration Test?
Ai sẽ làm Integration Test ? - Cả Dev và Test đèu có thể làm Integration Test do nó phụ thuộc vào bản thân sản phẩm phần mềm được tạo ra như thế nào. Nhưng bạn chỉ cần nắm rõ hai điều sau:
- Dev thực hiện test trên code, hoặc khởi chạy sản phẩm và test nhanh
- Tester thực hiện test trên sản phẩm làm việc hoàn chỉnh, một bản build có thể chạy được
Vậy nên, nếu sản phẩm làm việc của Dev chỉ đơn giản là các đoạn code không có frontend, hoặc tích hợp các tính năng phía backend, thì người làm Integration Test sẽ là các dev luôn. Nếu sản phẩm làm việc có frontend và đóng vai trò như những thành phần hoàn chỉnh có thể hoạt động (tức là đã tích hợp backend), giờ cần tích hợp với các thành phần hoàn chỉnh khác thì Integration Test sẽ được thực hiện bởi Tester.
Ví dụ, nếu các dev đã tạo ra được thành phần tính năng tính toán chi tiêu, và thành phần tính năng kết nối đến cơ sở dữ liệu, hai thành phần này chưa có frontend, thì khi tích hợp chúng vào nhau để thành tính năng lớn - tính toán chi tiêu khách hàng thì Tester sẽ không thể làm Integration Test mà phải là các Dev
Mặt khác, nếu tính năng tính toán chi tiêu này được phát triển độc lập và có frontend, đã có backend, sau đó nó có thể được tích hợp với bất cứ nguồn dữ liệu nào, thì khi đấy Integration Test có thể được thực hiện bởi Tester
Kiểm thử tích hợp cần sự hợp tác tốt giữa dev và test, do chủ yếu các tình huống tích hợp thường liên quan đến backend.
Typical question: Who is responsible for Integration Test? - Ai là người chịu trách nhiệm với Integration Test?
Typical question: What is the purpose of Integration Test? - Mục đích của Integration Test là gì?
Cách tiếp cận
Trong Integration Test, tuỳ thuộc vào tính năng đang được tích hợp sẽ cần áp dụng chiến thuật nhất định để thực hiện kiểm thử. Tuy kết quả sau cùng vẫn luôn là tất cả các module/component sẽ tích hợp đầy đủ vào nhau:
- Big-Bang: Tích hợp tất cả module/component trong một lần và thực hiện kiểm thử, vấn đề:
- Tất cả các module/component cần phải được hoàn thiện và sẵn sàng đưa vào tích hợp, vậy nên hạn chế ở chỗ là phải đợi đến cuối khâu Implement mới có thể làm Integration Test
- Khối lượng công việc nhẹ hơn về mặt kiểm thử, nhưng sẽ có nhiều bug được phát hiện trong khoảng thời gian ngắn
- Incremental: Tích hợp dần từng module/component và thực hiện kiểm thử:
- Có thể thực hiện song song với quá trình phát triển, module/component nào sẵn sàng thì có thể thực hiện test tích hợp luôn (Tuy nó có tên khác là Continuous integration test, nhưng về cơ bản nó vẫn là Incremental)
- Phải thực hiện số lần kiểm thử nhiều hơn, nhưng trải dài ra khoảng thời gian dài hơn, bắt lỗi giao diện của từng module/component
- Phức tạp hơn do đôi khi sẽ xảy ra thiếu sót về cấu trúc sản phẩm, mình sẽ giải thích kỹ hơn ở dưới
Chiến lược thực hiện Incremental
Logic rõ ràng là thực hiện incremental sẽ gặp vấn đề về thiếu sót cấu trúc, do các module/component được phát triển và kiểm thử dần. Ví dụ
Giả sử có một component thống kê chi tiêu A tích hợp với component kết nối đến cơ sở dữ liệu B, A gọi B trong chính nó để lấy data từ cơ sở dữ liệu ra rồi thực hiện tính toán, vẽ biểu đồ.
Nếu trong quá trình phát triển, dev làm A trước (hoặc B trước) thì thực hiện kiểm thử kiểu gì khi chưa có thằng còn lại?
Sử dụng ví dụ bên trên, mình sẽ giải thích 2 cách tiếp cận:
- Top-down: Việc xảy ra khi dev phát triển phần A trước, đấy là sẽ không có module hay phần tính năng nào để lấy dữ liệu ra từ database, vậy nên khi thực hiện Integration Test, chúng ta sẽ tại một stub để đóng vai trò như B
Stub B có thể là mọt function, hay một method đơn giản mang cùng tên, sử dụng trong interface giữa A và B. Bây giờ A sẽ cho gọi stub B, và stub B sẽ trả ra một bộ dữ liệu dummy chỉ cho mục đích kiểm thử - Bottom-up: Khi Dev phát triển phần B trước, sẽ không có module nào cho gọi B, vậy nên khi thực hiện Integration Test, chúng ta dùng một driver để đóng vai trò như A
Driver A sẽ là một class, hay method đơn giản nhưng có interface dẫn tới B và cho gọi B, đồng thời thực hiện một số tác vụ xử lý đơn giản dữ liệu lấy ra từ B.
graph TD
subgraph "Top-down (A first)"
A[A] -- Call --> StubB[Stub B]
StubB -- Returns dummy data --> A
A -- True processing --> Result[Statistics]
end
subgraph "Bottom-up (B first)"
DriverA[Driver A] --> B[B]
B -- Returns real data --> DriverA
DriverA -- Simple processing --> Demo[Illustrate]
end
Typical question: What are the typical approaches to Integration Test? - Các phương pháp tiếp cận thường dùng trong Integration Test là gì?
Typical question: What are stubs and drivers in Integration Test? - Stubs và drivers trong Integration Test là gì?
System Test
| System Test - Kiểm thử hệ thống là nhóm các hoạt động kiểm thử xác minh tính chính xác của sản phẩm phần mềm theo tài liệu đặc tả yêu cầu, bao gồm yêu cầu chức năng và phi chức năng | System Test is the group of testing activities to verify the correctness of the software product as per requirement specification, including functional and non-functional requirement |
Nôm na là chúng ta sẽ thực hiện kiểm thử trên chính sản phẩm phần mềm, một bản build hoàn thiện, có frontend, có thể vận hành. Bản build này sẽ được triển khai (deloy) lên một môi trường test (Test Enviroment). Tester sau đó bắt đầu thực hiện kiểm thử, cả chức năng và phi chức năng theo các test script đã viết sử dụng các test case, rồi tìm và log các bug.
Typical question: What is System Test? - Kiểm thử hệ thống là gì?
Hai kiểu kiểm thử (Test type) chính trong System Test là kiểm thử chức năng (Functional) và phi chức năng (Non-funtional). Hiểu nôm na là
- Kiểm thử chức năng sẽ xác minh các yêu cầu chức năng của tài liệu đặc tả, sản phẩm phần mềm có thể làm gì / What can the software do
- Kiểm thử phi chức năng sẽ xác minh các yêu cầu phi chức năng của tài liệu đặc tả, sản phẩm phần mềm làm tốt đến đâu / How well can the software perform. Bao gồm bảo mật, hiệu năng, v.v…
Typical question: What are functional and non-functional test? - Kiểm thử chức năng và phi chức năng là gì?
Ai sẽ làm System Test ? - Chỉ có tester mới thực hiện System Test, và nó sẽ chiếm phần lớn nội dung làm việc của một Tester. Ý tưởng của System Test là thực hiện kiểm thử theo tài liệu đặc tả, tức là cứ có cái gì trong tài liệu thì chúng ta xác minh sản phẩm phần mềm có đúng như vậy không. Góc nhìn của người tester sẽ gần giống với góc nhìn của người dùng, tester sẽ thực hiện kiểm thử như cách một người dùng sử dụng phần mềm, nhưng với ý đồ rõ ràng và mindset là đi tìm bug.
Typical question: Who would do System Test? - Ai sẽ làm kiểm thử hệ thống?
Các bug mà System Test thường bắt được:
| Lỗi | |
|---|---|
| Sai tính toán | Incorrect calculation |
| Mất kiểm soát và sai đường dữ liệu | Incorrect Control and Data flow |
| Hành vi chức năng và phi chức năng bất thường của hệ thống | Unexpected system functional and non-functional behavior |
| Thất bại của các chức năng người dùng | Failure of end-to-end function |
| Không thể vận hành như trong hướng dẫn | Failure to function as described in the manual |
| Thất bại trong môi trường | Failure in environment |
Các bug bắt được ở System Test bản chất là kết quả cuối của các bug nằm trong code, trong tài liệu mà vượt qua được hai giai đoạn kiểm thử trước.
Typical question: What are the typical bugs that can be caught by System Test? - Các bug nào thường bắt được bởi System Test?
Typical question: When would tester do System Test? - Khi nào thì tester thực hiện kiểm thử hệ thống?
User Acceptance Test
| User Acceptance Test hay Acceptance Test - kiểm thử nghiệm thu là nhóm các hoạt động kiểm thử để xác minh tính chính xác của sản phẩm phần mềm theo yêu cầu của khách hàng | User Acceptance Test is the group of test activities to verify the correctness of the software product according to the requirements of customer |
Về cơ bản, khách hàng sẽ kiểm thử sản phẩm và xem nó có đúng như những gì mình đã yêu cầu hay không, hay dễ hiểu chính là đi nghiệm thu sản phẩm.
Ai sẽ làm Acceptance Test ? - Người thực hiện Acceptance Test phải là khách hàng, buộc phải là khách hàng. Ngoài ra thì Tester có thể được tham gia vào UAT nhưng không phải là người đưa ra quyết định, tức là mang tính hỗ trợ, có thể là viết test case hộ, log bug hộ, v.v…
UAT có hai loại, Alpha và Beta UAT
- Với Alpha UAT, sản phẩm phần mềm sẽ được deploy ở phía team dự án, khách hàng tới và thực hiện kiểm thử (hoặc làm remote) dưới dự theo dõi và giám sát của team
- Beta UAT thì sản phẩm sẽ được deploy bên phía khách hàng, họ tự thực hiện kiểm thử, không cần sự theo dõi và giám sát của dự án
Kết quả của UAT sẽ là văn bản nghiệm thu. Cái kết của UAT chính là OK đấy, mình nghiệm thu ổn, chấp nhận sản phẩm nhé. Chỉ khi nào khách hàng hài lòng với sản phẩm, chấp nhận tình trạng hiện tại của sản phẩm, thì UAT kết thúc.
Nếu khách hàng chấp nhận sản phẩm, thì sản phẩm sẽ được chuyển sang giai đoạn triển khai (deloyment), nếu không thì sẽ phải quay lại giai đoạn phát triển, có thể là do bug, hoặc do hiệu năng chưa đạt yêu cầu, v.v…
Typical question: Who would do User Acceptance Test? - Ai sẽ làm kiểm thử nghiệm thu?
Typical question: What is the purpose of User Acceptance Test? - Mục đích của kiểm thử nghiệm thu là gì?
Typical question: What are the typical bugs that can be caught by User Acceptance Test? - Các bug nào thường bắt được bởi kiểm thử nghiệm thu?