Conditions Values Rules or Combinations
R1 R2 R3 R4 R5 R6 R7 R8 C1 Y, N,- Y Y Y Y N N N N C2 Y, N,- Y Y N N Y Y N N C3 Y, N,- Y N Y N Y N Y N Effects E1 E2 E3 Checksum
Bảng quyết định bao gồm một tập các điều kiện và một tập các hệ quả được sắp xếp dưới dạng một cột bên trái của bảng. Ở cột thứ 2, cột tiếp theo cột điều kiện là cột gồm các giá trị có thể có bao gồm: Đúng (Y), Sai (N), Không xác định (-). Bên phải cột giá trị là một tập các luật. Mỗi luật bao gồm các giá trị Y, N, (-). Mỗi luật trên bảng quyết định xác định một trường hợp kiểm thử.
Theo [2], ta có các bước để xây dựng ca kiểm thử dựa vào kỹ thuật bảng quyết định như sau:
(1) Xác định các nguyên nhân và kết quả dựa vào mỗi đặc tả:
(2) Liệt kê tất cả nguyên nhân và kết quả vào bảng quyết định. Viết xuống các giá trị mà điều kiện có thể trả về (Y, N, -)
(3) Tính số lượng kết hợp có thể có. Nó bằng số lượng giá trị khác nhau tăng lên số lượng của điều kiện. Ví dụ: Nếu điều kiện nhận 2 giá trị khác nhau(Y,N) và có 4 điều kiện xảy ra thì số lượng kết hợp có thể có là 24.
(4) Điền vào tất cả các cột tất cả các kết hợp có thể có. Mỗi cột sẽ tương ứng với một kết hợp của các giá trị. Còn với mỗi dòng (điều kiện) thì ta thực hiện như sau:
Xác định tần số lặp (RF) bằng cách: chia số lượng còn lại của kết hợp cho số lượng giá trị khác nhau của điều kiện.
Viết RF lần các giá trị đầu tiên, sau đó RF lần tiếp theo và vân vân, cho tới khi hàng đã được điền đủ.
(5) Giảm thiểu các kết hợp (các nguyên tắc). Tìm các kết hợp không có ảnh hưởng, thay thế bằng dấu (-), và các kết hợp các cột giống nhau làm một. Lưu ý, trong suốt quá trình này phải đảm bảo rằng các kết quả là không bị thay đổi.
(6) Kiểm tra độ bao phủ của các kết hợp (các nguyên tắc). Với mỗi cột tính số kết hợp mà nó đại diện. Một (-) đại diện cho nhiều kết hợp như điều kiện đã có. Nhân cho mỗi (-) xuống cột. Thêm vào tổng số và so sánh với bước 3. Nó phải bằng nhau.
(7) Thêm các kết quả vào cột trên bảng quyết định. Đọc cột theo cột và xác định kết quả. Nếu có nhiều hơn một kết quả xảy ra trong một sự kết hợp duy nhất, thì gán số thứ tự cho kết quả, từ đó xác định được thứ tự mà các kết quả sẽ được thực hiện. Kiểm tra sự phù hợp của bảng quyết định.
(8) Chuyển các cột trong bảng quyết định thành các ca kiểm thử.
Sau khi xây dựng xong bảng quyết định, chúng ta sẽ tiến hành tạo các ca kiểm thử dựa trên cấu trúc bảng quyết định. Thông thường tương ứng với mỗi luật sẽ có ít nhất một ca kiểm thử được sinh ta. Nếu điều kiện của các luật là giá trị nhị phân (True/False), cần xây dựng ca kiểm thử cho từng điều kiện. Nếu điều kiện của luật là một vùng, phạm vi giá trị, chúng ta cần phải chú ý xem xét và viết ca kiểm thử cho cả trường hợp biến đầu vào nhận giá trị thấp nhất (min) và cao nhất (max) tương ứng với vùng giá trị đó. Ở bước này, kiểm thử viên cần kết hợp cả kỹ thuật kiểm thử giá trị biên và bảng quyết định để tạo ra bộ kiểm thử đầy đủ và chính xác (theo [3]).
Để phân biệt các trường hợp kiểm thử với bảng quyết định, chúng ta cần làm sáng tỏ các điều kiện đầu vào và các hành động đầu ra. Đôi khi các điều kiện cuối
cùng lại đề cập đến các lớp tương đương của các yếu tố đầu vào, và các hành động ám chỉ các phần xử lý chức năng chủ yếu của các mục được kiểm thử. Các luật được hiểu như là các trường hợp được kiểm thử. Bởi vì bảng quyết định có thể được thực hiện một cách máy móc cho đầy đủ, nên chúng ta thường xây dựng được một tập toàn vẹn các trường hợp kiểm thử.
Nhận xét:
Kỹ thuật sinh ca kiểm thử sử dụng bảng quyết định nên áp dụng cho các ứng dụng có những đặc trưng sau [1]:
Kiểm thử dựa trên bảng quyết định nên áp dụng cho các bài toán chứa các biến đầu vào có mối quan hệ logic phụ thuộc lẫn nhau.
Kỹ thuật này phù hợp cho các bài toán có sử dụng logic if – then-else.
Kiểm thử dựa trên bảng quyết định xử lý hiệu quả các bài toán có chứa quan hệ nguyên nhân và kết quả giữa đầu vào và đầu ra.
3.2 Kiểm thử hộp trắng
Kỹ thuật kiểm thử hộp trắng hay còn gọi là kiểm thử hướng cấu trúc thường được áp dụng để kiểm tra tính đúng đắn của mã nguồn (được lập trình). Đầu vào của kỹ thuật này là các mã nguồn, mã lệnh chứ không phải là chương trình đã được thực thi. Do đó, kỹ thuật này được áp dụng để kiểm thử cấu trúc chương trình, dòng điều khiển và dòng xử lý dữ liệu của chương trình.
Kỹ thuật này thường tốn thời gian, công sức để thực hiện, nên thường chỉ áp dụng ở mức độ kiểm thử đơn vị (hàm, lớp thành phần) của chương trình chứ không thực hiện ở các mức độ cao hơn.
Các kỹ thuật kiểm thử hộp trắng là: Kiểm thử dòng điều khiển, kiểm thử dòng dữ liệu và kiểm thử miền.
3.2.1. Kỹ thuật dòng điều khiển (Control Flow Testing)
Kỹ thuật dòng điều khiển là kỹ thuật là các testcase được sinh ra dựa việc mô hình hóa các luồng xử lý (hành vi của hệ thống) theo khái niệm đồ thị dòng điều khiển (control flow graph). Để tiến hành xác định kiểm thử, ta sẽ mô hình hóa các dòng lệnh từ mã nguồn bằng đồ thị dòng điều khiển. Từ đồ thị đó, mỗi rẽ nhánh trong luồng xử lý sẽ sinh ra một đường đi. Dựa trên các đường đi ta sẽ sinh được các testcase tương ứng.
Kỹ thuật này là kỹ thuật kiểm thử căn bản và được áp dụng hiệu quả cho nhiều hệ thống, nhiều giai đoạn test khác nhau.
Các bộ giá trị kiềm thử sinh ra từ kỹ thuật này có thể kiểm tra được tính đúng đắn với các thành phần của chương trình gồm: Các phương thức ( Method ), các câu lệnh (Statement ), các nhánh (branch), các điều kiện (if, switch…).
Hình 3.6 Sơ đồ dòng điều khiển
Các ký hiệu sử dụng trong đồ thị CFG:
Hình 3.7 Các ký hiệu sử dụng trong đồ thị
Để xác định mức độ bao phủ của chương trình của một tập ca kiểm thử cho trước ta sử dụng khái niệm độ đo kiểm thử. Theo [1]: Mức độ bao phủ của một tập kiểm thử được đo bằng tỷ lệ các thành phần thực sự được kiểm thử so với tổng thể sau khi thực hiện ca kiểm thử. Độ bao phủ càng lớn thì độ tin cậy của bộ kiểm thử ngày càng cao.
Độ đo kiểm thử cấp 1 (C1) : mỗi câu lệnh được thực hiện ít nhất 1 lần sau khi chạy hết các ca kiểm thử.
Độ đo kiểm thử cấp 2 (C2) : các điểm quyết định trong đồ thị đều được thực hiện ít nhất một lần cả hai nhánh đúng và sai.
Độ đo kiểm thử cấp 3 (C3) : Với các điều kiện phức tạp (chứa nhiều điều kiện con cơ bản), việc chỉ quan tâm đến giá trị đúng sai là không đủ để kiểm tra tính đúng đắn của chương trình ứng với điều kiện phức tạp này. Do đó, điều kiện để đảm bảo độ đo này là các điều kiện con thuộc các điều kiện phức tạp tương ứng với các điểm quyết định trong đồ thị dòng điều khiển của đơn vị cần kiểm thử đều được thực hiện ít nhất một lần cả hai nhánh đúng và sai.
Từ các định nghĩa về độ đo, ta có thể áp dụng kiểm thử độ đo để xác định số ca kiểm thử sao cho các ca kiểm thử bao phủ một độ đo nào đó. Theo [1], ta có số đường đi ứng với đồ thị dòng điều khiển sẽ được tính bằng một trong hai cách như sau:
1. Số cạnh – số đỉnh + 2 2. Số đỉnh quyết định + 1
Ứng với mỗi đường đi ta sẽ sinh ra được một ca kiểm thử tương ứng.
Bên cạnh việc tiến hành xây dựng kiểm thử dựa trên độ đo, ta nhận thấy vẫn chưa kiểm tra được các lỗi phát sinh do xuất hiện vòng lặp trong chương trình. Mặt khác, trong quá trình viết mã nguồn cho các đơn vị/hàm, các lỗi gây ra do sử dụng vòng lặp là khá nhiều và gây ảnh hưởng lớn đến chương trình. Theo [1], với chương trình có vòng lặp ta cần quan tâm đến loại vòng lặp là:
Lệnh lặp đơn giản: Tức là đơn vị chương trình chỉ có chứa một lệnh lặp. Lệnh lặp liền kề: Tức là đơn vị chương trình chứa lệnh lặp liền kề nhau.
Lệnh lặp lồng nhau: Tức là đơn vị chương trình chứa lệnh lặp mà trong nó còn chứa lênh lặp khác
Để tiến hành kiểm thử với vòng lặp, ta sẽ xây dựng các ca kiểm thử dựa trên số lần thực hiện của vòng lặp trong chương trình gồm:
1. Vòng lặp thực hiện 0 lần 2. Vòng lặp thực hiện 1 lần 3. Vòng lặp thực hiện 2 lần
4. Vòng lặp thực hiện k lần, 2 < k < n - 1, với n là số lần lặp tối đa của vòng lặp
5. Vòng lặp thực hiện n - 1 lần 6. Vòng lặp thực hiện n lần 7. Vòng lặp thực hiện n + 1 lần
Trong một số trường hợp, việc xác định số vòng lặp tối đa là khó, ta chỉ cần pá dụng việc sinh ca kiểm thử với bốn trường hợp đầu tiên. Với những trường hợp không
xác định được lệnh lặp thực hiện n+1 lần, ta chỉ áp dụng sinh kiểm thử với 6 trường hợp trước đó.
Kết luận:
Kỹ thuật kiểm thử dòng điều khiển là kỹ thuật phát hiện các lỗi tiềm ẩn của chương trình bằng các xác định các đường đi tương ứng với dòng điều khiển của chương trình từ đồ thị dòng điều khiển. Với mỗi một đường đi của đồ thị, ta sẽ xây dựng một ca kiểm thử và đảm bảo đường đi là thực thi được.
Trên thực tế, có không nhiều các công ty phần mềm áp dụng kỹ thuật kiểm thử này do việc áo dụng là khó, tốn kém hơn các kỹ thuật kiểm thử hộp đen [1]. Tuy nhiên, có một số công cụ đã hỗ trợ việc thực hiện kỹ thuật này bằng việc thực thi các ca kiểm thử trên một đơn vị hàm, đề xác định tính đúng đắn của hàm dựa trên kết quả chạy ca kiểm thử.
3.2.2. Kỹ thuật dòng dữ liệu (Data Flow Testing)
Kỹ thuật kiểm thử dòng dữ liệu là kỹ thuật mà việc sinh ca kiểm thử được dựa trên các đường đi sinh ra từ đồ thị dòng dữ liệu. Khi đó, các đường dẫn kiểm thử của chương trình sẽ được lựa chọn dựa vào vị trí khai báo và sử dụng các biến trong chương trình.
Trong quá trình lập trình, mỗi lập trình viên đều có thể sinh ra các câu lệnh “bất thường” hoặc không tuân theo chuẩn lập trình. Những câu lệnh bất thường đó có thể là việc khai báo biến, dữ liệu không đúng, khởi tạo giá trị biến không đúng hoặc sử dụng biến, gán giá trị…Những vấn đề đó là những vấn đề về dòng dữ liệu của đơn vị chương trình. Theo [1], các vấn đề này được chia thành ba loại như sau:
Gán giá trị rồi gán tiếp giá trị (loại 1).
Chưa gán giá trị nhưng được sử dụng (loại 2)
Đã được khai báo và gán giá trị nhưng không được sử dụng (loại 3)..
Huang [7] đã giới thiệu một phương pháp để xác định những bất thường trong việc sử dụng các biến dữ liệu bằng cách sử dụng sơ đồ chuyển trạng thái ứng với mỗi biến dữ liệu của chương trình.
Để áp dụng kỹ thuật kiểm thử dòng dữ liệu động, chúng ta phải xác định các đường dẫn chương trình có một điểm đầu vào và một điểm đầu ra sao cho nó bao phủ việc gán giá trị và sử dụng mỗi biến của chương trình/đơn vị chương trình cần kiểm thử. Các bước thực hiện như sau [1]:
Xây dựng đồ thị dòng dữ liệu của chương trình/đơn vị chương trình
Chọn một hoặc một số tiêu chí kiểm thử dòng dữ liệu
Xác định các đường dẫn chương trình phù hợp với tiêu chí kiểm thử đã chọn
Lấy ra các biểu thức điều kiện từ tập các đường đi, thực hiện giải các biểu thức điều kiện để có được các giá trị đầu vào cho các ca kiểm thử tương
ứng với các đường đi này và tính toán giá trị đầu ra mong đợi của mỗi ca kiểm thử
Thực hiện các ca kiểm thử để xác định các lỗi (có thể có) của chương trình.
Sửa các lỗi (nếu có) và thực hiện lại tất cả các ca kiểm thử trong trường hợp bước trên phát hiện ra lỗi.
Sau khi xây dựng đồ thị dòng dữ liệu của đơn vị chương trình, chúng ta cần xác định các đường đi của đơn vị chương trình của mỗi biến dữ liệu ứng với các độ đo kiểm thử. Trong mỗi đường dẫn này, biến dữ liệu được định nghĩa tại một đỉnh nào đó và được sử dụng tại các câu lệnh tiếp theo ứng với các đỉnh hoặc các cạnh của đường đi này.
Theo [1] ta có một số khái niệm cơ bản về dòng dữ liệu gồm:
Định nghĩa Global c-use: Giả sử biến x được sử dụng để tính toán (c-use) tại đỉnh i của đồ thị dòng dữ liệu. Việc sử dụng biến x tại đỉnh i được gọi là Global c-use nếu x đã được định nghĩa ở các đỉnh trước đó.
Định nghĩa Def -clear path: Giả sử biến x được định nghĩa (def ) tại đỉnh i và được sử dụng tại đỉnh j . Một đường đi từ i đến j ký hiệu là (i- n1- ... – nm - j ) với m ≥ 0 được gọi là Def -clear path ứng với biến x nếu biến này không được định nghĩa tại các đỉnh từ n1 đến nm.
Định nghĩa Global def: Một đỉnh i được gọi là Global def của biến x nếu đỉnh này định nghĩa biến x (def ) và có một Def -clear path của x từ đỉnh i tới đỉnh chứa một Global c-use hoặc cạnh chứa một p-use của biến này.
Định nghĩa Simple path: Một đường đi trong đồ thị dòng dữ liệu được gọi là một Simple path nếu các đỉnh chỉ xuất hiện đúng một lần trừ đỉnh đầu và đỉnh cuối.
Định nghĩa Loop-free path: Một đường đi trong đồ thị dòng dữ liệu được gọi là một Loop-free path nếu các đỉnh chỉ xuất hiện đúng một lần.
Định nghĩa Complete-path: Một đường đi được gọi là một Complete-path nếu nó có điểm bắt đầu và điểm kết thúc chính là điểm bắt đầu và điểm kết thúc của đồ thị dòng dữ liệu.
Định nghĩa Du-path Một đường đi (n1- n2- ... – nj – nk) được gọi là một Du-path (definition-use path) ứng với biến x nếu đỉnh n1 là Global def của biến x và:
đỉnh nk có một Global c-use với biến x và (n1- n2- ... – nj – nk) là một Def -clear simple path với biến x, hoặc
cạnh (nj, nk) có p-use với biến x và (n1- n2- ... – nj) là Def –clear loop-free path với biến này.
Các độ đo hay các tiêu chí kiểm thử dòng dữ liệu là đầu vào cùng với đồ thị dòng dữ liệu nhằm xác định các đường đi cho mục đích kiểm thử tương ứng. Các độ đo phổ biến đang được sử dụng trong kiểm thử dòng dữ liệu gồm ba độ đo đơn giản là All-
defs, All-c-uses, và All-p-uses tương ứng với tất cả các đường đi, đường đi qua tất cả các đỉnh, và đường đi qua tất cả các cạnh.
Hình 3.8 Mối quan hệ giữa các độ đo kiểm thử dòng dữ liệu.
Để tiến hành sinh ca kiểm thử dựa trên kỹ thuật kiểm thử dòng dữ liệu, chúng ta phải sinh đồ thị dòng dữ liệu từ đơn vị chương trình. Sau đó, từ đồ thị áp dụng từng độ đo kiểm thử, chúng ta sẽ xác định tất cả các đường đi đầy đủ (Complete-paths) thỏa mãn độ đo này. Từ đường đi được xác định, ta sẽ tiến hành sinh bộ dữ liệu đầu vào. Không phải bất cứ đường đi nào cũng có thể tìm được một bộ dữ liệu đầu vào để nó được thực thi được khi chạy đơn vị chương trình. Nếu tồn tại một bộ dữ liệu đầu vào như vậy thì đường đi tương ứng được gọi là đường đi thực thi được [1].