Khóa luận Nghiên cứu về mức bao phủ của kiểm thử

Mục lục

CHƯƠNG 1. MỞ ĐẦU 10

1.1 Bối cảnh nghiên cứu 10

1.2 Nội dung bài toán 11

1.3 Cấu trúc của khoá luận 12

CHƯƠNG 2. GIỚI THIỆU VỀ BAO PHỦ CODE 14

2.1 Bao phủ code là gì ? 14

2.2 Tại sao cần đo lượng code được bao phủ ? 14

2.3 Làm thế nào để xác định lượng code được bao phủ ? 15

2.4. Trong tiến trình test thì bao phủ code hợp với kỹ thuật kiểm thử nào ? 15

2.4.1 Kiểm thử hộp đen 15

2.4.2 Kiểm thử hộp trắng 15

2.4.3 Bao phủ code 16

CHƯƠNG 3. GIỚI THIỆU MỘT SỐ PHƯƠNG PHÁP BAO PHỦ 17

3.1 Bao phủ câu lệnh (Statement coverage) 17

3.2 Bao phủ nhánh (Branch coverage) 17

3.3 Bao phủ đường đi (path coverage) 18

3.4 Bao phủ điều kiện (condition coverage) 18

3.5 Bao phủ nhiều điều kiện (multiple condition coverage) 18

CHƯƠNG 4. PHÂN TÍCH, ĐÁNH GIÁ CÁC PHƯƠNG PHÁP BAO PHỦ 19

4.1 Phân tích phương pháp bao phủ câu lệnh (statement coverage) 19

4.2 Phân tích phương pháp bao phủ nhánh (branch coverage) 23

4.3 Phân tích phương pháp bao phủ đường đi (path coverage) 28

CHƯƠNG 5. PHÂN TÍCH GIÁ TRỊ ĐIỂM BIÊN 33

5.1 Giới thiệu 33

5.2 Phân hoạch tương đương(equivalence partitioning) 33

5.3 Phân tích giá trị biên (boundary value analysis) 34

5.3.1 Tổng quan về phân tích giá trị điểm biên 34

5.3.2 Lựa chọn các ca kiểm thử sử dụng phân tích giá trị điểm biên 34

5.3.3 Phân tích giá trị biên đơn biến (Single-Variable BVA) 35

5.3.4 Phân tích giá trị biên đa biến (Multi – Variable BVA) 36

5.3.5 Kết luận 40

CHƯƠNG 6. THỰC NGHIỆM 41

6.1 Ví dụ một chương trình đơn giản 41

6.1.1 Xây dựng các ca kiểm thử cho chương trình trên 42

6.1.2 Kết luận 46

6.2 Chương trình cài đặt tìm kiếm các câu lệnh rẽ nhánh trong mã nguồn java. 46

6.2.1 Giới thiệu về chương trình 46

6.2.2 Mô tả các chức năng chính 46

6.2.3 Biểu đồ trình tự 47

6.2.4 Thuật toán đã sử dụng 49

6.2.5 Các lớp cài đặt 51

6.2.5 Kết quả thao tác các chức năng giữa người dùng và chương trình như sau 51

6.3 Kết luận 56

CHƯƠNG 7: KẾT LUẬN KHOÁ LUẬN 57

7.1 Kết luận về khoá luận 57

7.2 Hướng nghiên cứu phát triển trong tương lai 57

TÀI LIỆU THAM KHẢO 59

 

 

