Trong một số trường hợp, kiểm thử phần mềm liên quan đến con người như kiểm soát chuyến bay, điều khiển lò phản ứng hạt nhân có thể tốn kém gấp ba đến năm lần tất cả các bước kỹ nghệ phầ
Trang 1MỤC LỤC
LỜI NÓI ĐẦU 4
CHƯƠNG 1 GIỚI THIỆU TỔNG QUAN VỀ KIỂM THỬ PHẦN MỀM 6
1.1 Khái niệm kiểm thử phần mềm 6
1.2 Mục đích của kiểm thử 6
1.3 Các giai đoạn kiểm thử viên nên nghĩ tới trong quá trình kiểm thử 7
1.4 Các mức kiểm thử phần mềm 7
1.4.1 Kiểm thử được tiến hành bởi đội ngũ dự án 7
1.4.2 Kiểm thử được tiến hành bởi các cơ quan bên ngoài 8
1.4.3 Yêu cầu của mỗi mức kiểm thử 8
1.5 Luồng thông tin kiểm thử 9
1.6 Thiết kế trường hợp kiểm thử 10
CHƯƠNG 2 MỘT SỐ KỸ THUẬT KIỂM THỬ PHẦN MỀM 11
2.1 Biểu đồ luồng (Flow Graph) và kiểm thử đường dẫn (Path Testing) 11 2.1.1 Các khái niệm cơ bản của kiểm thử đường dẫn 11
2.1.1.1 Định nghĩa 11
2.1.1.2 Dự đoán lỗi 11
2.1.1.3 Biểu đồ luồng điều khiển 12
2.1.2 Kiểm thử đường dẫn 15
2.1.2.1 Đường dẫn, nút và liên kết 15
2.1.2.2 Tiêu chuẩn cho sự lựa chọn đường dẫn 16
2.1.2.3 Tiêu chuẩn cho kiểm thử đường dẫn 16
2.1.2.4 Ý nghĩa và các chiến lược chung 17
2.1.2.5 Hiệu quả của kiểm thử đường dẫn 17
2.2 Kiểm thử luồng giao dịch (Transaction-Flow Testing) 18
2.2.1 Giới thiệu 18
2.2.2 Luồng giao dịch 18
2.2.2.1 Định nghĩa 18
2.2.2.2 Sử dụng 19
2.2.2.3 Thực hiện 19
2.2.3.Kỹ thuật kiểm thử luồng giao dịch 20
2.2.3.1 Để có được các luồng giao dịch 20
2.2.3.2 Cơ sở dữ liệu kiểm thử 20
2.2.3.3 Thực hiện 20
2.3 Kiểm thử luồng dữ liệu (Data-Flow Testing) 21
2.3.1 Định nghĩa 21
2.3.2 Các mô hình mới – Các cỗ máy luồng dữ liệu 21
2.3.3 Biểu đồ luồng dữ liệu 21
2.3.3.1 Trạng thái của đối tượng dữ liệu và sử dụng 22
Trang 22.3.3.2 Các luồng dữ liệu bất thường 22
2.3.3.3 Biểu đồ trạng thái luồng dữ liệu bất thường 23
2.3.4 Mô hình luồng dữ liệu 23
2.3.4.1 Các thành phần của mô hình 23
2.3.4.2 Ví dụ: Xét hình 2.10 24
2.3.5 Các chiến lược kiểm thử luồng dữ liệu 25
2.3.5.1 Các thuật ngữ 25
2.3.5.2 Các chiến lược 26
2.4 Kiểm thử miền (Domain Testing) 27
2.4.1 Mô hình 27
2.4.2 Kích thước miền 29
2.4.3 Các miền tốt, miền xấu 29
2.4.3.1 Các miền tốt 29
2.4.3.2 Các miền xấu 31
2.4.4 Dự đoán lỗi 31
2.4.5 Chiến lược kiểm thử miền 31
2.5 Kiểm thử cú pháp (Syntax Testing) 32
2.5.1 Tổng quan 32
2.5.2 Cú pháp cho các định dạng - Ký hiệu BNF 32
2.5.2.1 Các phần tử 32
2.5.2.2 Các toán tử BNF 33
2.5.2.3 Sự lặp lại 33
2.5.2.4 Ví dụ 33
2.5.3 Thiết kế trường hợp kiểm thử 34
2.5.3.1 Chiến lược 34
2.5.3.2 Các lỗi cú pháp mức đỉnh, mức trung gian, mức trường 34
2.5.3.3 Lỗi dấu phân cách 36
2.5.3.4 Lỗi cú pháp phụ thuộc bối cảnh 37
2.5.3.5 Lỗi phụ thuộc trạng thái 37
2.6 Kiểm thử hộp đen (Black-box Testing) 37
2.6.1 Phân hoạch cân bằng 39
2.6.2 Phân tích cực biên 39
2.6.3 Đoán lỗi 40
2.6.4 Kỹ thuật biểu đồ nguyên nhân - kết quả 40
2.6.5 Kiểm thử so sánh 41
2.7 Kiểm thử hộp trắng (White-box Testing) 42
CHƯƠNG 3 CÁC CHIẾN LƯỢC KIỂM THỬ CHO CÁC LẬP TRÌNH VIÊN VÀ CÁC KIỂM THỬ VIÊN 43
3.1 Các chiến lược kiểm thử cho các lập trình viên 43
3.1.1 Lập trình hợp tác 43
3.1.2 Sự bảo trì 43
3.1.3 Tự thẩm định 44
3.1.4 Thiết kế trường hợp kiểm thử 44
Trang 33.1.5 Thứ tự ưu tiên các loại kiểm thử 45
3.2 Các chiến lược cho các kiểm thử viên độc lập 45
3.2.1 Tổng quát 45
3.2.2 Sự thay đổi ngữ nghĩa 45
3.2.3 Các thay đổi kiểu 47
3.2.4 Các thay đổi về sự biểu diễn 47
3.2.5 Những sự kết hợp và nạp chồng 47
3.2.6 Các phương pháp truy xuất khác nhau 48
3.2.7 Các tài nguyên động 48
3.2.8 Thay đổi phiên bản 49
3.2.9 Đọc mã và các tài liệu thiết kế khác 49
CHƯƠNG 4 ỨNG DỤNG THIẾT KẾ MỘT CÔNG CỤ KIỂM THỬ TỰ ĐỘNG 50
4.1 Giới thiệu 50
4.2 Thiết kế mô hình tổng thể 50
4.3 Xây dựng công cụ 53
4.3.1 Không gian tên (Namespace) 53
4.3.2 .NET Reflection 55
4.3.3 Bảng tính (Spreadsheet) và XML 55
4.3.4 Không gian tên NET CodeDOM 58
4.3.5 Thiết kế các form 60
4.3.5.1 Giao diện chính của công cụ 60
4.3.5.2 Form Kiểu kiểm thử 61
4.3.5.3 Form Quyết định kiểm thử tự động/bằng tay 61
4.4 Kết quả chạy thử nghiệm 62
4.4.1 Kiểm thử một assembly – Kiểm thử đơn vị 62
4.4.2 Kiểm thử các tham số được truyền là đối tượng - Kiểm thử tích hợp 71
4.4.3 Kiểm thử với nhiều tập dữ liệu kiểm thử 76
4.4.4 Kiểm thử các phương thức nạp chồng 77
4.4.5 Kiểm thử các tham số được truyền là các mảng 79
4.5 Nhận xét, đánh giá kết quả thu được 80
4.5.1 Cải tiến kiểm thử đơn vị 80
4.5.2 Tự động tạo dữ liệu kiểm thử 81
4.5.3 Cách tiếp cận duy nhất cho kiểm thử tích hợp 81
4.5.4 Có khả năng cập nhật với những khả năng kiểm thử mới 81
4.5.5 Viết test script dựa vào dữ liệu 81
KẾT LUẬN 83
TÀI LIỆU THAM KHẢO 84
PHỤ LỤC 85
Trang 4LỜI NÓI ĐẦU
Công nghệ phần mềm (Software Engineering) là sự áp dụng một cách có
hệ thống, có kỷ luật và định lượng được cho việc phát triển, hoạt động và bảo trì phần mềm Ngành học kỹ nghệ phần mềm bao gồm các kiến thức, các công cụ và các phương pháp cho việc định nghĩa yêu cầu phần mềm, thực hiện các tác vụ thiết kế phần mềm, xây dựng phần mềm, kiểm thử phần mềm (Software testing)
và bảo trì phần mềm Kiểm thử phần mềm là một trong những giai đoạn của kỹ nghệ phần mềm, là giai đoạn mấu chốt trong quy trình phát triển phần mềm nhằm đảm bảo chất lượng của phần mềm Trong thời đại ngày nay, khi mà ngành công nghiệp phần mềm phát triển như vũ bão thì những yêu cầu về chất lượng phần mềm ngày càng trở nên nghiêm ngặt hơn
Tuy nhiên thực tế ở Việt Nam và nhiều nước khác, kiểm thử phần mềm chưa được coi trọng như đúng vai trò của nó Việc thiết kế kiểm thử và kiểm thử chưa được tiến hành một cách có hệ thống, có phương pháp Để có thể nắm vững
và phần nào triển khai ứng dụng về lĩnh vực này, em đã chọn đề tài “Kiểm thử phần mềm và ứng dụng thiết kế một công cụ kiểm thử tự động” làm đồ án tốt nghiệp của mình
Mục đích của đồ án là tìm hiểu, hệ thống các khái niệm cơ bản, các chiến lược, kỹ thuật kiểm thử phần mềm, trên cơ sở đó xây dựng thử nghiệm một hệ thống kiểm thử phần mềm đơn giản
Đồ án gồm 4 nội dung chính như sau:
Chương 1 Giới thiệu tổng quan về kiểm thử phần mềm
Chương 2 Một số kỹ thuật kiểm thử phần mềm
Chương 3 Các chiến lược kiểm thử cho các lập trình viên và các kiểm thử viên
Chương 4 Ứng dụng phát triển một công cụ kiểm thử tự động
Hiện nay ở Việt Nam các công cụ, các phần mềm ứng dụng còn chưa được
sử dụng một cách rộng rãi, mỗi phần mềm ứng dụng đểu nhằm đạt được một mục tiêu là giải quyết một bài toán cụ thể nào đó chứ chưa phải là phần mềm có tính
Trang 5chất thương mại, được sử dụng cho một lớp rộng rãi các lĩnh vực gần nhau, cũng chưa xuất hiện nhiều việc có các phần mềm cũng nhằm một lớp bài toán nào đó cạnh tranh với nhau Trong bối cảnh đó, việc xây dựng các phần mềm kiểm thử
để đánh giá hiệu năng của phần mềm chưa phải là vấn đề cấp bách, song với xu thế phát triển trong nước cũng như trên thế giới về công nghệ phần mềm, việc xây dựng các bộ phần mềm kiểm thử, đánh giá tính đúng đắn cũng như hiệu năng của phần mềm ứng dụng là một việc làm tất yếu sẽ đến Song trước mắt việc thực hiện đề tài này còn gặp nhiều khó khăn, vì vậy kết quả nghiên cứu và thực nghiệm còn có nhiều hạn chế Em hy vọng rằng trong tương lai có thể tiếp tục phát triển ý tưởng cũng như xây dựng được sản phẩm kiểm thử đáp ứng được yêu cầu thực tiễn và hữu ích cho người sử dụng
Trang 6CHƯƠNG 1 GIỚI THIỆU TỔNG QUAN VỀ KIỂM THỬ
PHẦN MỀM
Mục đích của chương này là đưa ra một cái nhìn tổng thể về kiểm thử phần mềm: kiểm thử phần mềm là gì, có những loại kiểm thử phần mềm nào, mục đích của kiểm thử phần mềm là gì và tiến trình kiểm thử phần mềm được tiến hành như thế nào?
1.1 Khái niệm kiểm thử phần mềm
Kiểm thử phần mềm là khâu mấu chốt để đảm bảo chất lượng phần mềm,
là đánh giá cuối cùng về các đặc tả, thiết kế và mã hoá
Kiểm thử phần mềm là quá trình chạy thử một ứng dụng để phát hiện lỗi
và xem nó có thoả mãn các yêu cầu đã đặt ra Trong quá trình phát triển phần mềm, những người phát triển phần mềm và các kỹ sư kiểm thử cùng làm việc để phát hiện lỗi và đảm bảo chất lượng sản phẩm Một sản phẩm phần mềm được phân phối phải có đầy đủ các chức năng yêu cầu và tương thích với phần cứng của khách hàng
Hoạt động kiểm thử ít được các nhà quản lý chú ý vì nó tốn kém, mất thời gian và hiếm khi phát hiện được lỗi Hơn nữa, một tổ chức phát triển phần mềm không chấp nhận chi đến 40% tổng năng lực dự án cho kiểm thử Trong một số trường hợp, kiểm thử phần mềm liên quan đến con người (như kiểm soát chuyến bay, điều khiển lò phản ứng hạt nhân) có thể tốn kém gấp ba đến năm lần tất cả các bước kỹ nghệ phần mềm khác cộng lại Kết quả là phần lớn các ứng dụng không được kiểm thử đầy đủ và được phân phối mà vẫn tiềm ẩn lỗi
Trang 7Thiết kế kiểm thử và kiểm thử nên tập trung vào ngăn ngừa lỗi Với khu vực thiết kế kiểm thử và kiểm thử không ngăn ngừa được lỗi thì chúng cũng nên phát hiện ra dấu hiệu của lỗi Các lần kiểm thử nên cung cấp những chuẩn đoán
dễ hiểu để lỗi có thể dễ dàng được sửa Ngăn ngừa lỗi là mục tiêu đầu tiên của kiểm thử, ngăn ngừa được một lỗi sẽ tốt hơn là phát hiện rồi sửa lỗi vì khi ngăn ngừa được lỗi thì sẽ không phải sửa mã Hơn nữa, không cần phải kiểm tra lại xem việc sửa lỗi là đúng đắn, không tiêu tốn bộ nhớ, không phá vỡ kế hoạch làm việc Có vai trò lớn hơn, thiết kế kiểm thử là một trong những công cụ ngăn chặn lỗi tốt nhất được biết đến Mục đích là tạo ra sự kiểm thử có ích để có thể phát hiện và loại bỏ lỗi trước khi chúng được viết mã Trên thực tế thiết kế kiểm thử
có thể phát hiện và loại bỏ lỗi tại mọi giai đoạn của quá trình thiết kế phần mềm,
từ ý tưởng đến đặc tả, thiết kế, viết mã và phần còn lại
1.3 Các giai đoạn kiểm thử viên nên nghĩ tới trong quá trình kiểm thử
Tại sao phải kiểm thử? Mục đích của việc kiểm thử là gì? Tiến trình được
mô tả bởi năm giai đoạn sau:
Giai đoạn 0: Không có sự khác biệt nào giữa kiểm thử và gỡ lỗi, kiểm thử để hỗ trợ cho gỡ lỗi
Giai đoạn 1: Kiểm thử để cho thấy phần mềm làm việc
Giai đoạn 2: Kiểm thử để cho thấy phần mềm không làm việc
Giai đoạn 3: Mục đích của kiểm thử là làm giảm những rủi ro nhận thấy khi phần mềm không làm việc tới mức có thể chấp nhận được
Giai đoạn 4: Kiểm thử không phải là quy luật mà là hoạt động trí óc để thu được phần mềm với rủi ro thấp mà không mất quá nhiều công sức
1.4 Các mức kiểm thử phần mềm
Các phép kiểm thử có mặt tại các mức khác nhau và được tiến hành bởi các cá nhân khác nhau trong quá trình phát triển ứng dụng
1.4.1 Kiểm thử được tiến hành bởi đội ngũ dự án
Được gọi là kiểm thử phát triển (Development tesingt) bao gồm:
Trang 8 Kiểm thử đơn vị (Unit testing): được tiến hành cho mỗi đơn vị mã nhỏ
nhất như hàm, module
Kiểm thử tích hợp (Integration testing): kiểm thử mặt logic và xử lý
của các khối, kiểm thử việc truyền tin giữa chúng Kiểm thử viên sẽ tiến hành kiểm thử giao diện, sự tương tác giữa các thành phần, module, cửa sổ
Kiểm thử chức năng (Functional testing): kiểm thử ở bất kỳ mức độ
nào (lớp, module, giao diện hay hệ thống) để kiểm tra xem nó có đúng với các đặc tả hay không?
Kiểm thử hệ thống (System testing): kiểm thử hệ thống một cách toàn
diện để đánh giá các đặc tả chức năng có được đáp ứng, các thao tác giao diện có giống thiết kế không?
Kiểm thử tích hợp hệ thống (System integration testing): kiểm tra hệ
thống có tích hợp đúng với các phần mềm của hãng thứ ba hay các giao diện của hệ thống khác hay không?
Kiểm thử sự thực thi (Performance testing): Để kiểm tra hiệu suất của
chương trình có đáp ứng được như mong đợi hay không?
1.4.2 Kiểm thử được tiến hành bởi các cơ quan bên ngoài
Được gọi là đảm bảo chất lượng (Quality Assurance - QA) và kiểm thử chấp nhận (Acceptance testing) Người ngoài có thể là người sử dụng hay đại
diện người dùng nằm ngoài sự điều khiển và quản lý của người quản lý dự án
QA testing tương tự system testing về mặt mục đích và cách tiến hành Các báo cáo kiểm thử QA được gửi thường xuyên tới người quản lý dự án Các
QA lập kế hoạch và kiểm tra để đảm bảo các ứng dụng thực hiện tất cả các chức năng cần thiết Kiểm thử QA là bước cuối cùng trước khi ứng dụng được sản xuất đại trà
1.4.3 Yêu cầu của mỗi mức kiểm thử
Mỗi mức kiểm thử đòi hỏi phải xác định chiến lược kiểm thử Đó là: Black box testing hay White box testing:
Trang 9 Black box testing: kiểm tra về mặt chức năng hoặc phi chức năng mà
không tham khảo cấu trúc bên trong của thành phần hay hệ thống Kết quả được dự đoán và so sánh với kết quả thực tế để đánh giá mức độ thành công
White box testing: việc kiểm tra dựa trên sự phân tích cấu trúc bên
trong của thành phần hoặc hệ thống đó
Top-down hay bottom-up:
Top-down: phương thức kiểm tra sự tích hợp mà các thành phần ở trên
hệ thông cấp bậc được kiểm tra trước, với các thành phần cấp thấp hơn được xem là phần gốc
Bottom-up: việc kiểm tra tích hợp trong đó các thành phần thuộc lớp
thấp nhất được kiểm tra trước, và sau đó được dùng để làm cho việc kiểm tra các thành phần thuộc lớp cao hơn được dễ dàng Qui trình này được lặp lại cho đến khi thành phần ở đầu của cấu trúc được kiểm tra
Các chiến lược kiểm thử không loại trừ lẫn nhau, sử dụng riêng rẽ hay đồng thời Với một ứng dụng phải sử dụng nhiều chiến lược để phát hiện được
hết lỗi Các chiến lược sau khi được xác định sẽ được áp dụng để tạo các trường hợp kiểm thử cụ thể
1.5 Luồng thông tin kiểm thử
Hình 1.1.Luồng thông tin kiểm thử
Gỡ lỗi
Mô hình tin cậy
Kiểm thử
Cấu hình
kiểm thử
Kết quả trông đợi
Đánh giá
Lỗi
Dữ liệu
tỷ lệ lỗi
Trang 10Hai lớp vào được cung cấp cho tiến trình kiểm thử:
Cấu hình phần mềm, bao gồm: bản đặc tả yêu cầu phần mềm, bản đặc
tả thiết kế và chương trình gốc
Cấu hình kiểm thử, bao gồm: kế hoạch và thủ tục kiểm thử
Kiểm thử được tiến hành và tất cả các kết quả đều được đánh giá Khi dữ liệu lỗi được phát hiện thì việc gỡ lỗi bắt đầu Quá trình gỡ lỗi là phần khó được
dự kiến trước của tiến trình kiểm thử, một lỗi chỉ ra sự sai biệt độ 0.01% giữa các kết quả mong đợi và thực tế có thể mất 1 giờ, 1 ngày, 1 tháng để chuẩn đoán và sửa chữa
Sau khi các kết quả kiểm thử được thu thập và đánh giá, cần có một chỉ dẫn định lượng về chất lượng và độ tin cậy phần mềm Nếu hay gặp phải những lỗi nghiêm trọng yêu cầu sửa đổi thiết kế thì chất lượng và độ tin cậy phần mềm
là đáng ngờ, cần phải có thêm các kiểm thử Còn nếu các chức năng phần mềm làm việc đúng, lỗi gặp phải dễ sửa thì có thể rút ra một trong hai kết luận:
Chất lượng và độ tin cậy phần mềm là chấp nhận được
Kiểm thử chưa thấy được những lỗi nghiêm trọng Nếu kiểm thử không phát hiện được lỗi nào thì có thể cấu hình kiểm thử chưa được cân nhắc đúng mức và lỗi vẫn còn tiềm ẩn trong phần mềm
1.6 Thiết kế trường hợp kiểm thử
Thiết kế kiểm thử cho phần mềm và các sản phẩm kĩ nghệ khác có thể khó khăn như việc thiết kế ban đầu cho chính sản phẩm Các kỹ sư phần mềm thường xem kiểm thử như việc giải quyết về sau, xây dựng các trường hợp kiểm thử có thể “cảm thấy đúng” nhưng hầu như không đảm bảo được tính đầy đủ
Trang 11CHƯƠNG 2 MỘT SỐ KỸ THUẬT KIỂM THỬ PHẦN
MỀM
Toàn bộ chương này được sử dụng để trình bày các kỹ thuật kiểm thử thường được sử dụng trong các dự án phần mềm Còn có rất nhiều kỹ thuật kiểm thử khác được sử dụng trong quá trình phát triển phần mềm Tuy nhiên, các kỹ thuật được trình bày dưới đây là các kỹ thuật cơ bản nhất đối với các kiểm thử viên hay thậm chí với cả các lập trình viên
2.1 Biểu đồ luồng (Flow Graph) và kiểm thử đường dẫn (Path Testing) 2.1.1 Các khái niệm cơ bản của kiểm thử đường dẫn
2.1.1.1 Định nghĩa
Path testing là lớp các kỹ thuật kiểm thử dựa trên sự lựa chọn chính xác
tập khả năng kiểm thử trong cả chương trình Tiêu chuẩn kiểm thử là hoàn hảo khi tập khả năng được chọn chính xác Ví dụ: chọn đường dẫn đầy đủ để mỗi câu lệnh trong mã nguồn được thực hiện ít nhất một lần
Các kỹ thuật kiểm thử đường dẫn là cổ nhất trong số các kỹ thuật kiểm thử
có cấu trúc được sử dụng tại IBM hơn hai thập niên Ý tưởng thực hiện mỗi câu lệnh và mỗi nhánh ít nhất một lần sau vài lần kiểm thử là của những người nghiên cứu sâu về kiểm thử phần mềm Chúng cũng là các kỹ thuật đầu tiên được nghiên cứu tỉ mỉ về lý thuyết Có nhiều bằng chứng chứng tỏ kiểm thử đường dẫn được phát hiện và sử dụng một cách độc lập ở rất nhiều nơi khác nhau
Kiểm thử đường dẫn có thể ứng dụng để kiểm thử đơn vị với phần mềm mới, yêu cầu kiểm thử viên phải có hiểu biết đầy đủ về cấu trúc của chương trình
và thường được sử dụng bởi những lập trình viên để kiểm tra từng phần trong mã nguồn Tác dụng của nó giảm khi kích thước của phần mềm tăng sau mỗi lần kiểm thử và ít khi được sử dụng cho kiểm thử hệ thống
Trang 12việc Y” thay vì “Nếu A sai …” Kiểm thử đường dẫn thừa nhận các đặc tả là đúng và có thể thực hiện được, do đó sẽ không có lỗi xử lý nào khác ảnh hưởng đến luồng điều khiển, dữ liệu được định nghĩa và truy nhập đúng cách Các ngôn ngữ lập trình có cấu trúc ngăn ngừa được nhiều lỗi do đó tác dụng của kiểm thử đường dẫn với các ngôn ngữ này bị giảm bớt Ngược lại, mã được viết bằng các ngôn ngữ bậc thấp như COBOL, FORTRAN và BASIC có tỉ lệ lỗi luồng điều khiển cao hơn nên không thể thiếu được kiểm thử đường dẫn
2.1.1.3 Biểu đồ luồng điều khiển
Biểu đồ luồng điều khiển là biểu đồ biểu diễn cấu trúc điều khiển của một chương trình, sử dụng các thành phần: khối xử lý, quyết định, điểm nối (hình 2.1) Biểu đồ luồng điều khiển cũng tương tự như biểu đồ tiến trình
Hình 2.2.Các thành phần trong biểu đồ luồng điều khiển
a) Khối xử lý
Một khối xử lý (tiến trình) là một chuỗi các câu lệnh không bị ngắt quãng bởi các quyết định hay điểm nối Về mặt hình thức nó là một chuỗi câu lệnh mà nếu bất kỳ một câu lệnh nào được thực hiện thì tất cả các câu lệnh từ đó cũng được thực hiện Một khối xử lý có thể chỉ là một câu lệnh cũng có thể là hàng
trăm câu lệnh
b) Quyết định và lựa chọn
Một quyết định là một điểm trong chương trình tại đó luồng điều khiển có thể rẽ nhánh Ví dụ: lệnh If trong FORTRAN, If-then-else trong PASCAL Trong luồng điều khiển hầu hết các quyết định là hai hướng, còn lại một số là ba hướng Thiết kế trường hợp kiểm thử với nhánh hai hướng nói chung dễ hơn ba hướng
Trang 13Một khai báo lựa chọn là một nhánh nhiều đường đi hay nhiều quyết định
Ví dụ: lệnh nhảy trong Assembly, GOTO trong Fortran hay CASE trong Pascal Theo quan điểm từ việc thiết kế kiểm thử thì không có sự khác biệt cơ bản nào giữa khai báo quyết định và khai báo lựa chọn
c) Điểm nối
Một điểm nối là một điểm trong chương trình tại đó luồng điều khiển có thể hợp nhất Ví dụ: đích của một lệnh nhảy hay bỏ qua trong Assembly, câu lệnh End-If và Continue trong Fortran, End và Until và các nhãn trong Pascal
d) Biểu đồ luồng điều khiển và biểu đồ tiến trình
Biểu đồ tiến trình của một chương trình tương tự như biểu đồ luồng nhưng khác nhau ở một điểm quan trọng: biểu đồ luồng điều khiển không đưa ra chi tiết của một khối xử lý và không quan tâm có bao nhiêu câu lệnh trong khối khi được xem như là một tiến trình đơn lẻ, ngược lại, mọi phần của khối xử lý đều được vẽ
ra trong biểu đồ tiến trình, nếu một khối xử lý có 100 bước thì biểu đồ tiến trình
NEXT U V(U-1):=V(U+1)+U(V-1) ELL: V(U+U(V)):=U+V
IF U=V GOTO JOE
IF U>V THEN U:=Z Z:=U
END
Hình 2.3.Chương trình ví dụ
Trang 14Đầu tiên, chuyển chương trình này sang biểu đồ như hình 2.3 - biểu đồ trình tự cổ điển 1-1
Hình 2.4 Biểu đồ trình tự 1-1
Vì độ phức tạp tăng lên nên phải thêm các nhãn phụ: LOOP, XX, YY Gộp các bước xử lý lại và thay thế chúng bằng một hộp xử lý để thu được biểu đồ luồng điều khiển
Hình 2.5 Biểu đồ luồng điều khiển
Hình 2.5 biểu diễn biểu đồ luồng đơn giản hơn:
Hình 2.6 Ký hiệu biểu đồ luồng điều khiển đơn giản
Trang 15Có hai thành phần trong biểu đồ rút gọn là các hình tròn và mũi tên Một hình tròn với một hay nhiều mũi tên đi ra là một quyết định, với một hay nhiều mũi tên đi vào là một điểm nối Gọi các hình tròn là các nút còn các mũi tên là các liên kết Nút thường được đánh số hay gán nhãn bằng nhãn của chương trình Tên của các liên kết được tạo nên từ tên của các nút được nối bởi nó Chẳng hạn liên kết từ nút 7 đến nút 4 được gọi là liên kết (7,4), trong khi liên kết từ nút 4 đến nút 7 được gọi là liên kết (4,7) Đối với các liên kết song song giữa các cặp nút ta có thể biểu diễn như sau: (12,13, upper) hoặc (12,13 lower)
Biến đổi cuối cùng được biểu diễn như hình 2.6:
Hình 2.7 Ký hiệu biểu đồ luồng điều khiển đơn giản hơn
Những biểu diễn trên vẫn rất bất tiện, có thể sử dụng biểu diễn bằng danh sách liên kết như hình 2.7:
Hình 2.8 Ký hiệu biểu đồ luồng điều khiển bằng danh sách liên kết
Mỗi nút đều có tên và có một lối vào trong danh sách cho mỗi liên kết trong biểu đồ
2.1.2 Kiểm thử đường dẫn
2.1.2.1 Đường dẫn, nút và liên kết
Một đường dẫn trong chương trình là một chuỗi các câu lệnh hoặc các khai báo bắt đầu một đầu vào, một điểm nối hay một quyết định và kết thúc ở một
Trang 16điểm khác có thể là một điểm nối, một quyết định hay đầu ra Một đường dẫn có thể đi qua nhiều điểm nối, khối xử lý, quyết định một hay nhiều lần
Đường dẫn lại chứa nhiều đoạn, đoạn nhỏ nhất là một liên kết, nó là một tiến trình nằm giữa hai nút (như điểm nối-tiến trình-điểm nối, điểm nối-tiến trình-quyết định, quyết định-tiến trình-quyết định) Một đoạn đường dẫn là một chuỗi liên tục các liên kết của một đường dẫn nào đó
2.1.2.2 Tiêu chuẩn cho sự lựa chọn đường dẫn
Có rất nhiều đường giữa đầu vào và đầu ra của một thủ tục thông thường Mỗi quyết định làm gấp đối số đường, mỗi vòng lặp nhân số đường lên nhiều lần, thậm chí một thủ tục nhỏ cũng có thể có rất nhiều đường dẫn Phương pháp kiểm thử là kiểm tra tất cả các đường dẫn, nhưng đó vẫn chưa phải là phương pháp kiểm thử toàn diện bởi vì một lỗi có thể tạo nên các đường dẫn không mong muốn hay tạo nên các đường không thực hiện được Và khi tất cả các đường đều đúng cũng không có nghĩa thủ tục đáp ứng được yêu cầu xử lý Vậy như thế nào
là kiểm thử đầy đủ?
Sử dụng tất cả các đường từ đầu vào đến đầu ra
Sử dụng mỗi khai báo hay câu lệnh ít nhất một lần
Sử dụng tất cả các nhánh và lựa chọn theo mỗi hướng ít nhất một lần
2.1.2.3 Tiêu chuẩn cho kiểm thử đường dẫn
Bất kỳ một chiến lược kiểm thử đường dẫn nào cũng ít nhất phải thực hiện mọi câu lệnh và qua các nhánh theo tất cả các hướng Ba chiến lược (tiêu chuẩn) trong một lớp các chiến lược có khả năng:
1 Kiểm thử đường dẫn (P∞) - thực hiện tất cả các đường dẫn luồng điều khiển có thể trong chương trình (hoàn thành kiểm thử 100% đường dẫn) Đây là tiêu chuẩn mạnh nhất trong lớp các chiến lược kiểm thử đường dẫn, nhưng rất khó đạt được
2 Kiểm thử câu lệnh (P1) - Sau vài lần kiểm thử phải thực hiện tất cả các câu lệnh ít nhất một lần (hoàn thành kiểm thử 100% câu lệnh hay 100% nút) Ký hiệu tiêu chuẩn này là C1 Đây là tiểu chuẩn yếu nhất trong lớp các chiến lược kiểm thử
Trang 173 Kiểm thử nhánh (P2) - thực hiện một số lần kiểm thử để đảm bảo tất cả các nhánh khác đều được thực hiện ít nhất một lần (hoàn thành kiểm thử 100% nhánh hay 100% liên kết) Ký hiệu tiêu chuẩn này là C2
2.1.2.4 Ý nghĩa và các chiến lược chung
Phạm vi nhánh và câu lệnh ngày nay được xem như là yêu cầu kiểm thử tối thiểu Phạm vi câu lệnh được thiết lập như là yêu cầu kiểm thử tối thiểu trong chuẩn kiểm thử đơn vị của IEEE Phạm vi nhánh và câu lệnh cũng được sử dụng hơn hai thập niên như là những yêu cầu kiểm thử tối thiểu tại IBM và nhiều công
ty máy tính và phần mềm khác Kinh nghiệm chung cho thấy những điểm sau:
Không kiểm thử một đoạn mã sẽ để lại một phần lỗi trong chương trình tương đương với kích thước của đoạn mã không được kiểm thử
Các đường dẫn có khả năng cao thường được kiểm thử kỹ lưỡng trừ khi hệ thống làm việc đúng đắn Các đường dẫn có khả năng cao chưa kiểm thử được ở mức đơn vị sẽ còn được kiểm thử trong kiểm thử tích hợp hay kiểm thử hệ thống
Các lỗi logic và suy nghĩ mập mờ tỉ lệ nghịch với khả năng thực hiện đường dẫn
Người thiết kế thủ tục có thể thấy khả năng thực hiện của một đường dẫn theo chủ quan nhưng thực tế chỉ có người phân tích mới thấy
Ước lượng chủ quan tầm quan trọng của một đoạn mã của lập trình viên phụ thuộc vào kinh nghiệm, óc thẩm mỹ, sự hiểu biết của anh ta
2.1.2.5 Hiệu quả của kiểm thử đường dẫn
Khoảng 65% lỗi có thể được phát hiện trong kiểm thử đơn vị khi thực hiện theo các phương pháp kiểm thử đường dẫn Khi kết hợp với các phương pháp khác như giới hạn kiểm tra trong các vòng lặp thì tỉ lệ lỗi bắt được là từ 50% đến 60% Kiểm thử đường dẫn có hiệu quả đối với phần mềm không có cấu trúc hơn phần mềm có cấu trúc Các thống kê cũng cho thấy hạn chế khi dùng kiểm thử đường dẫn như là kỹ thuật duy nhất
Trang 182.2 Kiểm thử luồng giao dịch (Transaction-Flow Testing)
2.2.1 Giới thiệu
Biểu đồ luồng điều khiển thảo luận ở trên là mô hình thường được sử dụng nhất trong thiết kế kiểm thử Sử dụng khái niệm tương tự về các thành phần và phương pháp ở trên cho một loại biểu đồ luồng khác, biểu đồ luồng giao dịch, để tạo nên mô hình hoạt động của chương trình đưa đến kiểm thử chức năng Biểu
đồ luồng giao dịch là mô hình cấu trúc hoạt động của chương trình
2.2.2 Luồng giao dịch
2.2.2.1 Định nghĩa
Một phiên giao dịch theo quan điểm của người sử dụng là một đơn vị công việc, bao gồm một dãy các thao tác được tạo nên bởi hệ thống, con người, hay các thiết bị bên ngoài hệ thống Các phiên giao dịch được tạo ra như là kết quả của một số hoạt động bên ngoài, khi kết thúc nó không còn trong hệ thống ngoại trừ ở dạng lược sử bản ghi Một phiên giao dịch của hệ thống thông tin trực tuyến
có thể bao gồm các bước (nhiệm vụ) sau:
11 Truyền thông tin đầu ra
12 Ghi lại phiên giao dịch vào nhật ký và huỷ giao dịch
Người sử dụng chỉ nhìn thấy kịch bản này như một phiên giao dịch đơn Hầu hết các hệ thống trực tuyến xử lý rất nhiều loại giao dịch, ví dụ: một máy thu ngân tự động có thể được sử dụng để rút, gửi, thanh toán hoá đơn, hay
Trang 19chuyển tiền Hơn thế, các thao tác khác có thể được thực hiện như kiểm tra tài khoản, ghi tài khoản, bỏ tài khoản… Mặc dù các thao tác có thể khác nhau giữa các giao dịch, nhưng hầu hết các giao dịch đều có các thao tác chung, chẳng hạn máy thu ngân tự động bắt đầu các giao dịch bằng thao tác xác nhận thẻ của người
sử dụng và mã số của tài khoản
2.2.2.2 Sử dụng
Các luồng giao dịch không thể thiếu để xác định yêu cầu của các hệ thống phức tạp, đặc biệt là các hệ thống trực tuyến Một hệ thống lớn như điều khiển không lưu hay hệ thống đường bay có tới hàng nghìn luồng giao dịch, chúng được biểu diễn bởi các biểu đồ luồng khá đơn giản, rất nhiều trong số chúng có một đường dẫn đơn thẳng Các vòng lặp được sử dụng để yêu cầu làm lại sau khi người sử dụng nhập sai Chẳng hạn, hệ thống ATM cho phép người sử dụng làm lại ba lần và sẽ thu hồi thẻ ở lần thứ tư
Trang 202.2.3.Kỹ thuật kiểm thử luồng giao dịch
2.2.3.1 Để có được các luồng giao dịch
Các hệ thống phức tạp xử lý nhiều giao dịch phức tạp khác nhau cần có các luồng giao dịch được biểu diễn rõ ràng hay được viết thành tài liệu Có những cách biểu diễn khác như dùng các biểu đồ HIPO và các lưới Petri, các luồng giao dịch cũng có thể ánh xạ vào chương trình nên chúng cũng có thể được biểu diễn bằng PDL Nếu sử dụng các cách biểu diễn này và việc biểu diễn là đúng thì sẽ dễ dàng tạo nên các luồng giao dịch Mục đích là có được phác thảo những gì xảy ra với các giao dịch - phác thảo sự phát triển của các hành động
2.2.3.2 Cơ sở dữ liệu kiểm thử
Khoảng 30%-40% công sức thiết kế kiểm thử luồng giao dịch là việc thiết
kế và bảo trì cơ sở dữ liệu kiểm thử Có hai lỗi chính trong thiết kế cơ sở dữ liệu Đầu tiên, do không biết có một kiểm thử cơ sở dữ liệu sẽ được thiết kế nên các lập trình viên và kiểm thử viên tự thiết kế cơ sở dữ liệu của mình nhưng lại không thích hợp Kết quả là mỗi kiểm thử viên cần tới sự trợ giúp của toàn bộ hệ thống Thông thường thì những kiểm thử viên độc lập cần nhiều thiết kế kiểm thử
tỉ mỉ hơn các lập trình viên, vì vậy yêu cầu phải thành lập các nhóm kiểm thử Lúc này lỗi thứ hai xảy ra Để tránh lặp lại sự lộn xộn trên, sẽ có một cơ sở dữ liệu toàn diện thoả mãn tất cả yêu cầu kiểm thử Một hệ thống thông thường với khoảng nửa triệu dòng mã nguồn có thể cần tới bốn hoặc năm cơ sở dữ liệu không tương thích hỗ trợ cho kiểm thử Việc thiết kế các cơ sở dữ liệu này quan trọng không kém việc thiết kế các cấu trúc dữ liệu của hệ thống, yêu cầu những nhà thiết kế phải có kinh nghiệm, năng lực, khéo léo, tỉ mỉ - kinh nghiệm trong cả thiết kế hệ thống và thiết kế kiểm thử
2.2.3.3 Thực hiện
Cố gắng thực hiện từ đầu và đừng lo lắng nếu cần đến hàng trăm lần kiểm thử để đạt được phạm vi luồng giao dịch C1 + C2 Làm đi làm lại các giao dịch không chỉ một lần mà hàng trăm lần trong khi thực hiện dự án Kiểm thử luồng giao dịch với mục tiêu đạt được C1 + C2 thường mang lại một số lượng lớn các trường hợp kiểm thử
Trang 212.3 Kiểm thử luồng dữ liệu (Data-Flow Testing)
2.3.1 Định nghĩa
Data-Flow Testing là lớp các chiến lược kiểm thử dựa trên sự lựa chọn
các đường dẫn qua luồng điều khiển của chương trình để khảo sát dãy các sự kiện liên quan tới trạng thái của các đối tượng dữ liệu
2.3.2 Các mô hình mới – Các cỗ máy luồng dữ liệu
Các máy tính ngày nay hầu hết đều là các cỗ máy Von Neumann, kiến trúc đặc trưng cho khả năng hoán đổi việc lưu trữ các lệnh và dữ liệu trong cùng các đơn vị bộ nhớ Kiến trúc Von Neumann thông thường thực thi một lệnh tại một thời điểm theo dãy vi lệnh sau:
1 Lấy lệnh từ bộ nhớ
2 Thông dịch lệnh
3 Lấy các toán hạng
4 Xử lý
5 Lưu kết quả (có thể là trong các thanh ghi)
6 Tăng bộ đếm của chương trình (con trỏ nhảy tới lệnh tiếp theo)
7 GOTO 1
Cỗ máy Von Neumann thuần tuý chỉ có một tập vòng điều khiển để thông dịch lệnh, một tập các thanh ghi để xử lý dữ liệu, một đơn vị thực thi Thiết kế này hướng đến sự thực thi tuần tự từng lệnh một
Trái lại, các cỗ máy song song đồ sộ có nhiều cơ cấu để thực hiện các bước từ 1-7 ở trên và do đó có thể lấy một vài lệnh và/hoặc đối tượng một cách song song Nó cũng có thể thực hiện đồng thời các phép toán số học và lôgic trên các đối tượng dữ liệu khác nhau
2.3.3 Biểu đồ luồng dữ liệu
Biểu đồ luồng dữ liệu là biểu đồ chứa các nút và các liên kết có hướng Mặc dù đang thực hiện kiểm thử luồng dữ liệu nhưng không nhất thiết phải sử dụng chúng mà có thể sử dụng biểu đồ luồng điều khiển được chú thích để diễn
tả những gì đang xảy ra với các đối tượng dữ liệu
Trang 222.3.3.1 Trạng thái của đối tượng dữ liệu và sử dụng
Các đối tượng dữ liệu có thể được tạo ra, sử dụng, và huỷ bỏ, chúng có thể được sử dụng theo hai cách khác nhau: trong một phép tính hay như một phần của một quyết định Các ký tự sau chỉ ra các khả năng này:
d - được định nghĩa, được tạo, được thiết lập, v.v
k - bị huỷ, không xác định, được giải phóng
u - sử dụng cho cái gì đó
c - sử dụng trong một phép tính
p - sử dụng trong một quyết định
2.3.3.2 Các luồng dữ liệu bất thường
Một sự bất thường được chỉ ra bởi hai chữ cái thể hiện thứ tự các hành động Có 9 kết hợp có thể của 3 chữ cái k, d, u:
dd – có thể không có hại nhưng mập mờ - định nghĩa đối tượng hai lần mà không xen vào sử dụng
dk – có thể là lỗi Tại sao định nghĩa một đối tượng mà không sử dụng nó
du - trường hợp bình thường Đối tượng được tạo ra và được sử dụng
kd – tình huống thông thường Đối tượng bị huỷ rồi được định nghĩa lại
kk – không có hại nhưng có thể có lỗi Có chắc đối tượng đã bị huỷ
ku – lỗi Đối tượng không tồn tại - giá trị không xác định hay vô hạn
ud – thông thường không phải là một lỗi
uk – tình huống thông thường
uu – tình huống thông thường
Ngoài các trường hợp trên còn có 6 trường hợp ký tự đơn lẻ:
-k: huỷ một biến không tồn tại
-d: đây chỉ là định nghĩa đầu tiên trong đường dẫn
-u: có thể bất thường
k-: không bất thường Việc làm cuối cùng của đường dẫn là để huỷ biến d-: có thể bất thường Biến được định nghĩa nhưng không được sử dụng; nhưng đây có thể là một định nghĩa toàn cục hay bên trong một thủ tục có định nghĩa các biến cho các thủ tục khác
Trang 23u-: không bất thường Biến được sử dụng nhưng chưa bị huỷ
Dấu gạch ngang ở trước để chỉ ra không có gì đáng chú ý xảy ra trước hành động dọc theo đầu vào – ra của đường dẫn quan tâm, dấu gạch ngang theo sau để chỉ không có gì xảy ra từ điểm quan sát tới đầu ra
2.3.3.3 Biểu đồ trạng thái luồng dữ liệu bất thường
Mô hình luồng dữ liệu bất thường quy định mỗi đối tượng có thể ở 1 trong
4 trạng thái sau:
K – không xác định, bị huỷ trước đó, không tồn tại
D - được định nghĩa nhưng không được sử dụng cho bất cứ cái gì
U – đã được sử dụng trong phép tính hay trong quyết định
A - bất thường
Hình 2.9 là các ví dụ về biểu đồ trạng thái luồng dữ liệu bất thường:
Hình 2.10 Biểu đồ luồng dữ liệu bất thường 2.3.4 Mô hình luồng dữ liệu
2.3.4.1 Các thành phần của mô hình
Quy tắc tạo nên mô hình:
1 Mỗi khai báo có một nút với tên duy nhất Mỗi nút có ít nhất một liên kết ngoài và một liến kết trong ngoại trừ các nút ra không có liên kết ngoài và các nút vào không có các liên kết trong
Trang 242 Các nút ra là các nút tượng trưng đặt tại đầu các mũi tên đi ra của các khai báo kết thúc (END, RETURN) để hoàn tất biểu đồ Tương tự, các nút vào được đặt tại các khai báo bắt đầu (BEGIN)
3 Liên kết ngoài của các khai báo đơn được đánh trọng số bởi một dãy thích hợp các hành động của luồng dữ liệu cho khai báo đó Ví dụ, với lệnh gán A:= A + B trong hầu hết các ngôn ngữ được đánh trọng số cd hay ckd cho biến
A Dãy chữ cái phải có thứ tự thích hợp để mã sẽ được thực hiện cho biến đó
4 Các nút quyết định (ví dụ: IF – THEN – ELSE, DO WHILE, CASE) được đánh chữ cái p trên mọi liên kết ngoài thích hợp với liên kết ngoài đó
5 Mọi dãy các khai báo đơn (ví dụ một dãy các nút với một liên kết trong và một liên kết ngoài) có thể được thay thế bởi một cặp nút có các trọng số liên kết kết hợp
6 Nếu có một vài luồng dữ liệu hoạt động trên một liên kết với một biến chỉ ra thì trọng số của liên kết được ký hiệu bởi một chuỗi các hành động trên liên kết đó
7 Ngược lại, một liên kết với một vài luồng dữ liệu hoạt động trên nó có thể được thay thế bởi một dãy các liên kết tương đương, mỗi liên kết có nhiều nhất một luồng dữ liệu hoạt động cho một biến bất kỳ
2.3.4.2 Ví dụ: Xét hình 2.10
Hình a là biểu đồ luồng điều khiển đã biết
Hình b biểu diễn cho luồng điều khiển này để chú giải các luồng dữ liệu của các biến X và Y
Hình c biểu diễn biểu đồ luồng điều khiển tương tự để chú giải cho biến Z
Z được định nghĩa lần đầu tiên bằng lệnh gán ở liên kết đầu tiên Z được sử dụng trong một quyết định (Z>=0) tại nút 3, vì thế cả hai liên kết ngoài đều được đánh
là p Có thêm hai thể hiện nữa của quyết định sử dụng ở nút 8 và 9
Luồng dữ liệu chú giải cho biến V được biểu diễn bởi hình d Phép gán V(U),U(V):=(Z+V)*U được viết gộp Nó được mô hình hoá thành hai khai báo riêng biệt và kết quả có tổng cộng 3 chữ c cho biến này tại liên kết (6,7)
Trang 25Hình 2.11 Các biểu đồ luồng điều khiển 2.3.5 Các chiến lược kiểm thử luồng dữ liệu
2.3.5.1 Các thuật ngữ
Một đoạn đường dẫn định nghĩa rõ ràng (đối với biến X) là một dãy liên kết được nối với nhau mà X được định nghĩa trên liên kết đầu tiên, không được định nghĩa lại hay huỷ bỏ ở bất kỳ một dãy liên kết con nào của đoạn đường dẫn đó
Một đoạn đường dẫn vòng lặp tự do là một đoạn đường dẫn có mỗi nút được đi qua không quá một lần
Một đoạn đường dẫn đơn giản là một đoạn đường dẫn có nhiều nhất một nút được đi qua hai lần
Một đường dẫn du từ nút i đến nút k là một đoạn đường dẫn nếu liên kết cuối cùng có một phép tính sử dụng biến X thì đường dẫn là đơn giản và định nghĩa rõ ràng, nếu nút áp chót là j thì đường dẫn là (i, p,
q, … , r, s, t, j, k) và liên kết (j, k) có một quyết định, đường dẫn từ i tới j vừa là vòng lặp tự do vừa là định nghĩa rõ ràng
Trang 262.3.5.2 Các chiến lược
1 Các đường dẫn All-du
Chiến lược các đường dẫn All-du (ADUP) là chiến lược kiểm thử luồng dữ liệu mạnh nhất, yêu cầu mỗi đường dẫn du từ mỗi định nghĩa của mỗi biến đến mỗi sử dụng của định nghĩa được sử dụng dưới một số phép kiểm thử
2 Chiến lược All-uses
Có ít nhất một đường dẫn định nghĩa rõ ràng từ mỗi định nghĩa của mỗi biến đến mỗi sử dụng của định nghĩa và chúng đều được sử dụng sau một vài phép kiểm thử
3 Các chiến lược All-p-uses/Some-c-uses và All-c-uses/Some-p-uses All-p-uses/Some-c-uses cho mỗi biến và mỗi định nghĩa của biến đó chứa
ít nhất một đường dẫn tự do từ định nghĩa tới mỗi quyết định được sử dụng, nếu
có các định nghĩa của biến không được khống chế bởi điều kiện trên thì thêm các trường hợp kiểm thử phép tính – sử dụng, để khống chế mỗi định nghĩa Ngược lại chiến lược All-c-uses/Some-p-uses đầu tiên bảo đảm đã được khống chế bởi các trường hợp sử dụng phép tính và nếu bất kỳ một định nghĩa nào không được khống chế bởi các đường dẫn được chọn trước đó thì thêm các trường hợp sử dụng quyết định cần thiết để chắc chắn chúng được tính đến trong vài lần kiểm thử
4 Chiến lược All-Definitions
All-Definitions (AD) chỉ yêu cầu mỗi định nghĩa của mỗi biến được khống chế bởi ít nhất một sử dụng của biến đó
5 Các chiến All-Predicate-Uses, All-Computation-Uses
All-Predicate-Uses (APU) xuất phát từ chiến lược APU + C bằng cách thêm yêu cầu bao gồm sử dụng của c cho biến khi không có các sử dụng của p cho biến sau mỗi định nghĩa Tương tự với chiến lược All-Computation-Uses Rõ ràng ACU là yếu hơn ACU + P và APU yếu hơn APU + C
6 Trình tự các chiến lược
Hình 2.11 so sánh các chiến lược kiểm thử luồng dữ liệu và luồng đường dẫn:
Trang 27Hình 2.12 Quan hệ của các chiến lược kiểm thử có cấu trúc
Các mũi tên có nghĩa chiến lược ở cuối mũi tên mạnh hơn chiến lược ở đầu mũi tên, đường từ “All paths” đến “All statements” được chú ý hơn đối với các ứng dụng thực tế
2.4 Kiểm thử miền (Domain Testing)
2.4.1 Mô hình
Kiểm thử miền có thể dựa trên các đặc tả và/hoặc thông tin thi hành tương đương, nếu dựa trên các đặc tả thì nó là kỹ thuật kiểm thử chức năng, nếu dựa trên sự thực thi thì nó là kỹ thuật có cấu trúc Thực tế nó thường được áp dụng cho một biến đầu vào hoặc sự kết hợp đơn giản của hai biến dựa trên các đặc tả Mọi đầu vào của mô hình có thể được xem như là các số Ví dụ, một ký tự
có thể được xem như là một một số bằng cách ghép các bit lại và xem chúng như
Trang 28Kiểm thử miền tập trung vào phân loại các khía cạnh của thủ tục hơn là vào các phép tính Miền đầu vào là một tập hợp Nếu ngôn ngữ nguồn hỗ trợ các định nghĩa tập hợp (các kiểu tập hợp trong Pascal, các kiểu liệt kê trong C) thì cần ít kiểm thử vì các trình biên dịch đã làm hầu hết Kiểm thử miền không hiệu quả với tập các đối tượng dữ liệu rời rạc do không có chiến lược chung, đơn giản Trong kiểm thử miền, các công thức được dịch thành các số hạng của các biến vectơ đầu vào Nếu áp dụng với cấu trúc thì việc biên dịch các công thức phải dựa trên các đường dẫn có thực qua thủ tục, dựa vào biểu đồ luồng điều khiển Ngược lại, nếu áp dụng với các đặc tả thì việc biên dịch dựa trên biểu đồ luồng dữ liệu được xác định cho thủ tục, thông thường việc thông dịch không cần thiết vì các miền được xác định trực tiếp
Miền được định nghĩa bởi các đường biên Các đường biên cũng là nơi hầu hết các lỗi xảy ra Với mỗi đường biên có ít nhất một công thức chỉ ra những
số nào thuộc miền và những số nào không thuộc Ví dụ, câu lệnh IF x > 0 then ALPHA ELSE BETA, các số lớn hơn 0 thuộc về miền ALPHA trong khi 0 và các số nhỏ hơn thuộc về miền BETA Một miền có thể có một hay nhiều đường biên – không quan trọng là có bao nhiêu biến định nghĩa nó Chẳng hạn, nếu công thức là x2 + y2 < 16 thì miền nằm trong vòng tròn bán kính 4 Các miền thường được định nghĩa bởi nhiều đoạn đường biên và vì thế bởi nhiều công thức
Hình 2.13 mô tả 3 trường hợp của một miền một chiều
Hình 2.14 Miền một chiều
Theo lý thuyết, đường biên của một miền bị đóng nếu các điểm trên đường biên thuộc miền Nếu các điểm trên đường biên thuộc một vài miền khác thì đường biên được gọi là mở Hình 2.13 biểu diễn 3 miền D1, D2 và D3 Ở hình a, các đường biên của D2 bị đóng tại cả các giá trị lớn nhất và nhỏ nhất Nếu
Trang 29D2 đóng đối với biến x thì các miền liền kề (D1 và D3) phải đều mở đối với biến
x Với hình b, D2 đóng ở phía giá trị nhỏ nhất và mở ở giá trị lớn nhất, tức D1
mở tại giá trị nhỏ nhất của D2 và D3 đóng tại giá trị lớn nhất của D2 Hình c mô
tả D2 mở ở cả hai phía, tức là các đường biên đều bị đóng với D1 và D3
2.4.2 Kích thước miền
Mỗi biến đầu vào thêm vào miền một chiều Một biến định nghĩa các miền trên một trục số, hai biến định nghĩa các miền hai chiều, ba biến định nghĩa các miền đặc và cứ tiếp tục như vậy
Tất cả các đường biên suốt không gian vectơ đầu vào một chiều thì nhỏ hơn kích thước của không gian Vì một miền có thể chỉ chứa các điểm trên một đường thẳng nên kích cỡ của công thức có thể nhận bất kỳ giá trị nào nhỏ hơn kích cỡ của không gian Không gian của miền có nhiều hơn 3 chiều được gọi là n chiều, những gì cắt ngang qua mặt không gian n chiều được gọi là siêu mặt phẳng Ví dụ: một mảng đầu vào với kích thước 100 là hiếm nhưng nó là không gian 100 chiều Không gian đầu vào nhiều chiều là phổ biến với các thủ tục bình thường Kiểm thử miền có thể được làm bằng tay với một, hai chiều nhưng nói chung nó là công cụ mạnh
2.4.3 Các miền tốt, miền xấu
2.4.3.1 Các miền tốt
Hình 2.14 biểu diễn một số miền tốt hai chiều
Hình 2.15 Một số miền tốt hai chiều
Các đường biên có một số thuộc tính quan trọng như: tuyến tính, đầy đủ,
có hệ thống, trực giao, đóng, liên thông tuyệt đối và lồi Với phạm vi các miền có các thuộc tính này, kiểm thử miền rất dễ dàng, ngược lại thì kiểm thử miền rất khó khăn Điều quan trọng là tỉ xuất lỗi với các miền tốt thấp hơn các miền xấu Các đường biên miền tốt được định nghĩa bởi các bất đẳng thức hay các phương trình tuyến tính Các đường biên miền tốt là đầy đủ khi chúng kéo dài
Trang 30khoảng số từ dương vô cùng đến âm vô cùng ở tất cả các chiều Hình 2.15 biểu diễn một vài đường biên không đầy đủ Đường A và E có các đoạn nét đứt
Hình 2.16 Một vài đường biên khôngđầy đủ
Ưu điểm của các đường biên đầy đủ là cần đến một tập các phép kiểm thử
để xác định đường biên mà không quan tâm nó giới hạn bao nhiêu miền Nếu một đường biên bị chia nhỏ ra và có các lỗ hổng thì mỗi đoạn của đường biên đó phải được kiểm thử với mỗi miền nó giới hạn
Các đường biên có hệ thống tức là các đường bất đẳng thức liên hệ với một hàm bậc một Chẳng hạn như các quan hệ:
f1(X) >= k 1 hay f1(X) >= g(1,c)
f2(X) >= k 2 hay f2(X) >= g(2,c)
………… …………
fi(X) >= k i hay fi(X) >= g(i,c)
fi là một hàm tuyến tính bất kỳ, X là vectơ đầu vào, ki và c là các hằng số, g(i,c)
là hàm trên i và c sinh ra một hằng số, chẳng hạn k + ic
Các tập hợp đường biên U và V ở hình 2.14 là các đường trực giao Nếu hai tập đường biên trực giao thì chúng có thể kiểm thử độc lập Có 6 đường trong
U và 4 đường trong V, có thể xác định các thuộc tính đường biên bằng một số các phép thử tương ứng là 6 + 4 = 10 (O(n)) Nếu nghiêng các đường biên đi như hình 2.16 thì phải kiểm thử các giao điểm, bây giờ số phép thử là O(n2)
Hình 2.17 Các đường biên nghiêng
Trang 31Trên thực tế có hai điều kiện khác nhau liên quan đến tính trực giao Một tập các đường biên có thể trực giao với một tập khác nhưng không trực giao với các trục toạ độ hoặc ngược lại Điều kiện thứ nhất cho phép chúng ta đơn giản việc kiểm thử giao điểm Trường hợp thứ hai, các đường biên là các hàm của chỉ một biến Cả hai đều là các thuộc tính mong muốn Hình 2.17 biểu diễn sự khác nhau này:
Hình 2.18 Các đường biên tuyến tính không trực giao
2.4.3.2 Các miền xấu
Một số miền được tạo ra đã xấu, một số miền bị làm xấu đi bởi những đặc
tả tồi Các lập trình viên phải tìm cách để làm giảm độ phức tạp còn các kiểm thử viên không thấy được những phức tạp nên thường bỏ qua các trường hợp quan trọng
2.4.4 Dự đoán lỗi
Một miền thực hiện không đúng nghĩa là các đường biên sai, cũng có nghĩa các công thức luồng điều khiển sai Một đường biên lỗi có thể do một thủ tục con mức thấp, một lời gọi sai đến một thủ tục con đúng, hay lỗi bảng đầu vào Kiểm thử miền có thể được bổ sung bởi các phép kiểm thử khác để xác định quá trình xử lý là chính xác Nhiều lỗi khác nhau có thể là kết quả của các lỗi miền
2.4.5 Chiến lược kiểm thử miền
Chiến lược kiểm thử miền rất đơn giản mặc dù nó có thể rất buồn tẻ:
Các miền được định nghĩa bởi các đường biên của nó nên kiểm thử miền tập trung vào các điểm nằm trên hay gần các đường biên
Phân loại những gì sai có thể xảy đến với các đường biên rồi định nghĩa chiến lược kiểm thử cho mỗi trường hợp Lấy ra một số điểm đủ
để kiểm thử tất cả các loại lỗi đường biên
Trang 32 Vì mỗi đường biên thuộc về hai miền khác nhau nên các điểm được sử dụng để kiểm thử một miền cũng có thể sử dụng để kiểm thử các miền bên cạnh
Làm các kiểm thử và bằng phân tích cuối cùng xác định các đường biên nào là lỗi
Làm một số kiểm thử cần thiết để kiểm tra lại mỗi đường biên của mỗi miền
2.5 Kiểm thử cú pháp (Syntax Testing)
2.5.1 Tổng quan
Kiểm thử cú pháp bao gồm các bước sau:
1 Nhận dạng ngôn ngữ đích (ẩn hay hiện)
2 Xác định cú pháp của ngôn ngữ bởi một chú thích thuận tiện, chẳng hạn ở dạng BarKus-Naur (BNF)
3 Kiểm thử và gỡ lỗi cú pháp để chắc chắn nó đầy đủ, phù hợp và thoả mãn ngữ nghĩa mong đợi
4 Điều kiện kiểm thử thông thường gồm một tập các chuỗi đầu vào chứa các giá trị giới hạn vòng lặp Vấn đề là dự đoán kết quả và xác minh xem quá trình xử lý có đúng hay không
5 Kiểm thử cú pháp giải quyết tốt việc kiểm thử nặng nhọc
6 Phần lớn thiết kế kiểm thử cú pháp có thể và nên được làm tự động
7 Thực hiện kiểm thử một cách tự động là cần thiết cho kiểm thử cú pháp bởi vì phương pháp này sinh ra rất nhiều phép kiểm thử
2.5.2 Cú pháp cho các định dạng - Ký hiệu BNF
2.5.2.1 Các phần tử
Mỗi đầu vào có thể được xem như là một chuỗi các ký tự Việc định nghĩa
cú pháp phải mang tính hình thức, bắt đầu với các phần tử cơ bản nhất Dưới đây
là một định nghĩa mẫu:
Alpha_characters ::= A/B/C/D/E/F/G/H/I/J/K/L/M/N/O/P/Q
/R/S/T/U/V/W/X/Y/Z
Numarals ::= 1/2/3/4/5/6/7/8/9
Trang 332.5.2.2 Các toán tử BNF
Cú pháp định nghĩa trong BNF là một tập các định nghĩa Mỗi định nghĩa
có thể dẫn tới các định nghĩa khác hay tới chính nó để cuối cùng lấy được các ký
tự tạo nên chuỗi đầu vào Ví dụ:
word ::= alpha_character alpha_character / numeral sp numeral
Chuỗi đầu vào có tên là word với một cặp các alpha_character hay một cặp các numeral cách nhau bởi một sp Ví dụ về các word/không phải là word:
word: AB, DE, XY, 3 sp 4, 6 sp 7, 9 sp 9, 1 sp 2
nonwords : AAA, A sp A1, A), 11, 111, WORD, NOT sp WORD, +
2.5.2.3 Sự lặp lại
Object1-3 nghĩa là có 1 đến 3 đối tượng, object* nghĩa là không có hay sự lặp đi lặp lại không giới hạn của đối tượng, object+ tức là một hay nhiều lần lặp lại của đối tượng Ký hiệu * hay + có thể xuất hiện trong bất kỳ cú pháp nào bởi
vì cả hai ký hiệu đều có nghĩa là một số lần lặp có thể của đối tượng
ordinary_digit ::= special_digit / zero / other_digit
exchange_part ::= other_digit2 ordinary_digit
Trang 34ra cho các lỗi riêng rẽ, làm tương tự với cặp 2 lỗi rồi cặp 3 lỗi Tuy nhiên nếu có
N lỗi đơn thì sẽ có N2 cặp 2 lỗi và N3 cặp 3 lỗi
2.5.3.2 Các lỗi cú pháp mức đỉnh, mức trung gian, mức trường
Mức cú pháp cao nhất được định nghĩa:
item ::= atype / btype / ctype / dtype etype
Sau đây là một số trường hợp kiểm thử:
Làm cho nó sai: Sử dụng một phần tử đúng ở một số mức cú pháp thấp hơn khác nhưng không phải ở mức này
Trang 35 Sử dụng một kết hợp sai: phần tử cuối cùng là kết hợp của hai phần từ khác theo thứ tự đã chỉ ra Đảo lộn thứ tự của các phần tử và kết hợp chúng lại
dtype atype / btype etype / etype dtype / etype etype / dtype dtype
Atype btype ctype dtype etype / atype atype atype
dtype atype etype / dtype etype etype / dtype etype128
Trang 36iii vân vân
Mức thứ 3
- ordinary_digit tồi
i không phải là một số - sử dụng một chữ cái
ii không phải là số - sử dụng một ký tự điều khiển
iii không phải là số - sử dụng một dấu phân cách
iv không phải là số - bỏ nó ra ngoài
v vân vân
Mức thứ tư
- other_digit tồi – như với ordinary_digit tồi
- special_digit tồi – như với ordinary_digit tồi
- vân vân
2.5.3.3 Lỗi dấu phân cách
Các dấu phân cách là các ký tự hay chuỗi nằm giữa các trường để chỉ một trường kết thúc và bắt đầu một trường khác Các vấn đề về dấu phân cách là nguồn dồi dào cho các trường hợp kiểm thử do đó nên tập trung nhận dạng các dấu phân cách và các quy tắc bao trùm cú pháp của chúng:
Thiếu dấu phân cách: Các trường sát nhau trộn lẫn vào nhau
Dấu phân cách sai: Khi có một số loại dấu phân cách khác nhau được
sử dụng và có các quy tắc để chỉ ra dấu phân cách nào được sử dụng tại vị trí nào
Không phải là dấu phân cách: Có một số ký tự hay chuỗi không phải là các dấu phân cách nhưng có thể bị đặt vào vị trí dấu phân cách
Quá nhiều dấu phân cách: Số lượng các dấu phân cách tại ranh giới các trường có thể thay đổi
Cặp đôi dấu phân cách: Các dấu phân cách này thể hiện một tập các trường hợp kiểm thử thú vị khác Có thể có vài loại cặp đôi dấu phân cách trong một cú pháp Ví dụ như “BEGIN … BEGIN … END”,
“BEGIN … END … END”
Trang 37 Các dấu phân cách có thể tha thứ: Dấu phân cách có thể là tuỳ ý hoặc một vài định dạng luân phiên có thể được chấp nhận Trong các hệ thống truyền thông, bắt đầu một tin nhắn được định nghĩa là ZCZC, nhưng rất nhiều hệ thống cho phép bất kỳ một trong 4 ký tự bị sai khác Vì thế #CZC, Z#ZC, ZC#C, ZCZ# đều có thể được chấp nhận
Có rất nhiều cách để thêm vào một ký tự lỗi như:
i một chố trống
ii Z hay C ở sai vị trí – CCZC, ZZZC, ZCCC, ZCZZ
2.5.3.4 Lỗi cú pháp phụ thuộc bối cảnh
Các thành phần của cú pháp có thể có quan hệ với nhau và có thể liên quan đến các giá trị trường của các trường khác, trường đầu tiên có thể là một luật để chỉ rõ cú pháp của các trường con Ví dụ:
command ::= pilot-field syntax_option
pilot_field ::= 1/2/3/4/5/6/7/8/9
syntax_option ::= option1 / option2 / option3 / …
2.5.3.5 Lỗi phụ thuộc trạng thái
Chuỗi hay giá trị trường có thể được chấp nhận tại một thời điểm nhưng không được chấp nhận tại thời điểm tiếp theo vì hiệu lực phụ thuộc vào trạng thái giao dịch hay trạng thái của hệ thống
2.6 Kiểm thử hộp đen (Black-box Testing)
Kỹ thuật kiểm thử hộp đen xem chương trình như là một hộp đen
Hình 2.20 Kiểm thử hộp đen
Các phương pháp kiểm thử hộp đen tập trung vào các yêu cầu chức năng của phần mềm, tức là kiểm thử hộp đen làm cho kỹ sư phần mềm suy ra được tập các điều kiện vào sẽ thao diễn qua tất cả các yêu cầu chức năng đối với một chương trình
Trang 38Kiểm thử hộp đen dự định tìm lỗi trong các phạm vi sau:
Các chức năng không đúng hay bị bỏ sót
Lỗi giao diện
Lỗi trong cấu trúc dữ liệu hay thâm nhập cơ sở dữ liệu ngoài
Lỗi hiệu năng
Lỗi khởi đầu và kết thúc
Kiểm thử hộp đen không xét tới các cấu trúc điều khiển nên sự chú ý dồn vào miền thông tin Các phép kiểm thử được thiết kế để trả lời những câu hỏi:
Tính hợp lệ của chức năng được kiểm thử như thế nào?
Lớp đầu vào nào sẽ tạo ra những trường hợp kiểm thử tốt?
Hệ thống có nhạy cảm với những giá trị vào nào đó không?
Đường biên của lớp dữ liệu được cô lập như thế nào?
Hệ thống có thể dung sai cho tỷ lệ dữ liệu và khối lượng dữ liệu nào?
Việc tổ hợp dữ liệu đặc biệt có tác động gì lên sự vận hành của hệ thống?
Áp dụng các kỹ thuật hộp đen có thể suy ra tập các trường hợp kiểm thử thoả mãn cho tiêu chuẩn sau:
Các trường hợp kiểm thử làm rút gọn số các trường hợp kiểm thử phụ phải thiết kế để đạt tới việc kiểm thử hợp lý
Các trường hợp kiểm thử cho ta biết sự hiện diện hay vắng mặt của các lớp lỗi hơn là một lỗi liên kết chỉ với một tập xác định hiện có
Kiểm thử hộp đen coi xử lý kết quả như là minh chứng bởi dữ liệu và không quan tâm tới vấn đề logic Khuynh hướng này hiệu quả đối với các module chức năng đơn và các hệ thống cấp cao Ba phương pháp chính là:
Phân hoạch cân bằng
Phân tích cực biên
Đoán lỗi
Trang 392.6.1 Phân hoạch cân bằng
Mục đích của phân hoạch cân bằng là tối thiểu các trường hợp kiểm thử với mỗi mức kiểm tra cho trước, các mục dữ liệu vào được chia thành các nhóm
dữ liệu có vai trò cân bằng nhau, mỗi nhóm đại diện cho một tập dữ liệu Nguyên tắc là bằng cách kiểm thử triệt để một mục của mỗi tập hợp, chúng ta có thể chấp nhận tất cả các mục tương đương khác của tập hợp đó cũng sẽ được kiểm tra một cách kỹ càng do đó làm giảm tổng số các trường hợp kiểm thử phải xây dựng Thiết kế trường hợp kiểm thử cho phân hoạch cân bằng dựa trên một đánh giá về các lớp tương đương với một điều kiện vào Lớp tương đương biểu thị cho một tập các trạng thái hợp lệ hay không hợp lệ đối với điều kiện vào Các lớp tương đương có thể được định nghĩa theo những hướng dẫn sau:
Nếu một điều kiện vào xác định một miền thì một lớp hợp lệ và hai lớp
không hợp lệ được xác định
Nếu một điều kiện vào đòi hỏi một giá trị xác định thì một lớp hợp lệ
và hai lớp không hợp lệ được xác định
Một điều kiện vào xác định một thành viên của một tập thì một lớp hợp lệ và một lớp không hợp lệ được xác định
Nếu một điều kiện vào là bool thì một lớp hợp lệ và một lớp không hợp lệ được xác định
Bởi nhiều lý do, một số lớn các lỗi có khuynh hướng xuất hiện tại biên của
miền hơn là tại trung tâm Chính vì lý do này mà phân tích cực biên (BVA) đã
được phát triển như một kỹ thuật kiểm thử Phân tích giá trị biên dẫn tới việc chọn lựa các trường hợp kiểm thử thực hiện các giá trị cận
Trang 40Phân tích cực biên là kỹ thuật thiết kế trường hợp kiểm thử bổ sung thêm cho phân hoạch cân bằng Thay vì chọn bất kỳ phần tử nào của một lớp tương đương, BVA chọn các trường hợp kiểm thử tại “cạnh” của lớp Thay vì chỉ tập trung vào các điều kiện vào, BVA suy dẫn ra các trường hợp kiểm thử từ miền đầu ra
Hướng dẫn cho BVA tương tự hướng dẫn cho phân hoạch cân bằng:
Nếu một điều kiện vào xác định một miền được giới hạn bởi các giá trị
a và b thì các trường hợp kiểm thử nên được thiết kế với các giá trị a
và b ngay ở trên và ở dưới a và b tương ứng
Nếu một điều kiện vào xác định một số các giá trị thì các trường hợp kiểm thử nên được xây dựng cho các giá trị cực tiểu và cực đại Các giá trị ngay trên và dưới giá trị cực tiểu và cực đại cũng được kiểm thử
Áp dụng các hướng dẫn 1 và 2 cho các điều kiện ra
Nếu các cấu trúc dữ liệu bên trong chương trình đã mô tả trước các biên (như một mảng có 100 phần tử) thì phải chắc chắn thiết kế một trường hợp kiểm thử để thực hiện cấu trúc dữ liệu đó tại biên của nó
2.6.3 Đoán lỗi
Trên cơ sở trực giác và kinh nghiệm, các chuyên gia có thể dễ dàng kiểm tra các điều kiện lỗi bằng cách đoán cái nào dễ xảy ra nhất Ví dụ, chia cho 0 nếu module có phép chia Vì dựa trên trực giác nên phép thử này khó tìm hết các lỗi
2.6.4 Kỹ thuật biểu đồ nguyên nhân - kết quả
Một nhược điểm của phân hoạch cân bằng và phân tích cực biên là tổ hợp của các miền tổ hợp không được xác định Biểu đồ nguyên nhân-kết quả (Cause-Effect Graphing) bù đắp cho thiếu sót này Nó chỉ ra các đầu ra và thông tin di chuyển như là hệ quả và các đầu vào gây ra hệ quả trên Các ký hiệu đồ hoạ xác định tương tác, lựa chọn, logic và các điều kiện tương đương Mỗi vòng đại diện một dãy các thao tác không có điểm quyết định hoặc điều khiển