TỔNG QUAN VỀ KIỂM THỬ
Các thuật ngữ và định nghĩa cơ bản về kiểm thử
Mục tiêu: Trình bày được tổng quan về kiểm thử phần mềm
Kỹ nghệ kiểm thử đã trải qua nhiều thập kỷ phát triển, dẫn đến sự không nhất quán và thiếu tương thích trong các thuật ngữ được sử dụng trong tài liệu Cuốn sách này trình bày các thuật ngữ dựa trên tiêu chuẩn của IEEE (Viện Kỹ nghệ điện và điện tử), với việc lựa chọn cẩn thận các thuật ngữ tiếng Việt tương ứng.
Lỗi trong phát triển phần mềm là những vấn đề mà con người thường gặp phải, và việc mắc lỗi là điều không thể tránh khỏi Khi lập trình viên mắc lỗi, những lỗi này được gọi là bug Lỗi có thể lan rộng, ví dụ như một lỗi trong xác định yêu cầu có thể dẫn đến sai lầm trong thiết kế, từ đó gây ra nhiều sai sót hơn trong quá trình lập trình Chính vì vậy, lỗi là nguyên nhân chính dẫn đến các vấn đề trong sản phẩm phần mềm.
Sai (Fault) là kết quả của lỗi, trong đó lỗi dẫn đến sự sai sót Sai có thể được hiểu là biểu hiện của lỗi thông qua các hình thức như chương trình, văn bản, sơ đồ dòng dữ liệu hay biểu đồ lớp Những sai lầm này thường khó phát hiện, đặc biệt khi nhà thiết kế bỏ sót thông tin trong quá trình thiết kế, dẫn đến thiếu sót cần thiết Sai về nhiệm vụ xảy ra khi thông tin đầu vào không chính xác, trong khi sai do bỏ quên xảy ra khi không cung cấp đủ thông tin Loại sai do bỏ quên thường khó phát hiện và sửa chữa hơn so với loại sai do thông tin đầu vào sai.
Thất bại xảy ra khi có lỗi được thực thi, và điều quan trọng là thất bại chỉ xuất hiện dưới dạng mã nguồn có thể chạy được, liên quan đến các lỗi về nhiệm vụ Tuy nhiên, cần xem xét cách xử lý các lỗi bỏ quên, tức những lỗi không được tiến hành hoặc bị trì hoãn lâu Ví dụ điển hình là virus Michaelangelo, chỉ hoạt động vào ngày sinh của nó, tức ngày 6/3 Việc khảo sát và phát hiện lỗi thuộc cả hai loại này có thể giúp ngăn chặn nhiều thất bại.
Sự cố là biểu hiện của một thất bại, có thể rõ ràng hoặc không rõ ràng đối với người dùng hoặc người kiểm thử Khi thất bại xảy ra, sự cố sẽ giúp người dùng nhận biết về sự xuất hiện của vấn đề này.
Yêu cầu của khách hàng và đặc tả phần mềm là yếu tố then chốt trong quá trình phát triển sản phẩm Phần mềm được thiết kế dựa trên nhu cầu đã được thu thập, phân tích kỹ lưỡng, nhằm xác định các đặc trưng cần thiết Đặc tả phần mềm được xây dựng để mô tả chính xác các yêu cầu và giao diện mà sản phẩm cần đáp ứng Tài liệu này là nền tảng để đội ngũ phát triển thực hiện công việc của mình Sự thất bại xảy ra khi sản phẩm không hoạt động đúng như đặc tả, và lỗi trong quá trình xây dựng đặc tả có thể dẫn đến những vấn đề nghiêm trọng Do đó, việc bỏ sót thông tin trong đặc tả được coi là một loại lỗi cần được chú ý.
Kiểm chứng và thẩm định là hai khái niệm thường bị nhầm lẫn nhưng thực tế có ý nghĩa khác nhau Kiểm chứng (verification) là quá trình đảm bảo sản phẩm phần mềm thỏa mãn các đặc tả của nó, trong khi thẩm định (validation) là để xác nhận sản phẩm đáp ứng yêu cầu của người dùng Việc thực hiện kiểm chứng trước thẩm định là cần thiết để đảm bảo sản phẩm đúng với đặc tả, tránh tình trạng không xác định được nguyên nhân lỗi khi phát hiện vấn đề Do đó, thuật ngữ V&V (Verification & Validation) được sử dụng để nhấn mạnh tầm quan trọng của quá trình này trong phát triển phần mềm.
Chất lượng và độ tin cậy của phần mềm là những yếu tố quan trọng trong việc đánh giá sản phẩm Chất lượng phần mềm được xác định bởi khả năng đáp ứng các yêu cầu chức năng, sự hoàn thiện và các tiêu chuẩn đã được đặt ra Các yếu tố chất lượng bao gồm tính đúng đắn, tính hiệu quả, độ tin cậy, khả năng kiểm thử, dễ học, dễ sử dụng và dễ bảo trì Độ tin cậy, mặc dù chỉ là một trong những yếu tố đánh giá chất lượng, thường bị nhầm lẫn với chất lượng tổng thể Khi phần mềm hoạt động ổn định, người kiểm thử có thể cho rằng nó đạt chất lượng cao Độ tin cậy được định nghĩa là xác suất phần mềm hoạt động không gặp sự cố trong một khoảng thời gian nhất định và thời gian khắc phục sự cố cũng là chỉ số quan trọng trong việc đánh giá độ tin cậy của sản phẩm phần mềm.
Kiểm thử phần mềm liên quan đến các khái niệm như lỗi, sai sót, thất bại và sự cố Mục đích chính của kiểm thử là phát hiện thất bại hoặc xác nhận tính chính xác trong quá trình hoạt động của phần mềm.
Kiểm thử phần mềm là yếu tố then chốt trong việc đảm bảo chất lượng sản phẩm phần mềm trong quá trình phát triển Quy trình "kiểm thử - tìm lỗi - sửa lỗi" giúp cải thiện chất lượng sản phẩm Bên cạnh đó, việc kiểm thử ở mức hệ thống trước khi phát hành cho phép đánh giá mức độ tốt của sản phẩm.
Kiểm thử phần mềm được coi là một quy trình kiểm chứng quan trọng nhằm đánh giá và nâng cao chất lượng sản phẩm Quy trình này bao gồm hai nhiệm vụ chính: phân tích tĩnh và phân tích động.
Phân tích tĩnh là quá trình khảo sát các tài liệu phát triển sản phẩm như yêu cầu người dùng, mô hình phần mềm, hồ sơ thiết kế và mã nguồn Các phương pháp truyền thống bao gồm khảo sát đặc tả và mã nguồn cùng tài liệu thiết kế, sẽ được trình bày trong bài 4 Ngoài ra, kỹ thuật phân tích hình thức như kiểm chứng mô hình và chứng minh định lý cũng được sử dụng để xác minh tính đúng đắn của thiết kế và mã nguồn, mặc dù chúng tương đối phức tạp và không nằm trong phạm vi của giáo trình này Phân tích tĩnh không liên quan đến việc thực thi chương trình mà chỉ xem xét và lý giải các hành vi có thể xảy ra khi chương trình được thực thi, với tối ưu hóa các chương trình dịch là một ví dụ điển hình.
Phân tích động là quá trình thực thi chương trình nhằm phát hiện các lỗi tiềm ẩn và đánh giá hiệu suất của nó Do không thể kiểm tra tất cả các dữ liệu đầu vào, việc lựa chọn các "ca kiểm thử" từ một tập con dữ liệu là cần thiết để tối ưu hóa khả năng phát hiện lỗi Việc lựa chọn dữ liệu đầu vào hiệu quả, có xác suất phát hiện thất bại cao, là một thách thức quan trọng trong kiểm thử phần mềm Cùng với phân tích tĩnh, phân tích động giúp người kiểm thử phát hiện và sửa lỗi sớm trong giai đoạn phát triển, và cả hai kỹ thuật này cần được lặp lại thường xuyên để đảm bảo chất lượng phần mềm.
Ca kiểm thử là một yếu tố quan trọng trong quy trình phát triển phần mềm, với mỗi ca được đặt tên và liên kết chặt chẽ với hành vi cụ thể của chương trình Mỗi ca kiểm thử bao gồm một tập hợp dữ liệu đầu vào và một chuỗi giá trị đầu ra mong đợi, giúp đảm bảo phần mềm hoạt động đúng như kỳ vọng.
Hình 1.1: Một vòng đời của việc kiểm thử.
Vòng đời kiểm thử theo mô hình thác nước cho thấy rằng lỗi có thể xuất hiện trong các giai đoạn đặc tả yêu cầu, thiết kế và lập trình, dẫn đến sai sót lan truyền trong quá trình phát triển phần mềm Một nhà kiểm thử nổi tiếng đã phân loại vòng đời này thành ba giai đoạn "đưa lỗi vào", giai đoạn kiểm thử để tìm lỗi, và ba giai đoạn cuối là "khử lỗi" Bước sửa sai không chỉ là cơ hội để khắc phục mà còn có thể tạo ra lỗi mới, khiến phần mềm từ đúng trở thành sai nếu việc sửa chữa không đầy đủ.
Ca kiểm thử
Cốt lõi của kiểm thử phần mềm dựa trên phân tích động là xác định các ca kiểm thử có khả năng phát hiện lỗi trong hệ thống Đầu vào của ca kiểm thử bao gồm tiền điều kiện và dữ liệu đầu vào, trong khi đầu ra mong đợi bao gồm hậu điều kiện và dữ liệu đầu ra thực sự Đầu ra thường bị bỏ qua do khó xác định Ví dụ, khi kiểm thử phần mềm tìm đường đi tối ưu cho máy bay, câu hỏi về đường đi tối ưu có nhiều câu trả lời Câu trả lời lý thuyết dựa trên giả thiết về một "cây đũa thần" biết tất cả, trong khi câu trả lời thực tế được xác định qua kiểm thử tham chiếu với sự giám sát của các chuyên gia trong lĩnh vực ứng dụng phần mềm.
Kiểm thử phần mềm bao gồm việc thiết lập các tiền điều kiện cần thiết, cung cấp các ca kiểm thử và quan sát dữ liệu đầu ra Quá trình này giúp so sánh dữ liệu đầu ra thực tế với các đầu ra mong đợi, từ đó phát hiện các lỗi hoặc khiếm khuyết tiềm ẩn của sản phẩm phần mềm.
Hình 1.2: Thông tin về một ca kiểm thử tiêu biểu
Hình 1.2 trình bày thông tin cơ bản về ca kiểm thử, nhằm hỗ trợ quản lý hiệu quả Mỗi ca kiểm thử cần được xác định bằng tên/chỉ số và lý do tồn tại, chẳng hạn như đặc tả nhu cầu Cần bổ sung lịch sử tiến hành, bao gồm người thực hiện, thời gian, kết quả (thành công hay thất bại) và phiên bản phần mềm tương ứng Đối với các ca kiểm thử giao diện người dùng, cần thêm thông tin về trình tự nhập liệu Tóm lại, ca kiểm thử quan trọng không kém gì mã nguồn và cần được phát triển, kiểm tra, quản lý và lưu trữ một cách khoa học.
Mô tả bài toán kiểm thử qua biểu đồ venn
Kiểm thử chủ yếu tập trung vào hành vi của chương trình, phản ánh quan điểm về cấu trúc phổ dụng mà các nhà phát triển hệ thống hoặc phần mềm cần chú ý.
Sự khác biệt giữa quan điểm cấu trúc và hành vi trong kiểm thử phần mềm thể hiện ở chỗ quan điểm cấu trúc tập trung vào “là cái gì”, trong khi quan điểm hành vi chú trọng vào “làm gì” Một thách thức lớn cho người kiểm thử là tài liệu cơ sở thường được viết cho các nhà phát triển, dẫn đến việc thiên về thông tin cấu trúc và bỏ qua thông tin về hành vi của chương trình Để làm rõ hơn về kiểm thử, chúng ta sẽ phát triển một biểu đồ Venn đơn giản, với chi tiết sẽ được trình bày trong bài 3.
Hình 1.3: Các hành vi được cài đặt và được đặc tả
Trong vũ trụ hành vi của chương trình cần kiểm thử, mục tiêu chính là xác định tập hợp các ca kiểm thử hữu ích Được cho một chương trình và đặc tả của nó, ta ký hiệu S là tập hợp các hành vi được đặc tả và P là tập hợp các hành vi của chương trình Hình 1.3 minh họa mối quan hệ giữa các hành vi lập trình và hành vi được đặc tả Những hành vi được đặc tả nằm trong vòng tròn S, trong khi những hành vi lập trình nằm trong vòng tròn P Người kiểm thử phải đối mặt với các vấn đề như hành vi được đặc tả nhưng không được lập trình, gọi là sai sót do bỏ quên, và hành vi lập trình nhưng không được đặc tả, tương ứng với sai sót về nhiệm vụ Tương giao giữa S và P đại diện cho phần đúng đắn, bao gồm các hành vi vừa được đặc tả vừa được cài đặt, với tính đúng đắn chỉ có ý nghĩa trong mối liên hệ giữa đặc tả và cài đặt.
Hình 1.4: Các hành vi được cài đặt, được đặc tả và được kiểm thử.
Vòng tròn T trong hình 1.4 biểu thị cho các ca kiểm thử, trong đó tập hợp các hành vi của chương trình nằm trong vũ trụ chuyên đề đang xem xét Mỗi ca kiểm thử xác định một hành vi cụ thể Mối quan hệ giữa S, P và T cho thấy rằng có những hành vi được mô tả nhưng không được kiểm thử (các miền 2 và 5), những hành vi vừa được mô tả vừa được kiểm thử (các miền 1 và 4), và các ca kiểm thử tương ứng với những hành vi không được mô tả (các miền 3 và 7).
Việc phân loại các hành vi lập trình thành các miền khác nhau là rất quan trọng trong quá trình kiểm thử phần mềm Có ba loại hành vi: hành vi không được kiểm thử (các miền 2 và 6), hành vi được kiểm thử (các miền 1 và 3), và các ca kiểm thử tương ứng với hành vi không được lập trình (các miền 4 và 7) Nếu có hành vi được đặc tả mà không có ca kiểm thử tương ứng, điều này cho thấy quá trình kiểm thử chưa đầy đủ Ngược lại, nếu có ca kiểm thử cho hành vi không được đặc tả, có thể là do thiếu sót trong đặc tả hoặc ca kiểm thử không đảm bảo Kinh nghiệm cho thấy, một người kiểm thử giỏi thường tập trung vào các ca kiểm thử thuộc loại đầu, vì vậy sự tham gia của họ trong giai đoạn khảo sát đặc tả và thiết kế là rất cần thiết.
Việc xác định các ca kiểm thử
Có hai phương pháp chính để xác định các ca kiểm thử: kiểm thử hàm (hay còn gọi là kiểm thử chức năng hoặc kiểm thử hộp đen) và kiểm thử cấu trúc (hay kiểm thử hộp trắng).
- white-box testing) Mỗi cách tiếp cận có phương pháp xác định ca kiểm thử khác nhau và được gọi chung là phương pháp kiểm thử.
Kiểm thử hàm dựa trên khái niệm rằng mọi chương trình là một hàm ánh xạ giá trị từ miền dữ liệu đầu vào sang miền dữ liệu đầu ra Khái niệm này thường được áp dụng trong kỹ thuật, nơi các hệ thống được xem như các hộp đen, dẫn đến thuật ngữ kiểm thử hộp đen Trong phương pháp này, nội dung bên trong hộp đen (cách cài đặt) không quan trọng, mà chỉ cần quan tâm đến các dữ liệu đầu vào và đầu ra Thực tế, việc thao tác với kiến thức về hộp đen là rất hiệu quả, đặc biệt trong khái niệm định hướng đối tượng, nơi các đối tượng được coi là hộp đen và tương tác với nhau thông qua các phương thức có thể quan sát từ bên ngoài.
Hình 1.5: Một hộp đen kỹ thuật.
Kiểm thử hàm sử dụng đặc tả của phần mềm để xác định các ca kiểm thử, mang lại hai lợi ích chính: các ca kiểm thử này độc lập với cách cài đặt phần mềm, cho phép chúng vẫn khả dụng ngay cả khi có sự thay đổi trong cài đặt; đồng thời, các ca kiểm thử được phát triển song song và độc lập với hệ thống, giúp tăng tính linh hoạt và hiệu quả trong quá trình kiểm thử.
Cách tiếp cận này giúp rút ngắn thời gian phát triển dự án, tuy nhiên, điểm yếu của nó là có thể dẫn đến sự dư thừa đáng kể trong các ca kiểm thử hàm.
Hình 1.6 trình bày kết quả từ các ca kiểm thử được xác định qua các phương pháp kiểm thử hàm, trong đó phương pháp A cho ra một tập hợp ca kiểm thử lớn hơn so với phương pháp khác.
B Lưu ý rằng đối với cả hai phương pháp, tập các ca kiểm thử đều chứa trọn trong tập các hành vi được đặc tả Do các phương pháp kiểm thử hàm đều dựa trên các hành vi đặc tả, các phương pháp này khó có thể xác định được các hành vi không được đặc tả Trong bài 5 ta sẽ so sánh các ca kiểm thử sinh bởi các phương pháp hàm khác nhau cho các ví dụ nêu trong bài 2
Hình 1.6: So sánh các phương pháp xác định các ca kiểm thử hàm
Trong bài 5, chúng ta sẽ khám phá các phương pháp kiểm thử hàm chính, bao gồm phân tích giá trị biên, kiểm thử tính bền vững, phân tích trường hợp xấu nhất, kiểm thử giá trị đặc biệt, và kiểm thử phân lớp tương đương cho miền dữ liệu đầu vào và đầu ra, cùng với kiểm thử dựa trên bảng quyết định Tất cả các kỹ thuật này đều dựa trên thông tin rõ ràng về các thành phần được kiểm thử.
4.2 Kiểm thử cấu trúc có thể mô tả chính xác các yêu cầu kiểm thử và hệ thống cần kiểm thử Do có cơ sở lý thuyết mạnh, kiểm thử cấu trúc cho phép định nghĩa chính xác và sử dụng các độ đo về độ bao phủ Các độ đo về độ phủ cho phép khẳng định tường minh phần mềm đã được kiểm thử tới mức nào và do đó giúp cho việc quản lý quá trình kiểm thử tốt hơn
Hình 1.7: xác định ca kiểm thử đối với kiểm thử cấu trúc.
Hình 1.7 trình bày kết quả kiểm thử từ hai phương pháp kiểm thử cấu trúc, cho thấy phương pháp A tạo ra tập ca kiểm thử lớn hơn so với phương pháp B Câu hỏi đặt ra là liệu tập ca kiểm thử lớn hơn có thực sự tốt hơn không, và kiểm thử cấu trúc cung cấp các giải pháp để giải đáp vấn đề này Cả hai phương pháp A và B đều tạo ra các ca kiểm thử nằm trong tập hành vi đã được lập trình, nhưng việc xác định lỗi liên quan đến hành vi đã được xác định nhưng không được lập trình là rất khó Dễ nhận thấy rằng tập ca kiểm thử cấu trúc tương đối nhỏ so với toàn bộ hành vi lập trình Chúng ta sẽ so sánh các phương pháp này trong mục 1.4.3, và một số phương pháp kiểm thử cấu trúc như kiểm thử dòng điều khiển và kiểm thử dòng dữ liệu sẽ được giới thiệu chi tiết trong các chương sau.
4.3 Tranh luận về kiểm thử hàm so với kiểm thử cấu trúc
Khi so sánh hai cách tiếp cận khác nhau để xác định các ca kiểm thử, câu hỏi đặt ra là phương pháp nào hiệu quả hơn, nhưng cho đến nay vẫn chưa có câu trả lời thuyết phục Robert Poston chỉ trích kiểm thử cấu trúc, cho rằng công cụ này lãng phí thời gian của người kiểm thử và không hỗ trợ tốt cho việc kiểm thử phần mềm từ những năm 1970 Ngược lại, Edward Miller bảo vệ kiểm thử cấu trúc, nhấn mạnh rằng nếu độ bao phủ nhánh đạt 85% trở lên, nó có thể phát hiện gấp đôi số lỗi so với kiểm thử trực quan.
Hình 1.8: Nguồn các ca kiểm thử.
Biểu đồ Venn trong hình 1.8 giúp làm rõ sự khác biệt giữa hai cách tiếp cận kiểm thử: kiểm thử hàm và kiểm thử cấu trúc Mục tiêu chung của cả hai phương pháp là xác định các ca kiểm thử, nhưng kiểm thử hàm dựa vào đặc tả, trong khi kiểm thử cấu trúc dựa vào mã nguồn Không có phương pháp nào hoàn hảo, vì nếu các hành vi được đặc tả chưa được cài đặt, kiểm thử cấu trúc không thể phát hiện; ngược lại, nếu hành vi đã cài đặt không được đặc tả, kiểm thử hàm cũng không thể phát hiện Do đó, cả hai cách tiếp cận đều cần thiết, và sự kết hợp khéo léo giữa chúng sẽ mang lại độ tin cậy cao hơn cho quá trình kiểm thử.
Kiểm thử hàm có thể gặp phải vấn đề về tính dư thừa và hố phân cách Tuy nhiên, nếu kết hợp kiểm thử hàm với các số đo độ phủ của kiểm thử cấu trúc, những khiếm khuyết này có thể được phát hiện và khắc phục hiệu quả.
Biểu đồ Venn trong kiểm thử cung cấp cái nhìn sâu sắc về mối quan hệ giữa tập T các ca kiểm thử và các tập S và P, đại diện cho hành vi cài đặt và đặc tả Việc phân tích mối liên hệ này giúp hiểu rõ hơn cách thức các ca kiểm thử tương tác với các hành vi của hệ thống, từ đó nâng cao hiệu quả kiểm thử và đảm bảo chất lượng sản phẩm.
Các ca kiểm thử trong T được xác định bởi phương pháp xác định ca kiểm thử được sử dụng, và điều quan trọng là đánh giá tính hiệu quả của phương pháp này Để giải quyết vòng luẩn quẩn này, cần nhắc lại mối liên hệ giữa lỗi, sai sót, thất bại và sự cố Nếu hiểu rõ loại lỗi thường gặp và các sai sót phổ biến trong phần mềm, chúng ta có thể lựa chọn phương pháp phù hợp hơn để xác định các ca kiểm thử Đây chính là yếu tố làm cho kiểm thử trở thành một nghệ thuật.
Phân loại các lỗi và sai
Lỗi và sai được định nghĩa dựa trên sự phân biệt giữa quy trình và sản phẩm; quy trình mô tả cách thực hiện, trong khi sản phẩm là kết quả cuối cùng Kiểm thử phần mềm và đảm bảo chất lượng phần mềm (SQA) tương tác khi SQA cải thiện chất lượng sản phẩm thông qua cải tiến quy trình Kiểm thử tập trung vào phát hiện sai trong sản phẩm, trong khi SQA chú trọng vào việc giảm thiểu lỗi trong quá trình phát triển Cả hai đều dựa vào định nghĩa về các loại sai, được phân loại theo giai đoạn phát triển, hậu quả, độ khó giải quyết và mức độ rủi ro Một phân loại phổ biến dựa trên tần suất xuất hiện của sai, từ một lần đến lặp đi lặp lại Hình 1.9 minh họa phân loại sai dựa trên độ nghiêm trọng của hậu quả.
2 Vừa Hiểu lầm hoặc thừa thông tin
3 Khó chịu Tên bị thiếu, cụt chữ hoặc hóa đơn có giá trị 0.0 đồng
4 Bực mình Vài giao dịch không được xử lý
5 Nghiêm trọng Mất giao dịch
6 Rất nghiêm trọng Xử lý giao dịch sai
7 Cực kỳ nghiêm trọng Lỗi rất nghiêm trọng xảy ra thường xuyên
8 Quá quắt Hủy hoại cơ sở dữ liệu
9 Thảm họa Hệ thống bị tắt
10 Dịch họa Thảm họa lây lan
Để xử lý các loại sai, tham khảo tiêu chuẩn IEEE 93 về phân loại các bất thường trong phần mềm Tiêu chuẩn này định nghĩa quy trình giải quyết bất thường qua bốn giai đoạn: nhận biết, khảo sát, hành động và bố trí lại Các bất thường phổ biến được trình bày trong các bảng từ Bảng 1.1 đến Bảng 1.5, hầu hết đã được đề cập trong tiêu chuẩn IEEE, cùng với một số bất thường bổ sung khác.
Các mức kiểm thử
Một trong những khái niệm quan trọng trong kiểm thử phần mềm là các mức kiểm thử, phản ánh mức độ trừu tượng trong mô hình thác nước của vòng đời phát triển phần mềm.
Bảng 1.1: Các sai lầm về đầu vào/đầu ra
Trong quá trình xử lý dữ liệu, có nhiều loại trường hợp có thể xảy ra Đầu tiên, dữ liệu đầu vào có thể đúng nhưng không được chấp nhận Thứ hai, dữ liệu đầu vào sai nhưng vẫn được chấp nhận Ngoài ra, có thể xảy ra các trường hợp mô tả sai hoặc thiếu, tham số sai hoặc thiếu Kết quả đầu ra cũng có thể gặp phải nhiều vấn đề, như khuôn dạng sai, kết quả sai, hoặc đúng nhưng tại thời gian không phù hợp (quá sớm hoặc quá muộn) Thêm vào đó, kết quả có thể không đầy đủ hoặc thiếu, dẫn đến kết quả giả tạo Cuối cùng, các lỗi về văn phạm và chính tả cũng cần được lưu ý.
Mô hình thác nước, mặc dù có một số nhược điểm, vẫn rất hữu ích trong kiểm thử phần mềm Nó giúp xác định các mức kiểm thử khác nhau và làm rõ mục đích của từng mức Hình 1.10 minh họa một dạng của mô hình thác nước, nhấn mạnh sự tương ứng giữa kiểm thử và các mức thiết kế Theo các thuật ngữ kiểm thử hàm, ba mức định nghĩa (đặc tả, thiết kế sơ bộ và thiết kế chi tiết) tương ứng trực tiếp với ba mức kiểm thử: kiểm thử đơn vị, kiểm thử tích hợp và kiểm thử hệ thống.
Trong bảng 1.3, chúng ta điểm qua những sai lầm thường gặp trong tính toán thuật toán, bao gồm: tính toán sai, thiếu toán hạng, sai về dấu ngoặc, độ chính xác không đủ (do làm tròn hoặc cắt đuôi), và sử dụng hàm đi kèm không chính xác.
Bảng 1.4 liệt kê các sai lầm phổ biến trong giao diện xử lý gián đoạn ở hệ thống nhúng, bao gồm lỗi thời gian vào ra, gọi sai thủ tục, gọi đến thủ tục không tồn tại, và tham số không sánh cặp được do kiểu và số không tương thích Ngoài ra, kiểu không tương thích và bao hàm thừa cũng là những vấn đề cần lưu ý Các mức kiểm thử cũng tạo ra thách thức về thứ tự kiểm thử, có thể thực hiện theo phương pháp dưới lên, trên xuống hoặc các khả năng khác.
Các mức kiểm thử có thể được mô tả sơ bộ như sau:
Kiểm thử đơn vị là quá trình kiểm tra các đơn vị chương trình một cách độc lập, với đơn vị chương trình được hiểu là đoạn mã nguồn như hàm hoặc phương thức có thể gọi từ bên ngoài và tương tác với các đơn vị khác Việc kiểm thử này nhằm phát hiện và khắc phục lỗi nội tại trước khi tích hợp với các đơn vị khác Thông thường, kiểm thử đơn vị do chính tác giả thực hiện và có thể được chia thành hai giai đoạn: kiểm thử đơn vị tĩnh Các lỗi phổ biến trong kiểm thử đơn vị bao gồm sai sót về dữ liệu khởi tạo, lưu trữ và truy cập sai giá trị, sử dụng sai biến, và lỗi về kiểu dữ liệu hoặc phạm vi Việc phát hiện sớm những lỗi này giúp nâng cao chất lượng mã nguồn và đảm bảo tính ổn định của chương trình.
Hình 1.10: mức kiểm thử trong mô hình thác nước.
Kiểm thử tích hợp là bước tiếp theo sau kiểm thử đơn vị, nơi các đơn vị chương trình đã được kiểm thử sẽ được kết nối để tạo thành một hệ thống hoàn chỉnh Quá trình này không đơn giản, vì có thể phát sinh lỗi giao diện giữa các đơn vị, do đó cần phải kiểm thử để phát hiện những lỗi này Giai đoạn này bao gồm hai phần: kiểm thử tích hợp và kiểm thử hệ thống Mục tiêu của kiểm thử tích hợp là đảm bảo hệ thống hoạt động ổn định trong môi trường thử nghiệm, sẵn sàng cho việc triển khai vào môi trường thực tế bằng cách kết nối các đơn vị theo phương pháp tăng dần.
Kiểm thử hệ thống được thực hiện khi hệ thống đã hoàn chỉnh và tất cả các thành phần đã được tích hợp Mục tiêu chính của kiểm thử hệ thống là đảm bảo việc cài đặt đáp ứng đầy đủ các yêu cầu của người dùng Quá trình này đòi hỏi nhiều công sức do sự đa dạng trong các yêu cầu cần được kiểm tra Kỹ thuật kiểm thử hàm được đề cập trong bài 5 là phương pháp phù hợp nhất cho loại kiểm thử này.
Kiểm thử chấp nhận là giai đoạn quan trọng khi sản phẩm đã được nhóm kiểm thử hệ thống đánh giá và sẵn sàng đưa vào sử dụng Giai đoạn này được thực hiện bởi khách hàng để đảm bảo phần mềm hoạt động đúng như mong đợi Có hai loại kiểm thử chấp nhận: kiểm thử chấp nhận người dùng do người dùng thực hiện và kiểm thử chấp nhận doanh nghiệp do nhà sản xuất phần mềm tiến hành.
Bài tập của học viên
1: Trình bày mô tả bài toán kiểm thử qua biểu đồ venn
2: Nêu các mức kiểm thử
3: Hãy so sánh hai cách tiếp cận kiểm thử hàm và kiểm thử cấu trúc?
4: Phân loại các lỗi và sai
5 Hãy vẽ biểu đồ Venn phản ánh khẳng định: ta đã không làm cái mà lẽra ta cần phải làm, và làm cái mà lẽra ta không được làm
1: Trình bày mô tả bài toán kiểm thử qua biểu đồ venn, tham khảo mục 3 trong bài học trên
2: Nêu các mức kiểm thử, tham khảo mục 6 trong bài học trên
3: Hãy so sánh hai cách tiếp cận kiểm thử hàm và kiểm thử cấu trúc, tham khảo mục
4: Phân loại các lỗi và sai, tham khảo mục 5 trong bài học trên
5 Hãy vẽ biểu đồ Venn phản ánh khẳng định: ta đã không làm cái mà lẽra ta cần phải làm, và làm cái mà lẽ ra ta không được làm, tham khảo mục 3 trong bài học trên
Những trọng tâm cần chú ý
Trình bày đầy đủ nội dung của ca kiểm thử
Cần phải mô tả bài toán kiểm thử qua biểu đồ venn
Trình bày việc xác định các ca kiểm thử
Phân loại được đâu là lỗi và sai của chương trình
Bài mở rộng và nâng cao
Trong một câu chuyện cũ về lĩnh vực phần mềm, có một nhân viên cáu kỉnh đã phát triển một chương trình quản lý lương với chức năng kiểm tra số chứng minh thư của cán bộ và nhân viên Tuy nhiên, nếu nhân viên này bị sa thải, chương trình sẽ tự động tạo ra mã độc gây hại cho cơ quan Tình trạng này phản ánh những lỗi và sai sót trong quy trình phát triển phần mềm, đồng thời cho thấy sự thất bại trong việc đảm bảo an toàn và bảo mật Để khắc phục tình huống này, cần áp dụng các quyết định kiểm thử phù hợp nhằm phát hiện và ngăn chặn các lỗi tiềm ẩn trong mã nguồn.
Yêu cầu đánh giá kết quả học tập
+ Trình bày đầy đủ nội dung của ca kiểm thử
+ Cần phải mô tả bài toán kiểm thử qua biểu đồ venn
+ Trình bày việc xác định các ca kiểm thử
+ Phân loại được đâu là lỗi và sai của chương trình
Năng lực tự chủ và trách nhiệm: Tỉ mỉ, cẩn thận, chính xác, linh hoạt và ngăn nắp trong công việc.
Về kiến thức: Đánh giá bằng hình thức kiểm tra viết, trắc nghiệm, vấn đáp
Về kỹ năng: Đánh giá kỹ năng xác định được ca kiểm thử thử hàm, kiểm thử cấu trúc
Năng lực tự chủ và trách nhiệm: Tỉ mỉ, cẩn thận, chính xác, linh hoạt và ngăn nắp trong công việc.
MỘT SỐ VÍ DỤ
Bài toán tam giác
Bài toán tam giác nhận ba số nguyên là các số đo cạnh của tam giác Chương trình sẽ xác định loại tam giác tương ứng với ba cạnh này: tam giác đều (Equilateral), tam giác cân (Isosceles), tam giác thường (Scalene), hoặc không phải tam giác (NotATriangle) Đôi khi, bài toán được mở rộng để bao gồm loại tam giác vuông (Right Triangle) Trong các bài tập, chúng ta sẽ sử dụng phiên bản mở rộng này.
Bài toán này thường được sử dụng vì nó thể hiện rõ vấn đề định nghĩa không đầy đủ, ảnh hưởng đến việc trao đổi thông tin giữa khách hàng, nhà phát triển và người kiểm thử Đặc tả giả định rằng nhà phát triển hiểu rõ các tính chất của tam giác, cụ thể là tổng của hai cạnh bất kỳ phải lớn hơn cạnh còn lại, được thể hiện qua ba bất đẳng thức a < b + c, b < a + c và c < a + b Nếu một trong ba bất đẳng thức không thỏa mãn, a, b và c không thể tạo thành tam giác Tam giác đều xuất hiện khi ba cạnh bằng nhau, tam giác cân khi có một cặp cạnh bằng nhau, và tam giác thường khi không có cặp nào bằng nhau Một người kiểm thử giỏi có thể làm rõ bài toán bằng cách đặt giới hạn cho độ dài các cạnh, ví dụ yêu cầu các cạnh phải lớn hơn hoặc bằng 1 và có thể khai báo giới hạn trên là 20000.
Cài đặt truyền thống của ví dụ cổ điển này sử dụng kiểu tựa FORTRAN, nhưng chúng tôi đã chuyển sang ngôn ngữ C để đảm bảo tính thống nhất với các ví dụ khác trong giáo trình Sơ đồ khối của ví dụ được thể hiện trong hình 2.1, với các số trong sơ đồ tương ứng với các chú giải trong chương trình Một cài đặt có cấu trúc hơn sẽ được trình bày trong mục 1.4.
Hình 2.1: Sơ đồ khối cho cài đặt chương trình tam giác truyền thống.
Biến match được sử dụng để xác định sự bằng nhau giữa các cặp cạnh Khi hai cạnh bằng nhau, chẳng hạn như a = c, chỉ cần so sánh tổng a + c với b (vì b > 0, a + b > c sẽ luôn thỏa mãn) Quan sát này giúp giảm thiểu số lượng so sánh cần thực hiện Tuy nhiên, điều này có thể làm giảm tính rõ ràng và khả năng kiểm thử của quy trình.
In the following chapters, we will explore the advantages of this version of the program, particularly regarding the potential paths the program can take The program prompts the user to enter three integers representing the sides of a triangle, then checks for various conditions to determine the type of triangle formed It uses a matching variable to identify if the sides are equal, and subsequently evaluates whether the input values can form a valid triangle based on the triangle inequality theorem If the conditions are met, the program classifies the triangle as scalene, isosceles, or equilateral, or indicates that the values do not form a triangle This structured approach highlights the program's effectiveness in handling triangle classification based on user input.
Lưu ý là có sáu cách để đi đến nút “Not A Triangle” (12.1 – 12.6) và có ba cách để đi đến nút “Isosceles” (15.1 – 15.3)
1.4 Cài đặt có cấu trúc
Hình 2.2: Sơ đồ dòng dữ liệu cho cài đặt có cấu trúc của chương trình tam giác.
Hình 2.2 mô tả sơ đồ dòng dữ liệu của chương trình tam giác, được cài đặt thông qua một chương trình chính và bốn thủ tục Để phục vụ cho việc kiểm thử đơn vị sau này, bốn thủ tục đã được kết hợp thành một chương trình C Các dòng chú giải liên kết mã với phân rã trong hình 2.2.
//Function 1: Get Input printf("Enter 3 integers being sides of a triangle\n"); printf("a = ");scanf("%d",&a); printf("b = "); scanf("%d",&b); printf("c = "); scanf("%d",&c); printf ("Side A is ", a, "\n"); printf ("Side B is ", b, "\n"); printf ("Side C is ", c, "\n");
//Function 3: Determine Triangle Type if(IsATriangle) if((a == b) && (b == c)) printf("Triangle is Equilateral"); else if((a != b) && (a != c) && (b != c)) printf("Triangle is Scalene"); else printf("Triangle is Isosceles"); else printf("Not a Triangle"); return 0;
Lưu ý: Function 4 và Output Controller đã được kết hợp thành các lệnh trong Function 3
Hàm NextDate (ngày kế tiếp)
Độ phức tạp của chương trình tam giác chủ yếu đến từ các mối quan hệ giữa dữ liệu đầu vào và đầu ra Hàm NextDate thể hiện một loại độ phức tạp khác, đó là mối quan hệ giữa các biến đầu vào.
Hàm NextDate nhận ba biến: day, month và year, đại diện cho ngày, tháng và năm Hàm này cho phép người dùng xác định ngày tiếp theo dựa trên ngày đầu vào Các biến day, month và year phải tuân thủ các giới hạn: 1 ≤ day ≤ 31, 1 ≤ month ≤ 12, và 1812 ≤ year ≤ 2021.
Độ phức tạp của hàm NextDate xuất phát từ hai nguồn: ràng buộc của dữ liệu đầu vào và quy tắc phân biệt năm nhuận với năm không nhuận Trung bình, một năm có 365,2422 ngày, và năm nhuận giúp điều chỉnh các ngày "vượt trội" Theo lịch Gregorian, một năm được coi là nhuận nếu chia hết cho 4 nhưng không phải là năm thế kỷ, trừ khi năm đó chia hết cho 400 Ví dụ, các năm 1992, 1996 và 2000 là năm nhuận, trong khi năm 1900 không phải Hàm NextDate cũng minh họa cho khía cạnh kiểm thử phần mềm, nơi mà 80% mã nguồn được sử dụng cho các năm nhuận, tương ứng với quy luật Zipf, cho thấy sự phân bổ không đồng đều trong không gian hoạt động.
2.3 Cài đặt int mai(){ typedef struct{ int day; int month; int year;
To calculate tomorrow's date based on today's input, the user is prompted to enter the date in the format DD MM YYYY The program then assigns today's date to a variable for tomorrow If today's month is one of the months with 31 days, the program checks if the day is less than 31; if so, it increments tomorrow's day by one.
1; else{tomorrow.day = 1; tomorrow.month today.month + 1;
} if(today.month == 4 || today.month == 6 || today.month == 9 || today.month == 11) if(today.day < 30) tomorrow.day = today.day + 1; else{ tomorrow.day = 1; tomorrow.month today.month + 1;
} if(today.month == 12) if(today.day < 31) tomorrow.day = today.day + 1; else{ tomorrow.day = 1; tomorrow.month = 1; if(today.year == 2012) printf("2012 is over"); else tomorrow.year = today.year + 1;
} if(today.month == 2) if(today.day < 28) tomorrow.day = today.day + 1; else{ if(today.day == 28) if((today.year%4 == 0)&&(today.year%400 !0)) tomorrow.day = 29;//leap year else{ tomorrow.day := 1; tomorrow.month := 3;
} else if(today.day == 29){ tomorrow.day := 1; tomorrow.month := 3;
} else printf("Cannot have Feb.", today.day); printf("Tomorrow’s date is %3d %3d %5d", } tomorrow.day, tomorrow.month, tomorrow.year); return 0;
Hệ thống rút tiền tự động đơn giản
Để dễ dàng bàn luận về kiểm thử tích hợp và kiểm thử hệ thống, chúng ta cần một ví dụ có phạm vi rộng, như hệ thống rút tiền tự động (ATM) được trình bày trong [ADP93] Hệ thống này có nhiều biến thể về chức năng và giao diện, phù hợp với các hệ thời gian thực Mặc dù vậy, nó cũng liên quan đến các vấn đề mà các hệ thống COBOL truyền thống trong lĩnh vực thương mại điện tử thường gặp phải.
Hình 2.3: Trạm rút tiền ATM.
Hệ thống rút tiền tự động giao tiếp với các khách hàng của ngân hàng thông qua
Khách hàng có thể thực hiện ba loại giao dịch trên màn hình: gửi tiền vào tài khoản, rút tiền và kiểm tra số dư Các giao dịch này áp dụng cho hai loại tài khoản, bao gồm tài khoản tiết kiệm và tài khoản vãng lai.
Hình 2.4: Các màn hình của máy ATM đơn giản
Khi khách hàng đến trạm rút tiền, màn hình đầu tiên sẽ hiện lên Khách hàng sử dụng thẻ nhựa chứa mã số tài khoản cá nhân (PAN) để truy cập vào hệ thống Nếu mã PAN khớp với thông tin trong hồ sơ khách hàng, màn hình thứ hai sẽ được hiển thị Ngược lại, nếu mã PAN không tồn tại, màn hình thứ tư sẽ xuất hiện và thẻ sẽ bị giữ lại.
Trên màn hình 5, hệ thống cập nhật thông tin tài khoản khách hàng bằng cách thêm ngày hiện tại và tăng số lượng khoản mục về ATM Khách hàng có thể chọn giao dịch mong muốn từ các tùy chọn trên màn hình 3 Ngay sau đó, hệ thống chuyển sang màn hình 6, nơi khách hàng có thể lựa chọn tài khoản để thực hiện giao dịch đã chọn.
Khi yêu cầu kiểm tra số dư, hệ thống sẽ kiểm tra tệp ATM địa phương để xác định các giao dịch chưa gửi và kết hợp chúng với số dư ban đầu trong tệp tài khoản khách hàng của ngày hôm đó Sau đó, màn hình 14 sẽ được hiển thị.
Khi yêu cầu gửi tiền vào tài khoản, trạng thái của khe phong bì gửi tiền được xác định từ tệp điều khiển của trạm Nếu không có vấn đề, hệ thống hiển thị màn hình 7 để nhận tiền giao dịch; nếu có vấn đề, màn hình 12 sẽ được hiển thị Sau khi tiền gửi được nạp, màn hình 13 xuất hiện, chấp nhận phong bì và xử lý giao dịch Lượng tiền gửi được nạp là số tiền chưa gửi trong tệp ATM địa phương, và số lần gửi trong tháng sẽ được tăng lên Cả hai thông số này được xử lý bởi hệ ATM chủ một lần mỗi ngày, sau đó hệ thống hiển thị màn hình 14.
Khi khách hàng yêu cầu rút tiền, hệ thống sẽ kiểm tra trạng thái của khe nhả tiền Nếu khe bị kẹt, màn hình 9 sẽ xuất hiện; ngược lại, màn hình 7 sẽ cho phép khách hàng khai báo số tiền muốn rút Sau khi nhập dữ liệu, hệ thống xác minh số tiền trong máy có đủ không Nếu không đủ, màn hình 9 sẽ hiện lên, còn nếu đủ, quá trình rút tiền sẽ tiếp tục Hệ thống cũng kiểm tra số dư tài khoản của khách hàng; nếu không đủ, màn hình 8 sẽ hiển thị Nếu số dư đủ, màn hình 11 sẽ xuất hiện và tiền sẽ được nhả ra Số tiền rút được ghi vào tệp ATM địa phương và số lần rút trong tháng sẽ được tăng lên Cuối cùng, số dư tài khoản sẽ được in ra trong sao kê và sau khi khách hàng nhận tiền, màn hình 14 sẽ được hiển thị.
Khi khách hàng chọn nút No trên các màn hình 10, 12 hoặc 14, hệ thống sẽ hiển thị màn hình 15 và trả lại thẻ ATM cho khách Sau khi khách hàng nhận thẻ, hệ thống sẽ trở lại màn hình 1 Ngược lại, nếu khách hàng chọn nút Yes trên các màn hình này, hệ thống sẽ chuyển sang màn hình 5 để khách hàng có thể chọn các giao dịch khác.
Một lượng lớn thông tin đã bị lãng quên trong hệ thống đã mô tả Chẳng hạn, chúng ta có thể suy ra rằng trạm chỉ bao gồm các tờ 10 ngàn đồng Định nghĩa bằng văn bản có thể chính xác hơn so với thực tế Ví dụ này được thiết kế một cách đơn giản nhưng có tính toán.
Có nhiều câu hỏi cần giải quyết liên quan đến các giả thiết về giới hạn cho vay và cách ngăn chặn khách hàng rút tiền vượt quá số dư thực tế từ nhiều máy ATM trong cùng một ngày Các vấn đề khởi tạo như số tiền có trong máy và số lượng khách hàng mới được thêm vào hệ thống cũng cần được xem xét Những chi tiết thực tiễn này thường bị bỏ qua để đảm bảo tính đơn giản trong quy trình.
4 Bộ điều khiển gạt nước ô tô
Cần gạt nước ô tô trên xe Saturn năm 1992 được điều khiển qua một chốt và một núm vặn Chốt có bốn vị trí: OFF, INT (thỉnh thoảng), LOW và HIGH, trong khi núm vặn có ba vị trí được đánh số từ 1 đến 3, tương ứng với ba tốc độ chậm khác nhau Núm vặn chỉ có tác dụng khi chốt ở vị trí INT Bảng 2.1 mô tả các tốc độ của cần gạt tương ứng với các vị trí của chốt và núm vặn, trong đó giá trị n/a chỉ ra trường hợp không áp dụng.
Bảng 2.1: Tốc độ của cần gạt ứng với từng vị trí của chốt và núm vặn
Chốt OFF INT INT INT LOW HIGH
Bài tập của học viên
1 Xem lại sơ đồ khối của bài toán tam giác trong hình 2.1 Liệu biếnchương trình match có thể có: giá trị 4?, giá trị 5? Liệu có thể tiến hành dãy các khối 1, 2, 5, 6?
2 Nhắc lại lời bàn trong bài 1 về mối quan hệ giữa đặc tả và càiđặt của chương trình Nếu xem xét cẩn thận việc cài đặt của hàm NextDate, bạn sẽ thấy một vấn đề như sau Hãy nhìn vào lệnh CASE đối với các tháng có 30 ngày (4, 6,
Trong trường hợp day = 31, không có hành động đặc biệt nào được thực hiện Cần xem xét tính hợp lý của cài đặt này Đồng thời, cũng cần lặp lại phân tích tương tự cho việc xử lý các trường hợp day ≥ 29 trong lệnh CASE liên quan đến tháng Hai.
3 Trong chương 1, ta đã nói rằng một bộ phận của ca kiểm thử là dữ liệuđầu ra mong đợi Đối với hàm NextDate bạn dùng cái gì làm dữ liệu đầu ra mong đợi cho các ca kiểm thử của ngày 31 tháng 6 năm 1812 (June 31, 1812)? Tại sao?
KIỂM THỬ HÀM
Tổng quan
Kiểm thử hàm (functional testing) là hoạt động kiểm tra chương trình dựa trên tài liệu mô tả chức năng, hay còn gọi là đặc tả chức năng Tài liệu này mô tả yêu cầu và hành vi mong muốn của chương trình, là cơ sở để xây dựng các ca kiểm thử, được gọi là thiết kế kiểm thử Thiết kế kiểm thử là hoạt động chính trong kiểm thử hàm, mà không dựa vào phân tích mã nguồn của chương trình Kiểm thử hàm còn được gọi là kiểm thử dựa trên đặc tả, kiểm thử hộp đen, hay kiểm thử chức năng Ngược lại, thiết kế kiểm thử dựa vào mã nguồn được gọi là kiểm thử cấu trúc hay kiểm thử hộp trắng.
Kiểm thử hàm là kỹ thuật quan trọng giúp phát hiện lỗi mà kiểm thử hộp trắng không thể nhận ra, đặc biệt là các lỗi do cài đặt không đầy đủ so với đặc tả Trong khi việc thiếu hoàn toàn một chức năng dễ dàng được nhận diện, thì việc thiếu một trường hợp cụ thể trong chức năng lại khó phát hiện nếu không tiến hành kiểm tra kỹ lưỡng chương trình theo đặc tả.
Tài liệu đặc tả là nguồn thông tin quan trọng để thiết kế các ca kiểm thử, thường bao gồm mô tả chức năng của chương trình bằng ngôn ngữ dễ hiểu Ngoài ra, tài liệu còn có thể chứa các phân tích và thiết kế chi tiết hơn, kèm theo hình vẽ, bảng biểu và sơ đồ, giúp làm rõ hành vi của chương trình Những tài liệu này cung cấp cái nhìn sâu sắc về các tính chất hàm của chương trình, từ đó làm cơ sở cho việc thiết kế kiểm thử hiệu quả Tất cả những tài liệu này được gọi chung là đặc tả chức năng.
Kiểm thử hàm có ưu điểm nổi bật là có thể thực hiện sớm, ngay cả trước khi cài đặt chương trình, dựa trên đặc tả chức năng Thời điểm lý tưởng để bắt đầu thiết kế kiểm thử là khi tài liệu đặc tả đã ổn định Tuy nhiên, nhiều quy trình phần mềm hiện đại khuyến khích việc này diễn ra sớm hơn, trong giai đoạn xác định yêu cầu, khi các ca kiểm thử được lồng ghép vào quá trình Các ca kiểm thử thường được mô tả dưới dạng ví dụ, không chỉ giúp giải thích rõ ràng tài liệu đặc tả mà còn có thể sử dụng làm kịch bản kiểm thử.
Kết quả của việc thiết kế kiểm thử hàm thường dẫn đến việc tạo ra đặc tả ca kiểm thử, tương tự như đặc tả chương trình mô tả các yêu cầu mong muốn Đặc tả kiểm thử xác định các ca kiểm thử cần thiết để kiểm tra chương trình Từ một đặc tả ca kiểm thử, có thể phát triển nhiều ca kiểm thử cụ thể Ví dụ, với hàm giải phương trình bậc hai có đầu vào là ba hệ số a, b, c, đặc tả ca kiểm thử cho nghiệm kép yêu cầu b² = 4ac Từ đó, ta có thể tạo ra ca kiểm thử cụ thể như a = 1, b = 2, c = 1, với kết quả mong đợi là nghiệm kép −1.
Bản chất của các đặc tả ca kiểm thử là xác định các lớp hành vi của chương trình Thiết kế kiểm thử hàm là quá trình phân tách các đặc tả hành vi của chương trình thành những lớp có hành vi nhất quán hoặc tương tự Ví dụ, đối với hàm giải phương trình bậc hai, chúng ta có thể chia đặc tả thành các hành vi như phương trình có nghiệm kép và phương trình vô nghiệm.
Phân tích đặc tả giúp xác định và phân tách các lớp trong quá trình thiết kế kiểm thử, đồng thời chỉ ra những điểm không rõ ràng và thiếu sót Quá trình này tổng hợp nhiều nguồn thông tin từ đặc tả và kinh nghiệm của người thiết kế, nhưng mang tính thủ công và dễ mắc lỗi Nhiều chuyên gia thiết kế kiểm thử thường bỏ sót các ca kiểm thử quan trọng Để giảm thiểu sai sót, cần có phương pháp hệ thống chia quá trình thiết kế thành các bước cơ bản, trong đó một số bước có thể tự động hóa nhằm giảm công sức và tăng chất lượng Tuy nhiên, một số bước vẫn phải thực hiện thủ công, vì vậy kỹ năng và kinh nghiệm của người thiết kế kiểm thử là yếu tố quyết định chất lượng bộ kiểm thử Giả sử thiết kế kiểm thử cho chương trình P với Y = P(X), trong đó X là vec-tơ đầu vào và Y là vec-tơ đầu ra, chúng ta có thể tính được kết quả mong đợi Y dựa trên giá trị cụ thể của vec-tơ đầu vào X.
Để xác minh tính chính xác của chương trình P(X), chúng ta cần so sánh kết quả mong đợi Y với kết quả thực tế của chương trình Nếu Y và P(X) khớp nhau, điều đó chứng tỏ chương trình đã hoạt động đúng với giá trị X Nếu chương trình hoạt động chính xác với mọi giá trị X theo yêu cầu trong đặc tả, chúng ta có thể kết luận rằng chương trình P đã được cài đặt đúng theo đặc tả.
1.1 Sự phức tạp của kiểm thử hàm Để hiểu sự phức tạp của kiểm thử hàm chúng ta xem một chương trình đơn giản Y
Hàm roots(X) được sử dụng để tính nghiệm của phương trình bậc hai với đầu vào là ba tham số a, b, c, và trả về hai biến root_one, root_two Kết quả của hàm này không được trả về như một hàm toán học thông thường, mà thay vào đó, nó sử dụng các biến toàn cục để lưu trữ kết quả Do đó, khi xác định các tham số đầu vào a, b, c, và kết quả Y, cần phải cẩn thận để tránh nhầm lẫn trong quá trình tính toán.
Để thiết kế kiểm thử cho hàm giải phương trình bậc hai, chúng ta cần xác định các bộ giá trị cho a, b, c và tính toán kết quả mong đợi cho hai nghiệm bằng tay Sau đó, chúng ta sẽ chạy chương trình với các bộ giá trị này và so sánh kết quả thu được với kết quả mong đợi Trong đoạn mã trước, chúng ta đã giả định rằng các biến a, b, c có kiểu double Nếu đơn giản hóa, giả sử chúng là các biến kiểu số nguyên 32-bit, số lượng giá trị có thể có lên đến 2^23 ≈ 8 triệu.
10 28 giá trị hợp lệ cho a, b, c Nếu giả sử chương trình chạy với tốc độ 1.000.000.000.000
(1 tỷ) ca kiểm thử mỗi giây thì chúng ta vẫn cần đến hơn 2.5 tỷ năm mới chạy xong (chính xác là 2,510,588,971 năm, 32 ngày, và 20 giờ)
Kiểm thử theo kiểu vét cạn giúp xác nhận tính chính xác của hàm, nhưng việc tính toán thủ công các kết quả mong đợi với số lượng lớn là không khả thi Ngay cả việc sử dụng máy tính cũng không đủ hiệu quả để xử lý khối lượng tính toán lớn trong thực tế.
Một phương pháp khác để kiểm thử hàm roots là sử dụng các bộ giá trị ngẫu nhiên của X Tuy nhiên, phương pháp này khó có thể tạo ra các ca kiểm thử thỏa mãn điều kiện 2 − 4ac = 0 Phân phối của các khả năng nghiệm, nghiệm kép và không có nghiệm là không đồng nhất, khiến cho kiểm thử ngẫu nhiên khó phát hiện lỗi trong các trường hợp đặc biệt Vì vậy, cần thiết phải có một phương pháp tốt hơn để áp dụng cho các trường hợp tổng quát.
Trước hết chúng ta hãy xem các công việc chính của thiết kế kiểm thử cho chương trình Y = P(X):
Để phân tích một hệ thống, trước tiên cần xác định các biến đầu vào (X) và đầu ra (Y), cũng như miền giá trị của từng biến Cụ thể, X bao gồm các biến x₁, x₂, , xₙ và Y bao gồm các biến y₁, y₂, , yₘ Điều quan trọng là xác định miền giá trị cho từng biến, tức là Dom(xᵢ) cho i = 1 đến n và Dom(yⱼ) cho j = 1 đến m, trong đó Dom(x) đại diện cho tập hợp các giá trị mà biến x có thể nhận.
Chọn một số bộ giá trị của X để thực hiện kiểm thử, và tiến hành tính toán kết quả mong đợi cho từng bộ giá trị đầu vào Đối với mỗi bộ giá trị đầu vào cụ thể, ví dụ
Để đánh giá tính chính xác của chương trình P(a1, , an), chúng ta cần tính toán Y = (b1, , bm) để so sánh kết quả Việc tính toán này có thể trở nên phức tạp đối với các chương trình lớn Quy trình chọn bộ giá trị đầu vào thường dựa trên hiểu biết về miền dữ liệu, bao gồm việc lựa chọn các giá trị đặc biệt và giá trị bình thường, sau đó kết hợp chúng để tạo ra các trường hợp kiểm thử hiệu quả.
Kiểm thử bằng bảng quyết định
Kỹ thuật kiểm thử lớp tương đương và kiểm thử giá trị biên là những phương pháp hiệu quả cho các hàm có biến đầu vào không có quan hệ ràng buộc Bằng cách sử dụng bảng quyết định, chúng ta có thể phân tích các hành vi khác nhau của hàm dựa trên tính chất của bộ giá trị đầu vào.
Kiểm thử dựa trên bảng quyết định là một trong những phương pháp chính xác nhất trong kỹ thuật kiểm thử chức năng Bảng quyết định giúp mô tả hiệu quả các điều kiện và hành vi xảy ra khi những điều kiện này được thỏa mãn.
Cấu trúc bảng quyết định chia thành bốn phần chính như trong Hình 3.9:
• Các biểu thức điều kiện C1, C2, C3.
• Giá trị hành động, có (xảy ra) hay không, X là có
Khi lập bảng quyết định, chúng ta cần xác định các điều kiện có thể xảy ra để đánh giá các tổ hợp của chúng Từ đó, chúng ta sẽ xác định các ca kiểm thử tương ứng với các điều kiện được thỏa mãn Hành động xảy ra chính là kết quả mong đợi của từng ca kiểm thử.
Bảng quyết định logic chỉ bao gồm các giá trị điều kiện T, F và – Tuy nhiên, chúng ta có thể mở rộng các giá trị này bằng cách sử dụng các tập giá trị khác, chẳng hạn như 1, 2.
3, 4, khi đó chúng ta có bảng quyết định tổng quát
Bảng 3.10 minh họa một bảng quyết định đơn giản để xử lý sự cố máy in Khi gặp sự cố, chúng ta sẽ đánh giá tình trạng của máy in dựa trên các điều kiện có trong bảng, xác định cột duy nhất có các điều kiện thỏa mãn, và từ đó thực hiện các hành động khắc phục sự cố phù hợp.
Bảng 3.9: Ví dụ bảng quyết định
Bảng 3.10 trình bày quyết định khắc phục sự cố máy in Khi máy in không in và đèn đỏ nhấp nháy, cần kiểm tra dây nguồn Nếu máy in không được nhận ra, hãy kiểm tra các kết nối và đảm bảo rằng máy in đang hoạt động bình thường.
Kiểm tra cáp máy in X X Kiểm tra phần mềm in X X X X
Trong việc thiết lập bảng quyết định, thứ tự của các điều kiện và hành động không quan trọng, cho phép chúng ta thay đổi vị trí các hàng Tuy nhiên, để làm rõ hơn, có thể đánh số thứ tự cho các hành động thay vì sử dụng dấu X, nhằm chỉ ra hành động nào cần thực hiện trước Đối với bảng quyết định tổng quát, các giá trị của điều kiện không chỉ giới hạn ở đúng (T) hoặc sai (F), vì vậy cần tăng số cột để bao quát tất cả các tổ hợp có thể của các điều kiện.
Để xác định các ca kiểm thử từ bảng quyết định, cần chuyển đổi các điều kiện thành đầu vào và các hành động thành đầu ra Các điều kiện có thể xác định các lớp tương đương của đầu vào, trong khi các hành động tương ứng với các mô-đun xử lý chức năng đang được kiểm thử.
Bảng 3.11: Bảng quyết định cho Triangle Điều kiện 1 2 3 4 5 6 7 8 9 10 11 c1: a