doc59 trang | Chia sẻ: netpro | Lượt xem: 3803 | Lượt tải: 1download
Bạn đang xem trước 20 trang tài liệu Khóa luận Nghiên cứu về mức bao phủ của kiểm thử, để xem tài liệu hoàn chỉnh bạn click vào nút DOWNLOAD ở trên
ực thi, những câu lệnh nào không được thực thi thì yêu cầu ta cần phải phân tích bao phủ code. Phân tích code sẽ giúp ta: làm rõ những code không được thực thi nhờ test suite. Thêm vào các ca kiểm thử để kiểm tra lại. Nhận ra code dư thừa. Khi chương trình thiết kế thay đổi thường sẽ dẫn đến code dư thừa. Code dư thừa nên được loại bỏ vì nó có thể gây khó hiểu cho công việc của người bảo trì. Phân tích code bao phủ còn được sử dụng để theo dõi các phần code đặc biệt. Với việc đếm từng dòng code, bản phân tích bao phủ còn được sử dụng để sắp xếp có thứ tự các khối cơ bản trong một hàm. Thông qua phân tích bao phủ code sẽ làm giảm số lỗi. Bao phủ code không phải là phương thuốc chữa bách bệnh, bao phủ code sẽ không giúp nhận dạng các loại điều kiện, các vần đề về sử dụng bộ nhớ, con trỏ lỗi, thẩm định kết quả chương trình. Phân tích bao phủ code luôn sẵn có trong nhiều ngôn ngữ lập trình phổ biến như C++, nhưng chúng thường là các sản phẩm thứ ba được tích hợp với bộ biên dịch, và thường rất đắt. Như vậy phân tích bao phủ code là quá trình tạo ra các ca kiểm thử để tìm ra các vùng chưa được thực thi, tạo thêm các ca kiểm thử để tăng bao phủ và xác định lượng code bao phủ sẽ gián tiếp đo chất lượng code. Dưới đây ta sẽ lần lượt phân tích một số đề xuất bao phủ nhằm đưa ra để đánh giá chất lượng của ca kiểm thử: bao phủ câu lệnh (statement coverage), bao phủ nhánh (branch coverage) và bao phủ đường đi (path coverage) . 4.1 Phân tích phương pháp bao phủ câu lệnh (statement coverage) Trong thiết kế test case ta luôn cố gắng bao phủ tối đa câu lệnh trong mã nguồn với số test case ít nhất có thể. Bao phủ câu lệnh sẽ nhận ra các câu lệnh trong một phương thức hay trong một lớp đã được thực thi. Đây là một phương pháp đo đơn giản là tìm ra số câu lệnh đã được thực thi trong tổng số các câu lệnh mã nguồn [7]. Do đó lợi ích của bao phủ câu lệnh là khả năng tìm ra các dòng code không được thực thi. Xét một ví dụ đơn giản. Mã nguồn của chương trình như sau: public class StatementCoverage { public void FunctionPrint () { System.out.println("This is example about statement coverage"); } public static void main (String [] args) { StatementCoverage hi=new StatementCoverage(); hi.FunctionPrint(); } } Trong chương trình mã nguồn trên ta nhận thấy có : Số lớp : 1 lớp (lớp StatementCoverage). Số phương thức : 3 phương thức : Main() FunctionPrint() Println() Số dòng lệnh : 6 dòng. Sử dụng công cụ EMMA (open source) đo bao phủ dòng lệnh,(phần giới thiệu và cách cài đặt công cụ EMMA sẽ được giới thiệu ở phần phụ lục) kiểm tra các dòng mã nguồn đã được thực thi ta được báo cáo kết xuất như sau : Hình 1 : Kết quả kiểm tra mã nguồn được thực thi Kết quả kết xuất ở trên thông báo có số gói được tìm thấy là một, tổng số lớp có trong chương trình là một, tổng số phương thức trong lớp là ba, tổng số file thực thi là một và tổng số dòng đã thực thi là sáu. Với kết quả báo cáo như trên ta nhận thấy 100% mã nguồn đã được thực thi. Tuy nhiên bao phủ dòng lệnh có nhược điểm là không thể nhận ra các lỗi xảy ra từ cấu trúc luồng điểu khiển trong mã nguồn như là khi ghép các điều kiện hay các nhãn switch liên tiếp. Điều này có nghĩa là báo cáo bao phủ của ta vẫn sẽ kết suất ra kết quả báo cáo là 100% code đã được bao phủ nhưng thực tế thì các lỗi đã không được bắt. Ví dụ ta xét hàm returnInput() sau: public int returnInput(int x, boolean condition1, boolean condition2, boolean condition3) { if (condition1) x++; if(condition2) x--; if(condition3) x=x; return x; } Trong phương thức returnInput() ở trên có 7 câu lệnh trong nó. Kết quả mong muốn là giá trị đầu ra bằng với giá trị đầu vào. Ta sẽ kiểm tra hoạt động của hàm trên bằng cách thiết lập ca kiểm thử với các giá trị truyền vào hàm : int x=1; boolean condition1=true; boolean condition2=true; boolean condition3=true; Chương trình mã nguồn đầy đủ : public class Path { public int returnInput(int x, boolean condition1, boolean condition2, boolean condition3) {if (condition1) x++; if(condition2) x--; if(condition3) x=x; return x; } public static void main (String [] args) {int x=0; boolean condition1=true; boolean condition2=true; boolean condition3=true; Path constructorInstance=new Path(); int methodReturn=constructorInstance.returnInput (x,condition1, condition2,condition3); } } Kiểm tra các câu lệnh đã được thực thi ta được có kết quả báo cáo: tổng số gói là 1, tổng số lớp là 1, tổng số file là 1, tổng số phương thức là 3, tổng số dòng đã thực thi là 16. Minh hoạ kết quả báo cáo bao phủ câu lệnh như sau. Hình 2 : Kết quả đo bao phủ dòng lệnh Kết quả nhận được là chương trình được bao phủ 100% nhưng thực tế rõ ràng đã có một lỗi trong hàm returnInput(). Nếu ta đánh giá nhánh đầu tiên hoặc nhánh thứ hai là “true” thì kết quả trả lại của hàm không như mong muốn, giá trị trả lại không bằng với giá trị đầu vào. Lỗi này thật nguy hiểm, nếu người quản lý xem kết quả bao phủ 100%, quyết định việc test đã hoàn thành thì sản phẩm phát hành sẽ có lỗi. Như vậy có thể nói bao phủ dòng lệnh không báo cáo về các vòng lặp tới các điều kiện lặp, nó chỉ báo cáo phần thân của vòng lặp có được thực thi hay không. Với ngôn ngữ C, C++ và Java thì hạn chế này ảnh hưởng tới các vòng lặp. Đối với vòng lặp “do-while” khối lệnh sau “do” được thực hiện ít nhất một lần, bao phủ dòng lệnh xem chúng giống với các câu lệnh không rẽ nhánh. Bao phủ câu lệnh không thể phân biệt các nhãn switch liên tiếp[6]. Nhìn chung các ca kiểm thử tương thích với các nhánh hơn là với các câu lệnh. Ta sẽ không thể tạo ra 10 ca kiểm thử riêng biệt cho 10 câu lệnh không rẽ nhánh mà ta sẽ tạo ra một ca để kiểm tra chúng. Ví dụ : xem xét câu lệnh “if-else”. Có một câu lệnh theo sau mệnh đề “if” và có 99 câu lệnh theo sau mệnh đề “else”. Sau khi áp dụng một trong hai đường đi có thể, bao phủ cậu lệnh cho ta kết quả bao phủ hoặc 1% hoặc là 99 %. Bao phủ câu khối lệnh thường lờ đi vấn đề này. Trước những hạn chế của bao phủ câu lệnh ta có thể tìm đến một kỹ thuật bao phủ khác tốt hơn đó là bao phủ nhánh. 4.2 Phân tích phương pháp bao phủ nhánh (branch coverage) Một nhánh là một kết luận logic của một quyết định, do vậy bao phủ nhánh đơn giản là đo kết luận logic nào đã được kiểm tra. Phương pháp bao phủ này xem xét mã nguồn sâu sắc hơn là phương pháp bao phủ câu lệnh. Xác định số nhánh có trong một phương thức là một việc dễ làm. Kết luận kiểu boolean hiển nhiên có hai kết luận logic là “true” hoặc “false” do đó chương trình có N quyết định sẽ có 2N nhánh. Phương pháp bao phủ nhánh vẫn có những đơn giản như ở bao phủ câu lệnh tuy nhiên nó đã loại bỏ được một số hạn chế có ở bao phủ câu lệnh. Tổng số quyết định tác động lên một phương thức bằng với tổng số nhánh cần được bao phủ và nhánh entry trong phương thức. Quay trở lại với ví dụ : public class Path { public int returnInput(int x, boolean condition1, boolean condition2, boolean condition3) { if(condition1) x++; if(condition2) x--; if(condition3) x =x; return x; } } Trong ví dụ này ta sẽ có 7 nhánh: 3 nhánh “true”, 3 nhánh “false” và một nhánh entry. Nhận thấy rằng để bao phủ 7 nhánh này ta chỉ cần đến 2 test case như sau : Test case 1 : public void testReturnInputIntBooleanBooleanBoolean_Path1(){ int x=0; boolean condition1=true; boolean condition2=true; boolean condition3=true; Path contructorInstance=new Path(); Int methodReturn= constructorInstance.returnInput(x, condition1, condition2,condition3); } Test case 2 : public void testReturnInputIntBooleanBooleanBoolean_Path2(){ int x=0; boolean condition1=false; boolean condition2=false; boolean condition3=false; Path contructorInstance=new Path(); int methodReturn= constructorInstance.returnInput(x, condition1, condition2,condition3); } Biên dịch chương trình đầy đủ kiểm tra với test case 1 public class Path { public int returnInput(int x, boolean condition1, boolean condition2, boolean condition3) { if(condition1) x++; if(condition2) x--; if(condition3) x=x; return x; } public static void main(String []args) { int x=0; boolean condition1=true; boolean condition2=true; boolean condition3=true; Path constructorInstance=new Path(); int methodReturn= constructorInstance.returnInput(x, condition1, condition2,condition3); System.out.println("Ket qua mong doi : output value = input value"); System.out.println("output value :"+methodReturn);} } Kết quả test 1: Hình 3 : Kết quả thực hiện test case 1 Cho chạy qua công cụ đo bao phủ ta được kết quả Hình 4 : Kết quả đo bao phủ nhánh khi thực hiện test case 1 Biên dịch và chạy chương trình đầy đủ với test case 2 public class Path { public int returnInput(int x, boolean condition1, boolean condition2, boolean condition3) { if(condition1) x++; if(condition2) x--; if(condition3) x=x; return x; } public static void main(String []args) { System.out.println("Test case : false-false-false"); System.out.println("Cac cau lenh trong cac dieu kien se khong duoc thuc thi"); int x=0; boolean condition1=false; boolean condition2=false; boolean condition3=false; Path constructorInstance=new Path(); int methodReturn= constructorInstance.returnInput(x, condition1, condition2,condition3); System.out.println("Ket qua mong doi : output value = input value"); System.out.println("output value :"+methodReturn); } } Kết quả test 2: Hình 5 : Kết quả khi thực hiện test case 2 Cho chạy qua công cụ bao phủ ta được kết quả : Hình 6 : Kết quả đo bao phủ nhánh khi thực hiện test case 2 Với 2 test case như trên thẩm định cả yêu cầu giá trị output bằng với giá trị input và 100% nhánh đã được bao phủ. Nhưng dễ dàng nhận thấy ngay cả khi 100% nhánh được bao phủ thì chương trình vẫn có lỗi được tìm ra. Trong ví dụ vừa đề cập, ta đã không kiểm tra các trường hợp : TRUE-FALSE-TRUE hay FALSE-TRUE-TRUE…Với 3 quyết định trong một phương thức như trên ta sẽ có 2^3=8 quyết định. Kiểm tra 8 cách đi là một điều dễ dàng, nhưng có những phương thức có rất nhiều quyết định thì số đường đi sẽ tăng theo hàm mũ. Ví dụ một phương thức có tới 10 quyết định kiểu boolean như vậy ta sẽ có 210=1024 cách đi. Lúc này để đạt được mục tiêu bao phủ 100% câu lệnh và 100% nhánh là điều vô cùng khó khăn và không khả thi cho những phương thức phức tạp[11]. 4.3 Phân tích phương pháp bao phủ đường đi (path coverage) Một đường đi thể hiện một luồng thực thi từ khi bắt đầu đến khi kết thúc một hàm. Một phương thức với N quyết định sẽ có 2^N đường đi, và nếu phương thức có chứa vòng lặp thì có thể có vô số đường đi. Nhưng may thay, ta có thể sử dụng phương pháp được gọi là Cyclomatic Complexity [3] để làm giảm số đưòng đi mà chúng ta cần kiểm tra. Cysclomatic complexity của một phương thức là tổng số quyết định duy nhất trong phương thức. Cysclomatic complexity giúp ta định nghĩa số tuyến tính các đường độc lập, được gọi là các thiết lập cơ sở qua một phương thức. Các thiết lập cơ sở là các thiết lập các đường đi một cách ít nhất có thể. Giống như bao phủ nhánh, kiểm tra các đường thiết lập đảm bảo kiểm tra từng quyết định nhưng không giống như bao phủ nhánh, bao phủ đường đi đảm bảo kiểm tra tất cả các quyết định tác động động lập với nhau. Nói một cách khác, mỗi đường đi mới “flips” chính xác nhánh đã thực thi trước đó, các nhánh còn lại khác không thay đổi. Đây là nhân tố chủ yếu làm cho bao phủ đường đi mạnh mẽ hơn bao phủ nhánh, đồng thời nó còn cho phép ta nhìn nhận được những thay đổi khi một nhánh tác động lên hoạt động của một phương thức. Ta vẫn sẽ sử dụng ví dụ trong bao phủ câu lệnh và bao phủ nhánh để minh hoạ. public class Path { public int returnInput(int x, boolean condition1, boolean condition2, boolean condition3) { if(condition1) x++; if(condition2) x--; if(condition3) x =x; return x; } } Để đạt được bao phủ 100% đường đi, chúng ta cần định nghĩa các đường cơ sở. Cysclomatic complexity của phương thức này là bốn, do vậy ta cần định nghĩa bốn tuyến đường độc lập nhau. Để thực hiện công việc này ta sẽ chọn bất kỳ đường đầu tiên làm đường cơ sở và sau đó sẽ lật các quyết định một lần cho tới khi ta có các đường thiết lập cơ sở. Path 1: Chọn các giá trị “true” cho các quyết định, biểu diễn là TTT. Đây là đường đầu tiên trong thiết lập cơ sở của ta. Path 2 : Ta sẽ tìm đường cơ sở tiếp theo, lật quyết định đầu tiên trong đường cơ sở, đem lại giá trị FTT, giá trị ta mong muốn quyết định tác động. Path 3 : Lật quyết định thứ 2 trong đường cơ sở, đem lại cho ta giá trị TFT Path 4 : Cuối cùng, lật quyết định thứ 3 trong đường cơ sở, ta được đường thứ 4 với giá trị TTF. Vậy đã có 4 đường là : TTT, FTT,TFT và TTF. Tiếp theo đây ta sẽ xây dựng các ca kiểm thử và xem điều gì xảy ra. Hai đường đi TTT và FFF đã được kiểm tra trong bao phủ nhánh.Tiến hành kiểm tra đường đi FTT và TFT: Test case 3: Kiểm tra FTT. Thực thi đoạn code sau : public class Path { public int returnInput(int x, boolean condition1, boolean condition2, boolean condition3) { if(condition1) x++; if(condition2) x--; if(condition3) x=x; return x; } public static void main(String []args) { System.out.println("Test case : false-true-true"); System.out.println("Cac cau lenh trong cac dieu kien 1 se khong duoc thuc thi"); int x=0; boolean condition1=false; boolean condition2=true; boolean condition3=true; Path constructorInstance=new Path(); int methodReturn= constructorInstance.returnInput(x, condition1, condition2,condition3); System.out.println("Ket qua mong doi : output value = input value"); System.out.println("output value :"+methodReturn); } } Kết quả : Hình 7: Kết quả thực hiện test case 3 Đo bao phủ code ta được kết quả : Hình 8 : Kết quả đo bao phủ khi thực hiện test case 3 Test case 4 : Kiểm tra TFT.Thực thi đoạn code sau : public class Path { public int returnInput(int x, boolean condition1, boolean condition2, boolean condition3) { if(condition1) x++; if(condition2) x--; if(condition3) x=x; return x; } public static void main(String []args) { System.out.println("Test case : true-false-true"); System.out.println("Cac cau lenh trong cac dieu kien 2 se khong duoc thuc thi"); int x=0; boolean condition1=false; boolean condition2=true; boolean condition3=true; Path constructorInstance=new Path(); int methodReturn= constructorInstance.returnInput(x, condition1,condition2,condition3); System.out.println("Ket qua mong doi : output value = input value"); System.out.println("output value :"+methodReturn);} } Kết quả : Hình 9 : Kết quả thực hiện test case 4 Đo bao phủ code ta được kết quả : Hình 10 : Kết quả đo bao phủ khi thực hiện test case 4 Với kết quả của test case 3 và 4 ta nhận được lỗi chương trình, các lỗi này không nhận ra trong bao phủ câu lệnh và bao phủ nhánh. Kết quả mong đợi của chương trình là giá trị đầu vào và giá trị đầu ra phải bằng nhau. Ở đây giá trị đầu vào là 0 nhưng ta đã nhận được giá trị đầu ra là +1 và -1, vậy là lỗi đã được tìm ra. Tổng số đường cơ sở sẽ tăng theo số quyết định nhưng lúc này đã không tăng theo hàm mũ mà vẫn đảm bảo được yêu cầu bao phủ đầy đủ các nhánh. Ta nhận thấy rằng bao phủ đường đi bao gồm cả bao phủ câu lệnh và bao phủ nhánh trong phương thức. Nó tác động gộp lên cả bao phủ nhánh và bao phủ câu lệnh. Ta luôn nhớ rằng, mục đích kiểm tra của các đường cơ sở là để kiểm tra tất cả các nhánh tác động độc lập với nhau. Kiểm tra 4 đường cơ sở nhằm đạt được mục đích này. Ta có thể xây dựng các đường đi hoàn toàn khác nữa, nếu ta bắt đầu với đường cơ sở FFF sau đó tiến hành “flips” như đã làm ở trên ta sẽ thiết lập được 4 đường cơ sở hoàn toàn khác là : FFF, TFF, FTF,FFT. Kết quả của bộ 4 đường mới này với bộ 4 đường ở trên là như nhau, đều thoả mãn tiêu chuẩn tác động độc lập lên các quyết định. Qua đây dễ dàng nhận thấy với Cyclomatic complexity (số đường độc lập tuyến tính đi qua mã nguồn) giúp ta giảm một nửa số test case cần tiến hành. CHƯƠNG 5. PHÂN TÍCH GIÁ TRỊ ĐIỂM BIÊN 5.1 Giới thiệu Trong nhiều chương trình có nhiều hàm có vô số giá trị đầu vào do đó việc kiểm tra từng giá trị là vô cùng khó khăn, không khả thi. Nhưng trong vô vàn giá trị đầu vào đó ta nên chọn giá trị nào là tốt nhất cho kiểm tra ? Lấy bao nhiêu giá trị kiểm tra là đủ ?...Một kỹ thuật được đề xuất phục vụ cho việc lựa chọn giá trị kiểm tra đó là kỹ thuật phân hoạch tương đương (equivalence partitioning) và phân tích giá trị điểm biên (boundary value analysis), với kỹ thuật này giúp ta giảm đáng kể số ca kiểm thủ cần thực hiện. Phân tích giá trị điểm biên là một kỹ thuật phổ biến và quan trọng nhất trong việc thiết kế các ca kiểm thử. Nếu như đo bao phủ code là một kỹ thuật trong kiểm thử hộp trắng thì phân tích giá trị điểm biên lại là một kỹ thuật kiểm thử hộp đen. Trong kiểm thử hộp đen, các ca kiểm thử không tập trung vào cấu trúc thực bên trong logic chương trình mà nó được lựa chọn dựa trên các chức năng mong muốn có trong sản phẩm như trong tài liệu yêu cầu đã mô tả. Chúng ta kiểm tra chương trình có làm việc chính xác hay không trong một vài trường hợp đặc biệt, các trường hợp đặc biệt thường là các giá trị biên hoặc các giá trị vô cùng của biến đầu vào. Thông thường các lỗi chương trình thường hay xảy ra ở giá trị biên. Phân tích giá trị biên thường được kết hợp với phân hoạch tương đương (equivalence partitioning). Phân hoạch tương đương và phân tích giá trị biên có mối quan hệ chặt chẽ với nhau, luôn đi liền với nhau, đôi khi thật khó để phân biệt các ca kiểm thử được tạo bởi hai kỹ thuật này. Nói chung giá trị biên được nhận dạng là giá trị viền của các lớp phân hoạch tương đương. Để hiểu được giá trị biên trước hết ta đi tìm hiều về phân hoạch tương đương. 5.2 Phân hoạch tương đương(equivalence partitioning) Phân hoạch tương đương là một kỹ thuật kiểm thử hộp đen. Phân hoạch tương đương xác định số ca kiểm thử cho từng trường hợp cụ thể. Nhìn chung dùng phân hoạch tương đương nhằm mục đích : Giảm số ca kiểm thử Lựa chọn các ca kiểm thử chính xác để bao hàm các trường hợp có thể. Phân hoạch tương đương chia miền dữ liệu vào ra thành các vùng, mỗi vùng chứa các dữ liệu có cùng hành vi. Đối với mỗi vùng dữ liệu do dữ liệu có cùng hành vi nên ta chỉ cần xây dựng một ca kiểm thử để đại diện. Giá trị bên trong một vùng dữ liệu được xem là “tương đương” do đó số ca kiểm thử sẽ giảm xuống. Dải dữ liệu đầu vào bao gồm dải hợp lệ và dải không hợp lệ. Ta có ví dụ : truyền tham số tháng cho ngày. Trong ví dụ này ta có các dải giá trị hợp lệ và không hợp lệ như sau: Dải giá trị hợp lệ cho tháng là từ 1 đến 12 tương ứng từ tháng 1 đến tháng 12, có hai dải giá trị không hợp lệ đó là nhỏ hơn hoặc bằng 0 và lớn hơn hoặc bằng 13. Với 3 dải dữ liệu này sẽ có 3 ca kiểm thử được dề xuất tương ứng với 3 dải. Phân hoạch tương đương không đơn thuần là phương pháp xác định các ca kiểm thử một các đầy đủ. Kết hợp với phân tích các giá trị biên giới giữa các vùng, ta sẽ thêm vào các ca kiểm thử ở giá trị biên, từ đó tìm ra các ca kiểm thử hiệu quả nhất cho từng vùng[12]. 5.3 Phân tích giá trị biên (boundary value analysis) 5.3.1 Tổng quan về phân tích giá trị điểm biên Phân tích giá trị biên là một kỹ thuật thiết kế ca kiểm thử và được sử dụng để chỉ ra dữ liệu kiểm tra từ đó xây dựng các ca kiểm thử. Theo kinh nghiệm, đa phần các sai sót về lập trình thường xảy ra đối với các dữ liệu biên, những nơi diễn ra tính toán cơ học hoặc sự thao tác dữ liệu phải thay đổi cho hợp lý để chương trình xuất ra kết quả chính xác. Ý tưởng của phân tích giá trị biên là sử dụng giá trị biến đầu vào ở các vị trí : giá trị nhỏ nhất, giá trị lớn nhất, giá trị ngay bên trong biên, giá trị ngay bên ngoài biên, giá trị đại điện thông thường, và các giá trị lỗi. Kết quả mong đợi là khi chương trình làm việc chính xác với các giá trị đặc biệt này thì nó sẽ làm việc chính xác với các giá trị thông thường bên trong miền giá trị. Để kiểm tra một phương thức nào đó việc đầu tiên ta phải xác định dải dữ liệu hợp lệ và không hợp lệ đầu vào cùng với các điều kiện cho chức năng được xét[10]. 5.3.2 Lựa chọn các ca kiểm thử sử dụng phân tích giá trị điểm biên Thiết lập các ca kiểm thử được chỉ ra bởi phân tích giá trị điểm biên phụ thuộc vào cả sự yêu cầu về tính tin cậy của phần mềm và cả những giả thuyết có thể xảy ra trong quá trình kiểm soát lỗi. Tiếp theo sau đây chúng ta sẽ thảo luận về phân tích giá trị điểm biên của đơn biến (single-variable) và đa biến (multi-variable) dựa trên phân loại phân tích giá trị biên. 5.3.3 Phân tích giá trị biên đơn biến (Single-Variable BVA) Xem xét giá trị đầu vào để chỉ ra giá trị biên. Tất cả các giá trị biên này sẽ được kết hợp chặt chẽ trong việc thiết lập các ca kiểm thử. Những giá trị gần biên sẽ được thêm vào và sẽ được sử dụng để kiểm tra. Giá trị gần biên sẽ trợ giúp kiểm soát logic các đường biên của chương trình. Ví dụ khi kiểm tra dải giá trị trong một nhánh hoặc câu lệnh lặp người phát triển có thể sử dụng toán tử nhỏ hơn (). Các đoạn code được biên dịch nhưng chạy không chính xác với các điều kiện sẽ dẫn đến lỗi. Các giá trị gần giá trị biên phải có trong các ca kiểm thử để kiểm tra các loại lỗi này [4].Trong các ca kiểm thử thêm vào đường biên các giá trị gần biên, quá trình phân tích giá trị biên baseline sẽ gồm một vài giá trị đầu vào tồn tại trên danh nghĩa. Ví dụ sau sẽ minh hoạ cho quá trình phân tích giá trị biên baseline: Xem xét chương trình với một giá trị đầu vào N, dải giá trị của N là : a ≤ N ≤ c. Các ca kiểm thử được chọn trong tập hợp giá trị baseline ={a, a+, b, c-, c}. a+ là giá trị lớn hơn a, c- là giá trị nhỏ hơn c và b là một giá trị tồn tại trên danh nghĩa, b nằm trong khoảng a+ và c-. Trong ví dụ này, quá trình phân tích giá trị biên baseline sẽ chỉ ra năm ca kiểm thử. Minh hoạ bằng hình bên dưới. baseline Hình 11 : Tập hợp các giá trị biên baseline cho đơn biến trên một khoảng đầu vào Nếu như quản lý lỗi là một việc then chốt sau khi kiểm tra phần mềm thì cần phải tăng thêm các ca kiểm thử kiểm tra một cách mạnh mẽ thông qua quá trình phân tích giá trị biên baseline, cần thêm vào các giá trị bên ngoài dải cho phép. Các ca kiểm tra baseline được chỉ ra ở trên sẽ được thêm vào giá trị {a-,c+}, giá trị a- là giá trị bên dưới giá trị chấp nhận a và c+ là giá trị ngay trên giá trị chấp nhận c. Cả hai giá trị {a-,c+} dùng trong các ca kiểm thử cần phải được thực thi để xử lý trường hợp ngoại lệ hoặc để che dấu khuyết điểm code. Quay trở lại với ví dụ trên giá trị đầu vào đơn lúc này sẽ gồm bẩy giá trị hết sức mạnh mẽ: robust={a-, a, a+, b, c-, c, c+}. Minh hoạ bằng hình bên dưới : baseline robust Hình 12 : Đường các giá trị baseline và robust cho đơn biến trên một khoảng đầu vào Quá trình phân tích giá trị biên baseline hay quá trình phân tích biên rubust đều có thể được áp dụng cho giá trị đầu vào có nhiều dải giá trị. Xem xét biến đầu vào đơn M với hai dải giá trị con liền nhau, dải 1 được là d ≤ M < f và dải 2 là f ≤ M ≤ h. Thiết lập các ca kiểm thử lúc này là kết hợp tất cả các ca kiểm thử được chỉ ra khi cách áp dụng quá trình phân tích giá trị biên đối với từng dải giá trị riêng lẻ. Do vậy kết hợp kết quả tất cả các ca kiểm thử áp dụng cho từng dải riêng rẽ ta được : Mbaseline= {d, d+, e, f-, f} ∪ {f, f+, g, h-, h} = {d, d+, e, f-, f, f+, g, h-, h} Áp dụng phân tích giá trị biên robust làm M baseline tăng thêm các giá trị {d-, h+} mang lại kết quả Mrobust = {d-, d, d+, e, f-, f, f+, g, h-, h, h+} được minh hoạ bằng hình bên dưới baseline robust augmentation Hình 13 : Tập hợp các giá trị baseline và rubust trường hợp đơn biến trên hai khoảng đầu vào Thêm vào nhiều dải giá trị con hiển nhiên sẽ làm tăng số ca kiểm thử. Đối với hai dải giá trị liền nhau của một biến đầu vào, phân tích giá trị biên baseline chỉ ra 9 ca kiểm thử và phân tích giá trị biên rubust chỉ ra 11 ca kiểm thử. 5.3.4 Phân tích giá trị biên đa biến (Multi – Variable BVA) Đối với bài toán đa biến quá trình phân tích giá trị biên lựa chọn ca kiểm thử cần phải xem xét lỗi có thể xảy ra, trong bài viết này ta sẽ đề cập đến lỗi tại biên với đa biến đầu vào là một kiểu lỗi (ta sẽ gọi là multiple-fault). Đối với kiểu lỗi multiple-fault [4] được cho rằng nhiều lỗi đồng thời xảy ra, do vậy ta sẽ thêm vào các ca kiểm thử để soát lỗi trên đồng thời nhiều biến. Lấy ra từ ví dụ đơn biến ở trên, xét bài toán với hai biến đầu vào N và M, với dải giá trị của N: a ≤ N ≤ c và giá trị của M trải dài trên hai dải, dải #1:d ≤ M < f , dải #2: f ≤ M ≤ h. Như dã thảo luận ở trên, các ca kiểm thử đơn biến đã chỉ ra đối với N và M là : Nbaseline= {a, a+, b, c-, c} Mbaseline= {d, d+, e, f-, f, f+, g, h-, h} Các ca kiểm thử phân tích giá trị biên đa biến sử dụng cách phân tích các đường biên của một biến trong khi các biến khác được giữ là một giá trị danh nghĩa. Hợp tất cả các ca kiểm thử áp dụng cho từng biến đầu vào ta được tập các ca kiểm thử áp dụng cho đa biến đầu vào. Trong ví dụ trên ta sẽ áp dụng cho từng biến đầu vào trên từng dải giá trị con. Bài toán có hai giá trị đầu và

Các file đính kèm theo tài liệu này:

  • docNghiên cứu về mức bao phủ của kiểm thử.doc