Current State
Output Next State
a b a b q1 0 1 q1 q4 q2 0 1 q1 q5 q3 0 1 q5 q1 q4 1 1 q3 q4 q5 1 1 q2 q5
Nhóm các trạng thái có cùng output ta được phân vùng tương đương mức 1 bao gồm: W1 = {q1, q2, q3} và W2 = {q4, q5} như ảng 3.5 dưới đây:
2. Xây dựng vùng tương đương mức k
Xây dựng phân vùng tương đương mức 2 bằng cách cập nhật lại bảng phân vùng mức 1: bỏ cột output, thay trạng thái qi ở cột next state bởi qij với j là số nhóm mà chứa qi. Phân vùng mức 2 của FSM G3 được thể hiện trong Bảng 3.6 dưới đây:
Bảng 3.6: Bảng P1 phân vùng tương đương mức 2 của FSM G3
q3 0 1 q5 q1
2 q4 1 1 q3 q4
q5 1 1 q2 q5
W Current State Next State
a b 1 q1 q11 q42 q2 q11 q52 q3 q52 q11 2 q4 q31 q42 q5 q21 q52
Xây dựng phân vùng tương đương mức 3
Bảng 3.7: Bảng P2 phân vùng tương đương mức 3 của FSM G3
W Current State Next State
a b 1 q1 q11 q53 q2 q11 q53 2 q3 q53 q11 3 q4 q32 q43 q5 q21 q53
Xây dựng phân vùng tương đương mức 4
Bảng 3.8: Bảng P3 phân vùng tương đương mức 4 của FSM G3
Xây dựng phân vùng tương đương mức 5
Bảng 3.9: Bảng P4 phân vùng tương đương mức 5 của FSM G3
W Current state Next state a b 1 q1 q11 q44 2 q2 q11 q55 3 q3 q55 q11 4 q4 q33 q44 5 q5 q22 q55
W Current State Next State
a b 1 q1 q11 q43 q2 q11 q54 2 q3 q54 q11 3 q4 q32 q43 4 q5 q21 q54
chính là b. Ta cập nhật z = b.
Trạng thái tiếp theo của q1 và q2 với input b là q4 và q5. Ta chuyển tới bảng P2 và tìm ký hiệu input mà phân biệt q4 và q5, ta chọn a là ký hiệu phân biệt. Cập nhật z = ba.
Trạng thái tiếp theo của trạng thái q4 và q5 với input a là q3 và q2. Hai trạng thái này được phân biệt trong P1 bởi a và b, ta chọn a và cập nhật z = baa.
Trạng thái tiếp theo của trạng thái q3 và q2 đối với input a là q1 và q5. Tới bảng chuyển trạng thái ban đầu, ta được a là ký hiệu phân biệt q1 và q5. Ta cập nhật z = baaa.
Như vậy baaa là chuỗi phân biệt cặp trạng thái q1 và q2. Ta kiểm chứng lại: λ(q1,baaa) λ(q2,baaa).
Với cách làm tương tự như trên, ta tìm được chuỗi phân biệt cho các cặp trạng thái còn lại. Ta tìm được tập W như sau: W = {a, aa, aaa, baaa}
i/o i/o
Chương 4. KIỂM THỬ DỰA TRÊN MÔ HÌNH FSM
4.1. Mối quan hệ mô phỏng của hai FSM
[8] Cho hai FSM MS = <S1, I, O, s01, δ1, λ1> và MI = <S2, I, O, s02, δ2, λ2>,
MI được gọi là mô phỏng MS nếu gọi ξ là quan hệ mô phỏng thì: 1. (s01, s02)∈ ξ
2. (s1, s2) ∈ ξ ⟹
{∀i ∀o ∀s1’ [(s1 <MS> s1’) ⟹ [(s2 <MI> s2’) ∧ (s1’, s2’ ∈ ξ)]]} Để hiểu rõ hơn về định nghĩa, ta x t ví dụ sau:
Giả sử MS là máy hữu hạn trạng thái đặc tả hàm y = |x|
Hình 4.1: Mô hình FSM đặc tả hàm y = |x|.
MI là máy hữu hạn trạng thái thể hiện cài đặt hàm y = |x|
Hình 4.2: Mô hình FSM thể hiện cài đặt hàm y = |x|.
Đối với MS: Khi MS đang ở trạng thái ban đầu E, nếu input giá trị (x > 0) thì sẽ cho output giá trị (x) và chuyển sang trạng thái , nếu input giá trị (x < 0) thì cho output giá trị (-x) và chuyển sang trạng thái B.
Trong tiến trình phát triển phần mềm, một hệ thống reactive thường được đặc tả bởi mô hình FSM MS, mô hình hệ thống cài đặt là FSM MI. Điều chúng ta quan tâm là hệ thống cài đặt MI có “hoạt động đúng” theo như đặc tả MS hay không? Hoạt động kiểm thử sẽ giúp chúng ta có câu trả lời “Có” hay “Không”. Ý tưởng của phương pháp kiểm thử sẽ được trình bày trong mục 4.2.
4.2. Kiểm thử dựa trên mô hình FSM
Một hệ thống được đặc tả bởi mô hình máy hữu hạn trạng thái MS và được cài đặt bằng MI. Kiểm thử xem hệ thống MI có “hoạt động đúng” theo như đặc tả
MS hay không bằng cách so sánh hành vi của hai máy trạng thái dựa trên sự quan sát hành vi input output của MI gọi là kiểm tra sự phù hợp hay sự tìm lỗi [6].
Như thế nào là “hoạt động đúng”, như thế nào là “phù hợp”, như thế nào là “lỗi”? Căn cứ vào đâu để chúng ta có thể đưa ra kết luận MI hoạt động đúng theo đặc tả MS? Trong luận văn này, chúng tôi xin đề xuất khái niệm mô phỏng như là một tiêu chí để đánh giá MI có “hoạt động đúng” như đặc tả hay không.
Như vậy, bài toán ở đây là kiểm thử xem MI có mô phỏng MS hay không, nếu MI không mô phỏng MS thì có lỗi trong quá trình cài đặt.
Làm thế nào để biết được máy hữu hạn trạng thái MI có mô phỏng máy hữu
hạn trạng thái MS hay không? Phương pháp kiểm thử với việc kiểm chứng trạng thái [5] là cách để giúp ta có câu trả lời này. Ý tưởng của phương pháp như sau:
Hình 4.3: Mô hình khái niệm kiểm thử với việc kiểm chứng trạng thái [5].
Phương pháp:
Bước 1: Giả sử rằng FSM MI đang ở trạng thái ban đầu s0, di chuyển FSM MI tới si bằng việc áp dụng một chuỗi inputs được gọi là chuỗi chuyển đổi, được ký hiệu là T(si). Các trạng thái khác nhau thì có chuỗi chuyển đổi khác nhau: T(si) ≠ T(sj) với i ≠ j. Kết thúc bước này, FSM MI ở trạng thái si.
Bước 2: Áp dụng input a cho FSM MI và quan sát output thực tế đạt được, output này được so sánh với giá trị mong đợi b của FSM MS. Kết thúc bước này, nếu chuyển trạng thái được cài đặt đúng thì FSM MI được chuyển sang trạng thái mới sj, trạng thái này mô phỏng trạng thái sj’ của FSM MS.Tuy nhiên sự cài đặt có thể có lỗi, FSM MI khi đó được chuyển tới một trạng thái khác trạng thái sj,trạng thái này không mô phỏng trạng thái sj’ của FSM MS. Trạng thái sj của FSM MI có mô phỏng trạng thái sj’ của FSM MS hay không, điều này sẽ được kiểm chứng (verified) ở bước tiếp theo.
Bước 3: Áp dụng chuỗi kiểm chứng VERj cho FSM MI và quan sát chuỗi
output thực tế đạt được, chuỗi output này được so sánh với chuỗi output tương ứng của FSM MS. Một tính chất quan trọng của VERj là λ(sj,VERj) λ(sl,VERj),∀sl và sl sj. Kết thúc bước này FSM MI ở trạng thái sk.
viết được ngay những đoạn mã không có lỗi. Tính trung bình, một lập trình viên loại tốt thì cũng mắc từ 1 đến 3 lỗi trên 100 dòng lệnh. Người ta ước lượng rằng, việc kiểm thử để tìm ra các lỗi này chiếm phần nửa khối lượng công việc phải làm để có được một phần mềm hoạt động được” [3]. Khi cài đặt MI, thì lập trình viên thường mắc phải là những lỗi gì, chi tiết sẽ được trình bày ở phần tiếp theo.
4.3. Một số lỗi thường gặp khi cài đặt FSM
Khi có bản đặc tả FSM MS = < S1, I, O, s01, δ1, λ1> và hệ thống cài đặt FSM
MI = < S2, I, O, s02, δ2, λ2> , một câu hỏi đặt ra là FSM MI có mô phỏng FSM
MS hay không? Để trả lời câu hỏi này, ta lần lượt trả lời các câu hỏi sau:
1. Trạng thái ban đầu của FSM MI có mô phỏng trạng thái ban đầu của FSM MS hay không?
2. Với mỗi input a và output b thì mỗi chuyển trạng thái s1 s1’ của MS có tồn tại chuyển trạng thái s2 s2’ của MI và trạng thái s2’ có mô phỏng trạng thái s1’ hay không?
Như đã biết FSM MI là một hệ thống cài đặt, nó là một hộp đen (black-box) nên ta không thể quan sát trực tiếp trạng thái của MI mà ch có thể quan sát output của nó thông qua các điểm quan sát khi cung cấp cho MI input thông qua điểm điều khiển. Do đó để trả lời câu hỏi trạng thái ban đầu của FSM MI có mô phỏng trạng thái ban đầu của FSM MS hay không ta dùng một trong các phương pháp kiểm chứng trạng thái đã trình bày ở Chương 3 để xác minh. Giả sử chuỗi kiểm chứng trạng thái là x thì:
Nếu [λ1(s01,x) = λ2(s02,x)] và ∄[λ1(s01,x) ≠ λ2(s02,x)] thì s02 cùng hành vi với s01 hay trạng thái s02 mô phỏng trạng thái s01.
Nếu [λ1(s01,x) ≠ λ2(s02,x)] thì trạng thái s02 không cùng hành vi với s01 hay trạng thái s02 không mô phỏng trạng thái s01
Đốivới câu hỏi 2. ta x t 2 trường hợp: Thứ nhất, ứng với mỗi chuyển trạng thái s1 s1’ của MS có tồn tại chuyển trạng thái s2 s2’của MI hay không? Thứ hai, trạng thái s2’ có mô phỏng trạng thái s1’ hay không?
Có tồn tại chuyển trạng thái s2 → s2’ hay không? Ta kiểm tra xem khi chuyển từ s2 sang s2’ thì MI có cùng output với MS hay không?
Nếu λ2(s2,a) ≠ λ1(s1,a) thì không tồn tại chuyển trạng thái s2 s2’ ⟹ s2 và s1 không cùng hành vi hay s2 không mô phỏng s1 nên MI không mô phỏng
MS.
Nếu λ2(s2,a) = λ1(s1,a) thì tồn tại chuyển trạng thái s2 s2’. Tuy nhiên ta phải kiểm tra xem s2’ có mô phỏng s1’ hay không? Để trả lời câu hỏi “trạng thái s2’ có mô phỏng trạng thái s1’ hay không?” ta cũng sẽ dùng một trong các phương pháp kiểm chứng trạng thái đã trình bày ở Chương 3 để xác minh.
Nếu [λ1(s1’,x) = λ2(s2’,x)] và ∄[λ1(s1’,x) ≠ λ2(s2’,x)] thì s2’ cùng hành vi với s1’ hay trạng thái s2’ mô phỏng trạng thái s1’.
Nếu ∄[λ1(s1’,x) ≠ λ2(s2’,x)] thì trạng thái s2’ không cùng hành vi với s1’ hay trạng thái s2’ không mô phỏng trạng thái s1’.
Kết hợp kiểm tra output và kiểm chứng trạng thái của mỗi một chuyển trạng thái ta sẽ trả lời được câu hỏi 2.
Như vậy, kết hợp câu trả lời của câu hỏi 1. và 2. ta sẽ có câu trả lời cho câu hỏi “FSM MI có mô phỏng FSM MS hay không?”. Ta có Bảng 4.1 tổng hợp các lỗi khi cài đặt FSM MI như sau:
Bảng 4.1: Bảng tổng hợp các lỗi khi cài đặt FSM MI
λ1(s01,x) = λ2(s02,x) λλ12(s(s0102,x) ≠ ,x) [λ1(s1,a) ≠ λ2(s2,a)] [λ1(s1’,x) ≠ λ2(s2’,x)] [λ1(s1’,x) = λ2(s2’,x)] Kết luận - T - - - No T F T - - No T F F T - No T F F F T Yes
“No”: MIkhông mô phỏng MS
“ es”: MI có mô phỏng MS
Như vậy, qua Bảng 4.1 ta có thể thấy một số lỗi thường gặp khi kiểm thử sự mô phỏng của hai FSMs như sau:
Trạng thái tiếp theo của một chuyển trạng thái của MI không mô phỏng trạng thái trạng thái tiếp theo ứng với chuyển trạng thái tương ứng của MS. Trên đây là những lỗi mà lập trình viên có thể mắc phải khi cài đặt FSM
MI. Tuy nhiên, để kiểm thử viên phát hiện được ra những lỗi đó thì không phải đơn giản nếu không có phương pháp và chiến lược kiểm thử tốt. Trong chương 5 chúng tôi sẽ trình bày về độ bao phủ của mô hình FSM và chọn ra tiêu chí tốt nhất để sinh ca kiểm thử mà có thể phát hiện được các lỗi đã được tổng kết ở Bảng 4.1.
Chương 5. KỸ THUẬT SINH CA KIỂM THỬ
5.1. Độ bao phủ mô hình máy hữu hạn trạng thái
Như đã trình bày ở Chương 2, những đặc trưng của máy trạng thái bao gồm: trạng thái (state), input, output, chuyển trạng thái (transtion). Theo [4] thì trong việc kiểm thử dựa trên mô hình FSM chúng ta thường coi vấn đề input như là một phần của vấn đề trạng thái hoặc chuyển trạng thái. Giả định rằng tất cả inputs cần phải được xử lý một cách chính xác thông qua một số quá trình chuyển trạng thái của FSM, thậm chí cả khi đầu vào không hợp lệ được mong đợi là sẽ được xử lý chính xác mà không gây treo hệ thống hoặc các vấn đề khác, chẳng hạn như thông qua các cách thức sau đây:
Bỏ qua input không hợp lệ như là đứng yên ở cùng một trạng thái đối với những trường hợp input không hợp lệ đó.
Xử lý trực tiếp input không hợp lệ như xuất ra thông báo lỗi thông qua việc điều khiển những ngoại lệ và những sự chuyển trạng thái liên quan.
Đối với outputs, chúng ta cũng không giải quyết trực tiếp những vấn đề về output mà coi nó là một phần của vấn đề kiểm thử chuyển trạng thái. Ví dụ, sự chuyển tiếp đưa ra những thông tin không mong đợi như thừa, thiếu, lỗi output thì sẽ xác định sự chuyển tiếp là sự chuyển tiếp lỗi.
Vì thế trong kiểm thử dựa trên FSM tập trung vào những vấn đề về trạng thái và chuyển trạng thái. Input được sử dụng chính cho sự cập nhật và output được sử dụng chính cho sự kiểm tra kết quả.
Một câu hỏi đặt ra là: để kiểm thử FSM MI thì cần thiết kế bao nhiêu ca kiểm thử? Căn cứ vào đâu để biết được số ca kiểm thử đã đủ hay chưa? Trước tiên, chúng ta xem x t hai ch số để đo độ bao phủ là: Độ bao phủ trạng thái (state coverage) và độ bao phủ chuyển trạng thái (transition coverage).
5.1.1. Độ bao phủ trạng thái (state coverage)
Để đạt được độ bao phủ trạng thái ta lựa chọn chuỗi các chuyển trạng thái sao cho mỗi trạng thái được thăm ít nhất một lần [5]. Bài toán này sẽ tương đương với việc tìm đường đi qua tất cả các đ nh của một đồ thị có hướng sao cho mỗi đ nh được thăm ít nhất một lần. Vì mỗi đ nh của đồ thị tương đương với một trạng thái mà các trạng thái là hữu hạn nên việc tìm đường đi này là hoàn toàn có thể thực hiện được.
Hình 5.1: Mô hình máy hữu hạn trạng thái C1.
Với đường đi qua các đ nh q1 → q4 → q3 → q5 → q2 → q1 (đường n t đậm trong Hình 5.2) sẽ qua tất cả các đ nh của đồ thị, điều đó có nghĩa là tất cả các trạng thái của FSM đều được thăm. Do đó, với chuỗi chuyển trạng thái q1
q4 → q3 → q5 → q2 → q1 của FSM C1 sẽ đạt độ bao phủ trạng thái là 100%.
Hình 5.2: Một đường đi bao phủ tất cả các trạng thái của FSM C1.
Tuy nhiên, độ bao phủ trạng thái là điều kiện lựa chọn yếu nhất trong tất cả các điều kiện lựa chọn để tạo ra ca kiểm thử [5]. Đường đi q1 → q4 → q3 → q5 → q2 → q1 mới ch bao phủ được 5/10 chuyển trạng thái, như vậy còn 5 chuyển trạng thái không được bao phủ và lỗi khi cài đặt có thể xuất hiện ở phần không được bao phủ này. Chúng ta x t một dạng điều kiện bao phủ mạnh hơn đó
là bao phủ chuyển trạng thái. Độ bao phủ chuyển trạng thái sẽ được trình bày trong mục 5.1.2.
5.1.2. Độ bao phủ chuyển trạng thái (transition coverage)
Để đạt được độ bao phủ chuyển trạng thái ta lựa chọn chuỗi các chuyển trạng thái sao cho mỗi chuyển trạng thái được thăm ít nhất một lần [5]. ài toán này sẽ tương đương với việc tìm đường đi qua tất cả các cạnh của một đồ thị có hướng sao cho mỗi cạnh được qua ít nhất một lần. Vì mỗi cạnh của đồ thị tương đương với một sự chuyển trạng thái mà các trạng thái là hữu hạn nên việc tìm đường đi này là hoàn toàn có thể thực hiện được.
Để tìm độ bao phủ chuyển trạng thái trước tiên ta xây dựng cây kiểm thử từ mô hình FSM. Cây kiểm thử của một FSM là một cây có gốc là trạng thái ban đầu. Từ trạng thái ban đầu, nó chứa ít nhất một đường đi từ trạng thái ban đầu tới các trạng thái còn lại của FSM [2].
Theo [2], phương pháp xây dựng cây kiểm thử như sau:
Bước 1: Gốc của cây kiểm thử là trạng thái ban đầu.
Bước 2: Giả sử rằng cây kiểm thử đã được xây dựng đến mức k, mức thứ
k+1 sẽ được xây dựng như sau: Chọn một nút n tại mức k,
Nếu n xuất hiện ở mức bất kỳ từ 1 đến k thì n là nút lá và không xây dựng thêm nhánh này.