D) CÁC CÁCH BIỂU DIỄN CỦA MÔ HÌNH PHÂN TÍCH
f. Đặc tả giao diện đối tượng
7.4. THIẾT KẾ TRƯỜNG HỢP KIỂM THỬ (TEST CASE DESIGN)
Mục tiêu của tiến trình thiết kế các trường hợp kiểm thử là tạo ra một tập các trường hợp kiểm thử hiệu quả trong việc phát hiện ra những lỗi của chương trình và chỉ ra rằng hệ thống đáp ứng được yêu cầu.
Để thiết kế một trường hợp kiểm thử, ta cần lựa chọn một tính năng của hệ thống hoặc một thành phần đang kiểm thử, sau đó chọn một tập dữ liệu đầu vào để thực thi tính năng này.
Dưới đây là một số cách tiếp cận khác nhau được dùng để thiết kế các trường hợp kiểm thử:
1. Kiểm thử dựa trên yêu cầu: các trường hợp kiểm thử được thiết kế để kiểm tra các yêu
cầu của hệ thống. Kỹ thuật này thường được sử dụng trong các giai đoạn kiểm thử hệ thống. Với mỗi yêu cầu cần xác định các trường hợp kiểm thử để có thể chứng minh rằng các yêu cầu của hệ thống được đáp ứng.
2. Kiểm thử phân vùng (partition): xác định các phân vùng dữ liệu đầu vào (input) và phân
vùng kết quả đầu ra (output), thiết kế các trường hợp kiểm thử sao cho hệ thống thực thi từ tất cả các phân vùng và sinh ra tất cả các phân vùng của kết quả đầu ra. Các phân vùng là những nhóm dữ liệu có các thuộc tính chung, chẳng hạn như tất cả các số âm, tất cả những tên có độ dài <30 kí tự, tất cả các sự kiện sinh ra khi chọn một mục trên menu…
3. Kiểm thử cấu trúc: sử dụng kiến thức về cấu trúc chương trình để thiết kế các trường hợp kiểm thử thực thi tất cả các phần của chương trình. Về cơ bản, khi kiểm thử một chương trình ta nên cố gắng thực thi mỗi câu lệnh ít nhất một lần. Kiểm thử cấu trúc giúp xác định các trường hợp kiểm thử có thể.
Kiểm thử dựa trên yêu cầu là một cách tiếp cận ngữ nghĩa (semantic) để thiết kế các trường hợp kiểm thử thông qua việc xem xét mỗi yêu cầu và sinh ra một tập các trường hợp kiểm thử cho các yêu cầu này. Kiểm thử dựa trên yêu cầu được xem là kiểm thử thẩm định hơn là kiểm thử khiếm khuyết – nghĩa là ta đang cố gắng chứng minh rằng hệ thống hoạt động đúng như đặc tả.
Ví dụ, hãy xem xét những yêu cầu cho hệ thống quản lý thư viện LIBSYS:
1. Người sử dụng có thể tìm kiếmtừ tập hợp cơ sở dữ liệu ban đầu hoặc từ một tập con của tập cơ sở dữ liệu ban đầu đó.
2. Hệ thống phải cung cấp công cụ hiển thị hợp lý để người sử dụng xem được tài liệu trong kho tài liệu.
3. Mỗi phiếu đặt sách phải được cấp một số hiệu duy nhất để người sử dụng có thể sao lưu qua tài khoản trong vùng lưu trữ thường trực cá nhân.
Giả sử ta đang xây dựng các kịch bản kiểm thử cho chức năng tìm kiếm, khi đó những trường hợp kiểm thử có thể sinh ra từ những yêu cầu trong chức năng tìm kiếm là:
- Tìm kiếm trong một cơ sở dữ liệu với hai trường hợp: tài liệu có và không có trong cơ sở dữ liệu.
- Tìm kiếm trong hai cơ sở dữ liệu với hai trường hợp: Tài liệu có và không có trong cơ sở dữ liệu.
- Tìm kiếm trong nhiều hơn hai cơ sở dữ liệu với hai trường hợp: Tài liệu có và không có trong cơ sở dữ liệu.
- Chọn một trong những cơ sở dữ liệu từ các thiết lập của người sử dụng và bắt đầu tìm kiếm các tài liệu mà được biết là có mặt và không có mặt trong cơ sở dữ liệu đã chọn.
- Chọn nhiều hơn một cơ sở dữ liệu trong tậpcơ sở dữ liệu và bắt đầu tìm kiếm các tài liệu mà được biết là có mặt và được biết không có mặt trong các cơ sở dữ liệu đã chọn.
Thông qua ví dụ này, ta có thể nhận thấy việc kiểm thử một yêu cầu không chỉ viết một
trường hợp kiểm thử mà thông thường ta phải viết vài kịch bản kiểm thử để đảm bảo rằng các kịch bản kiểm thử này đã bao phủ được tất cả các trường hợp của yêu cầu.
Kiểm thử các yêu cầu khác trong hệ thống LYBSYS có thể được thực hiện giống như trên. Với yêu cầu thứ hai, ta sẽ đưa ra các trường hợp kiểm thử để phân phối tất cả các kiểu tài liệu có thể được xử lý bởi hệ thống và kiểm tra việchiển thị các tài liệu đó. Với yêu cầu thứ ba, ta có thể đưa vào một vài yêu cầu về việc đặt tài liệu, sau đó kiểm tra định danh yêu cầu được hiển thị trong phiếu chứng nhận của người dùng và kiểm tra định danh yêu cầu đó có phải là duy nhất
hay không.
7.4.2. Kiểm thử phân vùng
Dữ liệu đầu vào và kết quả đầu ra của một chương trình thường rơi vào một số lớp khác nhau có chung các thuộc tính, chẳng hạn như tập số âm, tập số dương và việc lựa chọn từ thanh thực đơn. Các chương trình vận hành theo cách để có thể so sánh được tất cả các thành viên của một lớp. Nghĩa là, nếu cần kiểm thử một chương trình có một số phép toán và yêu cầu có 2 số dương, ta mong rằng chương trình cũng được thực thi như thế với tất cả các số dương.
Những lớp này đôi khi được gọi là phân vùng tương đương. Một cách tiếp cận có hệ thống để thiết kế các trường hợp kiểm thử là dựa trên việc xác định tất cả các vùng cho một hệ thống hoặc một thành phần. Các trường hợp kiểm thử được thiết kế sao cho dữ liệu kiểm thử và kết quả đầu ra nằm trong những vùng này. Kiểm thử phân vùng có thể được sử dụng để thiết kế
các trường hợp kiểm thử cho cả hệ thống và các thành phần.
Trong hình 7.9, mỗi vùng tương đương được chỉ ra trong một hình ellipse. Các vùng dữ liệu kiểm thử tương đương là các tập dữ liệu mà tất cả các thành viên của tập hợp nên được xử lý cùng một cách. Vùng kết quả đầu ra tương đương là các chương trình có những đặc tính chung, do đó chúng có thể được xem như một lớp riêng biệt. Ta cũng có thể xác định các vùng mà dữ liệu kiểm thử nằm bên ngoài các vùng do ta lựa chọn. Trường hợp kiểm thử này được thực hiện ngay khi chương trình xử lý dữ liệu đầu vào không đúng một cách hợp lý. Dữ liệu đúng và không đúng cũng tạo nên các vùng tương đương nhau.
Hình 7.9. Phân vùng tương đương
Khi có một tập các vùng xác định, ta có thể lựa chọn các trường hợp kiểm thử từ các vùng này. Một nguyên tắc nhỏ cho việc lựa chọn các trường hợp kiểm thử là nên lựa chọn các trường hợp nằm ở vùng biên hơn là những trường hợp nằm giữa vùng. Lý do căn bản cho cách lựa chọn này là người thiết kế và lập trình chỉ chú ý tới những giá trị điển hình của dữ liệu đầu vào khi phát triển hệ thống. Ta kiểm tra trường hợp này với dữ liệu thuộc điểm giữa của phân vùng. Những giá trị ngoại biên thường là không đúng kiểu, vì thế nó hay nằm ngoài tầm kiểm soát của người phát triển. Lỗi chương trình thường xảy ra khi thực thi với những dữ liệu này.
Khi xác định các phân vùng ta thường sử dụng tài liệu đặc tả hoặc tài liệu người dùng.
Hệ thống
Tập các đầu ra
Đầu vào hợp lệ Đầu vào không
Hình 7.10. Các phân vùng tương đương
Để minh họa cho nguồn gốc của các trường hợp kiểm thử, ta sử dụng đặc tả của chương trình tìm kiếm được chỉ ra trong hình 7.11. Đoạn chương trình này tìm kiếm trong một dãy các thành phần đầu ra, một thành phần có giá trị định trước. Chương trình sẽ trả lại vị trí của thành phần trong dãy nếu nó tìm thấy. Trong trường hợp này, ta xác định phân vùng bằng việc xác định tiền điều kiện, nó đúng khi chương trình được gọi và một hậu điều kiện, nó đúng sau khi chương trình được thực thi.
Tiền điều kiện chỉ ra rằng thuật toán tìm kiếm chỉ thực hiện với một mảng không rỗng. Hậu điều kiện chỉ ra rằng biến tìm ra được thiết lập nếu như thành phần khóa nằm trong dãy. Vị trí của thành phần khóa là L trong dãy. Chỉ số giá trị không được xác định nếu thành phần cần tìm kiếm không tồn tại trong dãy. Từ đặc tả này, bạn có thể nhận thấy 2 vùng tương đương nhau:
1. Input mà thành phần cần tìm nằm trong dãy (found = true)
2. Input mà thành phần cần tìm không nằm trong dãy (found = false)
Hình 7.11. Đoạn đặc tả chương trình tìm kiếm trong dãy
Để kiểm thử chương trình này, ta có thể áp dụng các chỉ dẫn sau:
1. Kiểm thử phần mềm với các dãy giá trị đơn. Người lập trình thông thường nghĩ rằng các
dãy được hình thành bởi một số giá trị và thỉnh thoảng họ gắn giả thiết này vào chương trình của họ. Kết quả là chương trình có thể làm việc không hợp lý khi được thực hiện với một dãy giá trị đơn.
2. Sử dụng các dãy khác nhau với kích thước khác nhau trong các kịch bản khác nhau. Điều
này làm giảm cơ hội mà một chương trình có lỗi sẽ sinh ra kết quả đúng một cách ngẫu nhiên bởi các đặc tính ngẫu nhiên của dữ liệu đầu vào.
Vì thế các trường hợp kiểm thử với các thành phần đầu tiên, ở giữa, cuối cùng của dãy được truy cập. Cách tiếp cận này sẽ phát hiện ra những vấn đề tại các điểm biên của phân vùng.
Nhỏ hơn 4 Từ 4 đến 10 Lớn hơn 10 Số giá trị đầu vào
Các giá trị đầu vào
Nhỏ hơn 10000 Từ 10000 đến 99999 Lớn hơn 99999
procedure Search (Key : ELEM ; T: SEQ of ELEM; Found: in out BOOLEAN; L: in out ELEM_INDEX);
Pre-condition
-- Dãy có ít nhất một phần tử T’FIRST <= T’LAST
Post-condition
-- Phần tử được tìm thấy và được chỉ bằng L ( Found and T (L) = Key)
or
-- Phần tử không thuộc dãy ( not Found and
Từ những hướng dẫn trên, có hai phân vùng tương đương cần phải được xác định:
1. Dãy dữ liệu vào có một giá trị đơn.
2. Số thành phần trong dãy dữ liệu vào nhiều hơn một thành phần.
Sau đó có thể xác định thêm các phân vùng bằng cách kết hợp các vùng này – ví dụ, phân vùng mà số thành phần trong dãy lớn hơnsố thành phần không nằm trong phân vùng.
Bảng 7.1 chỉ ra các phân vùng phải xác định để kiểm thử chức năng tìm kiếm. Một tập có thể các trường hợp kiểm thử dựa trên những phân vùng này cũng được chỉ ra như trong bảng 7.1. Nếu thành phần cần tìm kiếm không nằm trong dãy, giá trị của L là không xác định (‘??’). Gợi ý sử dụng các dãy với kích thước khác nhau để kiểm thử trường hợp này.
Tập hợp các giá trị đầu vào để kiểm thử giải thuật tìm kiếm không thể bao quát được tất cả các khía cạnh. Giải thuật có thể sai nếu dãy dữ liệu vào bao gồm các giá trị 1, 2, 3, 4.
Bảng 7.1. Các phân hoạch tương đương cho chương trình tìm kiếm
Dãy Phần tử
Có một giá trị Thuộc dãy
Có một giá trị Không thuộc dãy
Nhiều hơn một giá trị Là phần tử đầu tiên trong dãy Nhiều hơn một giá trị Là phần tử cuối cùng trong dãy Nhiều hơn một giá trị Là phần tử nằm giữa trong dãy Nhiều hơn một giá trị Không thuộc dãy
Dãy đầu vào (input) Khóa (Key) Đầu ra (Found, L)
17 17 True, 1 17 0 False, ?? 17, 29, 21, 23 17 True, 1 41, 18, 9, 31, 30, 16, 45 45 True, 7 17, 18, 21, 23, 29, 41, 38 23 True, 4 21, 23, 29, 33, 38 25 False, ?? 7.4.3. Kiểm thử cấu trúc
Kiểm thử cấu trúc (hình 7.12) là một cách tiếp cận để thiết kế các trường hợp kiểm thử khi biết cấu trúc và mã nguồn của phần mềm. Cách tiếp cận này đôi khi còn gọi là kiểm thử hộp trắng, hộp gương hoặc hộp trong – để phân biệt với kiểm thử hộp đen.
Hình 7.12. Kiểm thử cấu trúc
Hình 7.13. Các lớp tương đương trong tìm kiếm nhị phân
Việc hiểu giải thuật được sử dụng trong chương trình có thể giúp bạn xác định các phân vùng và các trường hợp kiểm thử. Để minh họa cho điều này, ta tiến hành đặc tả thủ tục tìm kiếm (hình 7.11) bằng giải thuật tìm kiếm nhị phân (hình 7.14). Giải thuật này phải có tiền điều kiện chặt chẽ. Dãy được thực hiện phải là một dãy đã được sắp xếp và giá trị ở cận dưới của mảng phải nhỏ hơn giá trị cận trên.
Hình 7.14. Thuật toán tìm kiếm nhị phân
Bằng việc xem xét đoạn mã của giải thuật tìm kiếm, ta có thể thấy rằng việc tìm kiếm nhị phân liên quan tới việc chia khoảng tìm kiếm thành ba phần. Mỗi phần là một phân vùng tương đương (hình 7.13).
Sau đó ta thiết kế các trường hợp kiểm thử sao cho khóa nằm ở biên của các phân vùng.
Đây chính là cơ sở để xây dựng các trường hợp kiểm thử cho giải thuật tìm kiếm, như chỉ ra trong bảng 7.2. Dãy dữ liệu đầu vào được sắp xếp theo thứ tự tăng dần và phải thêm vào các kiểm thử mà thành phần cần tìm kiếm sát với điểm giữa của dãy.
Các phần tử < phần tử
giữa Các phần tử > phần tử giữa Ranh giới giữa các lớp tương
đương
Điểm giữa
Class BinSearch{
// Đây là hàm tìm kiếm nhị phân được thực hiện trên một dãy các đối tượng đã có thứ tự và một khóa // Trả về một đối tượng với hai thuộc tính là:
// Index –giá trị chỉ số của khóa trong dãy
// found –có kiểu logic cho biết có hay không có khóa trong dãy
// Một đối tượng được trả về bởitrong java không thể thông qua các kiểu cơ bản bằng tham chiếu // tới một hàm và trả về hai giá trị. Giá trị Index = -1 nếu khóa không có trong dãy.
public static void search(int key, int[] elemArray, Result r) {
1. int bottom = 0;
2. int top = elemArray.length – 1; Int mid;
3. r.found = false; 4. r.index = -1; 5. while (bottom <=top)
{
6. mid = (top + bottom)/2; 7. if(elemArray[mid] = key; { 8. r,index = mid 9. r.found = true; 10. return; } //if Else { 11. if(elemArray[mid]<key) 12. bottom = mid + 1; Else 13. Top = mid – 1; } } //while loop } //search } // BinSearch
Bảng 7.2. Các trường hợp kiểm thử cho thuật toán tìm kiếm nhị phân
Dãy đầu vào (input) Khóa (Key) Đầu ra (Found, L)
17 17 True, 1 17 0 False, ?? 17, 21, 23, 29 17 True, 1 9, 16, 18, 30, 31, 41, 45 45 True, 7 17, 18, 21, 23, 29, 38, 41 23 True, 4 17, 18, 21, 23, 29, 33, 38 21 True, 3 12, 18, 21, 23, 32 23 True, 4 21, 23, 29, 33, 38 25 False, ??
7.4.4. Kiểm thử đường (path testing)
Kiểm thử đường là một chiến lược kiểm thử cấu trúc với mục tiêu thực thi tất cả các đường trong một thành phần hoặc một chương trình. Trước tiên, mọi đường độc lập đều được thực thi, sau đó tất cả các câu lệnh trong thành phần phải được thực thi ít nhất một lần. Hơn nữa, tất cả các điều kiện cũng đều phải được kiểm thử với hai trường hợp đúng và sai.
Trong tiến trình phát triển hướng đối tượng, kiểu kiểm thử này cũng có thể được sử dụng để kiểm thử việc thực thi các phương thức của đối tượng. Số lượng đường độc lập trong một chương trình thường cân xứng với kích thước của nó. Khi một module được tích hợp vào trong hệ thống, nó trở nên khó sử dụng phương pháp kiểm thử cấu trúc. Kỹ thuật kiểm thử đường được sử dụng nhiều khi kiểm thử đơn vị.
Kiểm thử đường không kiểm thử tất cả những kết hợp có thể của các thành phần trong chương trình. Đối với bất kỳ thành phần nào ngoài thành phần thông thường không có vòng lặp,
thì điều này là không khả thi vì có vô số đường kết hợp có thể trong một chương trình có lặp.