NLNNLT-Kiem chung chuong trinh

Document Sample
NLNNLT-Kiem chung chuong trinh Powered By Docstoc
					          ĐẠI HỌC QUỐC GIA TP HỒ CHÍ MINH
   TRƯỜNG ĐẠI HỌC CÔNG NGHỆ THÔNG TIN
        KHOA KHOA HỌC MÁY TÍNH




BÀI THU HOẠCH NGUYÊN LÝ NGÔN NGỮ LẬP TRÌNH
    ĐỀ TÀI: KIỂM CHỨNG CHƯƠNG TRÌNH

    Giáo viên hường dẫn:    GSTS. HOÀNG KIẾM
     Sinh viên thực hiện:   VŨ TIẾN ĐẠT
                    Lớp:    KHOA HỌC MÁY TÍNH
                   Khóa:    01




                   TP.HỒ CHÍ MINH, 5-2010
                                                         2
Nguyên lý ngôn ngữ lập trình – Kiểm chứng chương trình




                   ĐẠI HỌC QUỐC GIA TP HỒ CHÍ MINH
           TRƯỜNG ĐẠI HỌC CÔNG NGHỆ THÔNG TIN
                KHOA KHOA HỌC MÁY TÍNH




     BÀI THU HOẠCH NGUYÊN LÝ NGÔN NGỮ LẬP TRÌNH
             ĐỀ TÀI: KIỂM CHỨNG CHƯƠNG TRÌNH

            Giáo viên hướng dẫn:    GSTS. HOÀNG KIẾM
             Sinh viên thực hiện:   VŨ TIẾN ĐẠT
                            Lớp:    KHOA HỌC MÁY TÍNH
                           Khóa:    01




                           TP.HỒ CHÍ MINH, 5-2010
                                                                                                                                    3
Nguyên lý ngôn ngữ lập trình – Kiểm chứng chương trình
                                            MỤC LỤC
Mở đầu
I . Kiểm chứng chương trình .................................. ................................................ 5
       I.1. Khái niệm................................................... ............................................... 5
       I.2. Một số thuật ngữ....................................... ................................................ 5
       I.3. Vòng đời kiểm chứng................................. .............................................. 6
       I.4. Mô hình kiểm chứng ................................ ................................................ 6
       I.5. Phẩm chất của một chương trình............... ............................................... 9
       I.6. Các phương pháp kiểm chứng chương trình ........................................... 10
                I.6.1. Cấu trúc kiểm tra chương trình ................................................. 10
                I.6.2. Tính đúng đắn của chương trình ............................................... 10
                I.6.3. Tính chắc chắn của chương trình.............................................. 12
                I.6.4. Kiểm chứng chương trình với mô hình nghịch đảo ................ 12
                I.6.5. Kiểm tra chương trình bằng phương pháp qui nạp................... 13
                I.6.6. Thực hiện bằng biểu tượng                     ................................................. 16
                I.6.7. Chứng thực đối tượng state machine ........................................ 17
                I.6.8. Kiểm tra mọi trạng thái có thể ................................................. 22
                I.6.9. Kiểm tra tính trực giao của trạng thái ....................................... 22
        I.7. Qui trình kiểm chứng............................................................................... 23
                I.7.1. Kiểm chứng tăng dần.............. ................................................. 23
                I.7.2. Kiểm chứng những phần đơn giản trước ................................ 23
                I.7.3. Biết trước dữ liệu xuất............ ................................................ 25
                I.7.4. Kiểm chứng các thuộc tính lưu trữ .......................................... 26
                I.7.5. So sánh các quá trình cài đặt độc lập ...................................... 27
                I.7.6. Kiểm tra tính bao quát của việc kiểm chứng ........................... 27
        I.8. Giới thiệu về 2 phương pháp white box và black box... ............ .... ....... 28
II . Thực nghiệm kiểm chứng chương trình................. .................................................. 29
                  II.1. Trường hợp đơn giản ...................... .................................................. 29
III. Kết luận ....................................................................................................................... 41
Tài liệu tham khảo ................................................................................................... 42
                                                                                        4
Nguyên lý ngôn ngữ lập trình – Kiểm chứng chương trình
Mở đầu


      Như chúng ta biết, các chương trình phần mềm khi được phát triển và đưa vào ứng
dụng thực tế cần phải đạt được những phẩm chất cơ bản như: tính đúng đắn, chính xác
(Correctness); tính chắc chắn (robustness); tính thân thiện với người dùng (User
friendliness); khả năng thích nghi (adapability); tính tái sử dụng (reuseability); tính an
toàn hệ thống (Security)…. Trong đó, tính đúng đắn, chính xác (Correctness) là phẩm
chất đầu tiên và không thể thiếu được đối với bất kỳ phần mềm nào. Vậy có cách nào để
khẳng định một khi phần mềm được đưa vào ứng dụng sẽ đảm bảo được phẩm chất này?
Đây là một câu hỏi rất khó và làm đau đầu nhiều nhà nghiên cứu trong thời gian vừa qua.
Từ đó các phương pháp kiểm chứng chương trình đã ra đời.

      Edsger Dijkstra nhận xét rằng việc kiểm chứng có thể giải thích sự hiện diện của
các lổi nhưng không thể cho biết được sự tiềm ẩn của chúng. Ông hy vọng rằng các
chương trình có thể được viết một cách đúng đắn trong quá trình phát triển chúng để
chương trình không còn lỗi và vì vậy không cần kiểm chứng nữa. Mặc dù đây là một mục
tiêu tốt đẹp nhưng nó không thực tế. Do vậy, trong bài viết này tác giả sẽ đề cập đến
những cách thức kiểm chứng chương trình để tìm ra lỗi nhanh chóng và hiệu quả cũng
như ứng dụng phương pháp white box vào kiểm chứng chương trình.
                                                                                         5
Nguyên lý ngôn ngữ lập trình – Kiểm chứng chương trình
I. Kiểm chứng chương trình

I.1. Khái niệm

    Kiểm chứng là sự kiểm tra có hệ thống nhằm tìm ra các lỗi của chương trình mà
chúng ta nghĩ là nó đang thực hiện đúng.

      Như vậy, kiểm chứng chương trình là một trong những bước quan trọng trong quy
trình phát triển sản phẩm phần mềm, đảm bảo cho chương trình phần mềm chạy ổn định
tránh nhưng sai sót hay lỗi khi đưa vào ứng dụng thực tế. Những lỗi của chương trình ở
đây có thể là: error, fault, failure hoặc incident…

I.2. Một số thuật ngữ

     + Error: là những lỗi do con người gây ra.

      + Fault: sai sót gây ra lỗi. Có thể sai sót do đưa ra dư thừa (đưa một vài thứ không
chính xác vào mô tả yêu cầu phần mềm) hoặc sai sót do bỏ sót (người thiết kế có thể gây
ra sai sót do bỏ sót, kết quả là thiếu một số phần đáng ra phải có trong mô tả yêu cầu
phần mềm).

      + Failure: xảy ra khi sai sót được thực thi (khi thực thi chương trình tại các nơi bị
sai thì sẽ xảy ra trạng thái failure).

     + Incident: là những kết quả do sai sót đem đến.

      + Test case: là trường hợp thử được liên kết tương ứng với hoạt động của chương
trình. Một trường hợp thử bao gồm một tập các giá trị đầu vào và một danh sách các kết
quả đầu ra mong muốn.

      + Verification: là tiến trình nhằm xác định đầu ra của một công đoạn trong việc phát
triển phần mềm phù hợp với công đoạn trước đó.

       + Validation: là tiến trình nhằm chỉ ra toàn hệ thống đã phát triển xong phù hợp với
tài liệu mô tả yêu cầu.

     Lưu ý:

     - Verification: chỉ quan tâm đến việc ngăn chặn lỗi giữa các công đoạn.

     - Validation: chỉ quan tâm đến sản phẩm cuối cùng không còn lỗi.
                                                                                       6
Nguyên lý ngôn ngữ lập trình – Kiểm chứng chương trình
I.3. Vòng đời của kiểm chứng

       Bảng dưới đây mô tả các công đoạn phát triển một phần mềm và cách khắc phục
lỗi.

      Lỗi có thể xảy ra trong tất cả các công đoạn từ “Mô tả yêu cầu”, “Thiết kế” đến
“Lập trình”. Từ công đoạn này chuyển sang công đoạn khác thường nảy sinh các sai sót
(do dư thừa hoặc thiếu theo mô tả yêu cầu). Đến công đoạn kiểm chứng chúng ta sẽ phát
hiện ra các hậu quả (các kết quả không mong muốn). Quá trình sửa lỗi bao gồm “phân
loại lỗi”, “cô lập lỗi” (tìm ra nguyên nhân và nơi gây lỗi), đề ra “giải pháp sửa lỗi” và
cuối cùng là khắc phục lỗi.
                          Hình 1. Vòng đời của kiểm chứng
             Lỗi                                                   Sửa lỗi

         Mô tả yêu cầu                                      Giải pháp sửa lỗi
                              Lỗi
         Sai sót

            Thiết kế                                    Cô lập lỗi
                                     Lỗi
              Sai sót
                        Lập trình                 Phân loại lỗi

                                                     Hậu quả
                         Sai sót
                                    Kiểm chứng

I.4. Mô hình kiểm chứng

     Những thảo luận của chúng ta phần lớn dựa vào việc kiểm chứng các chương trình
độc lập trong đang hoàn chỉnh của nó. Tuy nhiên, điều này không phải là một loại kiểm
chứng tự động, cũng không phải là cách kiểm chứng một chương trình trong lúc xây dựng.
Nó cũng không là cách hiệu quả nhất để kiểm chứng các thành phần nhỏ ẩn trong các thành
phần lớn hơn.

     Để kiểm chứng một bộ phận độc lập, ta cần phải tạo ra một số loại mô hình để cung
cấp đầy đủ sự hỗ trợ cũng như các giao tiếp cho tất cả các phần có liên quan của hệ thống
mà việc kiểm chứng được thực hiện. Như chúng ta đã trình bày một ví dụ nhỏ để kiểm
chứng việc tìm kiếm nhị phân ở phần đầu.
                                                                                         7
Nguyên lý ngôn ngữ lập trình – Kiểm chứng chương trình
      Thật dễ dàng xây dựng một mô hình để kiểm chứng các hàm toán học, các hàm liên
quan đến chuỗi, các hàm sắp xếp…, vì việc tạo mô hình bao gồm phần lớn sự thiết lập
các tham số đầu vào, gọi các hàm sẽ được kiểm chứng, sau đó kiểm chứng kết quả.
Nhưng để tạo ra một mô hình để kiểm chứng từng phần của một chương trình hoàn chỉnh
thì quả thật là một việc tốn nhiều thời gian và công sức.

      Để minh họa, ta sẽ xây dựng một kiểm chứng cho hàm memset, một trong những
hàm liên quan đến bộ nhớ trong thư viện chuẩn của C/C++. Những hàm này thường được
viết bằng hợp ngữ cho từng loại máy khác nhau bởi vì sự thực hiện của chúng rất quan
trọng. Tuy nhiên, nếu chúng càng được thực hiện cẩn thận thì chúng lại càng sai do vậy
chúng cần được kiểm chứng một cách kỹ lưỡng.

     Bước đầu tiên là cung cấp những phiên bản C đơn giản nhất cớ thể chạy được;
những phiên bản này cho thấy một sự đánh giá cho việc thực thi và quan trọng hơn là tính
chính xác. Khi chuyển sang một môi trường mới chỉ lấy sang những phiên bản đơn giản
và chúng chỉ được dùng khi đã được hiệu chỉnh chơ phù hợp.

      Hàm memset(s, c, n) gán ký tự c vào n byte trong bộ nhớ bắt đầu từ đầu địa chỉ s, trả
về s. Hàm này được thực hiện dễ dàng nếu không chú ý tới tốc độ:

     /* Hàm memset: gán kí tự c vào n byte đầu tiên của s */

     void *memset (void *s , int c, size_t n)

     {

         size_t i ;

         char *p;

         p = (char *) s ;

         for ( i = 0 , i < n; i++ )

         p [ i] = c;

     return s ;

     }
                                                                                        8
Nguyên lý ngôn ngữ lập trình – Kiểm chứng chương trình
     Nhưng khi quan tâm đến vấn đề tốc độ thì những mẹo như viết đầy đủ các word 32
hoặc 64 bit tại cùng thời điểm được sử dụng. Những điều này có thể gây ra lỗi vì thế bắt
buộc phải có những kiềm chứng tổng quát.

      Việc kiểm chứng dựa trên sự kết hợp toàn diện và kiểm tra điều kiện biên tại những
nơi dễ gây ra lổi. Đối với hàm memset, biên của nó bao gồm các giá trị hiển nhiên của n
như 0, 1, 2 nhưng cũng bao gồm các giá trị là lũy thừa của hai hoặc những giá trị lân cận,
bao gồm các giá trị nhỏ và lớn như 216, nó thích hợp với giá trị biên tự nhiên của nhiều
máy một word có 16 bit. Lũy thừa của hai cần được chú ý bởi vì một cách để làm cho
hàm memset thực hiện nhanh hơn là gán nhiều byte cùng lúc, điều này được thực hiện
bằng các lệnh đặc biệt hoặc bằng cách lưu một word tại một thời điểm thay vì chỉ lưu một
byte. Một cách tương tự, ta muốn kiểm tra mảng với những cách sắp xếp khác nhau trong
trường hợp có lổi phát sinh dựa trên địa chỉ bắt đầu hoặc chiều dài mảng. Ta sẽ đặt mảng
đích vào trong một mảng có kích thước lớn hơn, nhờ đó tạo ra một vùng đệm hoặc một
vùng an toàn trên mỗi chiều và chỉ ra một cách dễ dàng để thay đổi cách sắp xếp.

      Ta cũng muốn kiểm chứng nhiều giá trị của c, bao gồm 0, 0x7F (giá trị có dấu lớn
nhất), 0x80 và 0xFF (tìm những lỗi tiềm ẩn có thể liên quan đến các ký tự có dấu và
không dấu), và các giá trị lớn hơn một byte (để chắc chắn chỉ có một byte được sử dụng).
Ta cũng cần phải khởi tạo bộ nhớ theo vài giá trị khác những giá trị đó để có thể kiểm tra
hàm memset có ghi ra ngoài vùng hợp lệ hay không.

      Chúng ta có thể dùng một sự cài đặt đơn giản như một tiêu chuẩn so sánh trong việc
kiểm chứng hai mảng, sau đó so sánh các sự thực hiện trên sự kết hợp của n, c và offset
(đia chỉ tương đối) trong mảng:

     big = maximum left margin + maximum n + maximum right margin

     so = malloc (big)

     s1 = malloc (blg)

     for each combination of test parameters n, c and offset:

      set all of s0 and s1 to know pattern

      run slow memset (s0 + offset, c, n)

      run fast memset ( sl + offset , c, n)

      check return values
                                                                                           9
Nguyên lý ngôn ngữ lập trình – Kiểm chứng chương trình
        compare all of s0 and s1 byte by byte

     Một lỗi gây ra do hàm memset là ghi bên ngoài giới hạn của mảng thì ảnh hưởng
đến những byte ở vị trí bắt đầu hoặc kết thúc của mảng, vì vậy dành ra vùng đệm để dễ
dàng phát hiện những byte hư hỏng và để phát hiện ra lỗi ghi đè lên một số phần khác của
chương trình. Để kiểm chứng việc ghi ra ngoài giới hạn đã định, ta so sánh tất cả các byte
của s0 và s1 chứ không chỉ n byte cần ghi.

       Như vậy, tập các kiểm chứng hợp lệ phải bao gồm tất cả các kết hợp sau:

        offset = 10 , 11, ..., 20

        c = 0 , 1, 0x7F, 0x80, 0xFF, 0x1122334 4

n = 0 , 1, 2 , 3, 4 , 5, 7, 8 , 9, 15 , 16, 17, 31, 32, 33, ..., 65535, 65536, 65537

       Giá trị của n bao gồm ít nhất 2i - 1, 2, 2i + 1 với i từ 0 đến l6.

      Những giá trị này không cần phải kết với phần chính của mô hình kiểm tra, nhưng
nó cần xuất hiện trong mảng được tạo mốt cách thủ công hay bằng chương trình. Phát
sinh ra chúng một cách tự động sẽ tốt hơn: điều này làm cho dễ định rõ các luỷ thừa của
hai hoặc có được nhiều địa chỉ offset và nhiều ký tự hơn.

      Những kiểm chứng này làm cho hàm memset làm việc một cách đúng đắn, tốn ít thời
gian để tạo ra, thực hiện độc lập, vì có khoảng 3500 trường hợp cho các giá trị ở trên. Những
kiểm chứng này có thể mang chuyển được, vì vậy chúng ta có thể chuyển nó sang một môi
trường khác nếu cần thiết.

     Những hàm như memset có thể có được các kiểm chứng một cách toàn diện vì
chúng đơn giản đến nỗi một người có thể chứng minh rằng tất cả trường hợp kiểm chứng
có thể được thực hiện thông qua mã nguồn, vì thế nó có thể được kiểm chứng một cách
hoàn chỉnh. Chẳng hạn như, có thể kiểm chứng hàm memmove trong mọi cách kết hợp
chồng chéo, theo hướng, và theo hàng. Ta không có được sự kiểm chứng toàn diện trong
trường hợp phải kiểm chứng tất cả những thao tác sao chép có thể, nhưng đó là sự kiểm
chứng toàn diện đối với mỗi loại khác nhau của dữ liệu nhập.

I.5. Phẩm chất của một chương trình

Các chương trình phần mềm khi được phát triển và đưa vào ứng dụng thực tế cần phải đạt
được những phẩm chất cơ bản sau:
   -    Tính đúng đắn, chính xác (Correctness)
                                                                                      10
Nguyên lý ngôn ngữ lập trình – Kiểm chứng chương trình
    -   Tính chắc chắn (robustness)
    -   Tính thân thiện với người dùng (User friendliness)
    -   Khả năng thích nghi (adapability):chương trình phần mềm có khả năng thích ứng
        và tiến hóa theo yêu cầu chung phù hợp với thực tế đưa ra.
    -   Tính tái sử dụng (reuseability): chương trình có thể dùng để làm một phần trong
        một chương trình khác lớn hơn.
    -   Tính tương liên (Interoperability)
    -   Tính hiệu quả (efficiency)
    -   Tính khả chuyển (porability): có khả năng chuyển đổi dễ dàng giữa các môi
        trường phát triển khác nhau.
    -   Tính an toàn hệ thống (Security).
Ngoài 9 phẩm chất trên còn có phẩm chất quan trọng nữa là tính dừng của chương trình.
Năm 1985-1986 LENARD nói rằng “ Không thể tồn tại một chương trình kiểm tra tính
dừng của một chương trình”.
I.6. Các phương pháp kiểm chứng chương trình :

I.6.1. Cấu trúc kiểm tra chương trình :

Các phương thức chính để kiểm tra tính đúng đắn của chương trình bao gồm :

- Kiểm chứng toàn bộ các nhánh rẽ của chương trình. Sao cho mỗi lệnh của chương trình
  đều phải qua ít nhất một lần (Black-Box).
- Tạo bộ dữ liệu thử nghiệm ngẫu nhiên để phát hiện ra lỗi giả hay lỗi thật.
- Kiểm tra ỡ những điểm nút
- Chèn các lệnh kiểm tra logic ở mỗi đoạn chương trình.(White -Box)
I.6.2. Tính đúng đắn của chương trình :
Khi chương trình thực hiện mà xảy ra sai sót thì có rất nhiều nguyên nhân nhưng có 3
  nguồn gốc xảy rai sót chính là:
- Dữ liệu đầu vào: do dữ liệu nhập vào ban đầu thiếu tính ràng buộc nên sẽ xảy ra sai sót
  khi thực hiện khi đó để kiểm chứng thì dùng bộ kiểm tra dữ liệu ngẫu nhiên, hay đặc
  trưng tuỳ ý.
- Cú pháp : Dùng trình biên dịch để phát hiện
- Ngữ nghĩa: Lỗi này rất khó phát hiện dùng test logic, Heuristic test để kiểm tra.
Mỗi chương trình đều có ràng buộc về tính đúng đắn đối với điều kiện input đầu vào.
x,P(x) :     điều kiện đối với x
Q(y):         điều kiện đối với y
Ta có : P(x)^Program(x,y) Q(y)
                                                                                 11
Nguyên lý ngôn ngữ lập trình – Kiểm chứng chương trình


               x,P(x)                                           Q(y)




                 Input:x                  Program(x,y)          Output:y



     Ví dụ 1 :

Kiểm chứng chương trình giải phương trình bậc 2

Ta có phân tích sơ đồ kiểm chứng như sau:
                                                           X1,x2:Q(ax12+bx1+c=0,a
                 a,b,c,P(a,b,c                                x22+bx2+c=0)
                 ): b2-4ac>=0

                                               Program
                   Input: a,b,c             (ax2+bx+c=0)         Output: x1,x2



Ví dụ 2 :
Kiểm chứng tính đúng đắn của chương trình tính thương và dư số a/b với chương trình
  như sau:
r:=a;q:=0;
While r>b do
   Begin
        r:=r-1;
        q:=q+1;
   end;
Kết quả: q: là thương số, r : là dư số.

Kiểm tra :
- Điều kiện của phép chia b<>0. Nếu b=0 vòng lặp sẽ không dừng được dẫn đến chương
  trình sai.
                                                                                       12
Nguyên lý ngôn ngữ lập trình – Kiểm chứng chương trình
- Các cận : với a=b dẫn đến kết quả sai vì dứ số r=x và thương q=0.
Chương trình đúng được viết lại như sau :


r:=a;q:=0;
        While r>=b do
  Begin
       r:=r-1;
       q:=q+1;
  end;

I.6.3. Tính chắc chắn của chương trình

Cần phân tích chương trình thành các chương trình con sao cho tính độc lập giữa các
   chương trình con càng cao càng tốt.
Ví dụ :
i :=n
While i>0 do
   Begin
         Read(a[i]);
         i:=i-1;
   end;
for j:=1 to n do
   i:=i+a[j];
writeln(‘tong so=’,i);

Chương trình sẽ thực hiện sai nếu n<0 do biến i được dùng chung cho cả hai vòng lặp.
I.6.4. Kiểm chứng chương trình với mô hình nghịch đảo
Để kiểm tra tính logic của chương trình ta có thể sử dụng phương pháp nghịch đảo để
  kiếm chứng lại tính đúng đắn thực tế của chương trình:
Ví dụ 1: Thuật toán nhân Ấn Độ được phát triển như sau:
Input: x,y
Output: z=x*y
Thuật Toán :

Nhập x,y
  If x le then
         z=y;
  Else
  z=0
                                                                               13
Nguyên lý ngôn ngữ lập trình – Kiểm chứng chương trình
End if
While x>1 do
   Begin
        x:=x div 2;
        y:=y*2;
        If x lẻ then z:=z+y;
   End;
z:=z+y;
Để kiểm chứng chương trình trên ta lập trình lại và chèn thêm dòng lệnh kiểm chứng
   nghịch đảo để kiểm chứng chương trình như sau :

  Promgram nhan_ando ;
  var
  x,y,k,m,n :word ;
  BEGIN
  repeat write(‘nhap gia tri x=’) ;readln(x) until x>=0 ;
  repeat write(‘nhap gia tri y=’) ;readln(y) until y>=0 ;
  m :=x ;
  n :=y ;
  if (x mod 2)=1 then k:=y; else k :=0 ;
  if y<>0 then
  begin
         while x>1 do
                begin
                       x :=x shr 1 ;
                       y :=y shl 1 ;
                       if ((x mod 2)=1) then k :=k+y ;
                end ;
                k :=k+y ;
                writeln(‘x*y=’,k) ;
  (* chèn thêm đoạn lệnh kiểm chứng*)
         if ((k/n)=m) and ((k/m)=n) then
                write(‘Thuat toan dung’) ;
         else
                writeln(‘thuat toan sai !’) ;
readln ;
end ; (* END OF IF*)
END ;

I.6.5. Kiểm chứng chương trình dùng phương pháp quy nạp.
Phương pháp này dựa vào phương pháp chứng minh quy nạp trong toán học. được phát
  biểu như sau :
                                                                                   14
 Nguyên lý ngôn ngữ lập trình – Kiểm chứng chương trình
Để chứng minh một tân từ P(n) phụ thuộc vào số tự nhiên là đúng với mọi n. thì ta cần
  chứng minh hai điều sau đây :
(i)     P(0) là đúng.
(ii)    Nếu P(n) được giả định là đúng thì sẽ suy ra P(n+1) cũng đúng.

Khẳng định P(0) được gọi là cơ sở và bước chứng minh (ii) là bước quy nạp. Khi đã có
  hai điều chứng minh (i) và (ii), đựa vào nguyên lý quy nạp toán học ta kết luận P(n)
  đúng với mọi số tự nhiên n.
Ngoài ra còn có phương pháp chứng minh quy nạp mạnh được phát biểu như sau :
Để chứng minh P(n) đúng với mọi số tự nhiên ta chứng minh hai điều sau :
(i) P(0) đúng
(ii)    Nếu giả định là P(0),P(1),...P(n) đều đúng thì P(n+1) cũng đúng.

Ví dụ 1 :

Đầu vào là x,y,n để có đầu ra là x=x.yn ta viết đoạn chương trình tính như sau :
while n<>0 do
begin
  x :=x*y ;
  n :=n-1 ;
end ;
        ketqua :=x ;

Hãy chứng minh đoạn chương trình trên thực hiện viết. đúng ý đồ của người
  Xét vị từ S(n) cho đoạn chương trình sau :
  ‘’ x,y  R, n  N : nếu đầu vào là x,y,n thì đầu ra là : x=x*yn ‘’
Ta chứng minh bằng nguyên lý quy nạp :
Khi n=0 thì vòng lặp không thực hiện được, ketqua cua đoạn chương trình là x, vậy S(0)
  đúng.
Ta giả sử S(k) đúng, tức đầu ra là x=x*yk
Ta cần chứng minh S(k+1) đúng :
Thật vậy do k>=0 ==> k+1>0 nền vòng lặp sẽ thực hiện ít nhất là thêm 1 lần nữa suy ra
  x=x*y=x*yk*y = x=yk+1 nghĩa là S(k+1) đúng
Vậy đoạn chương trình trên là đúng với ý đồ của người lập trình.

Ví dụ 2 :
                                                                                    15
Nguyên lý ngôn ngữ lập trình – Kiểm chứng chương trình
Đầu vào là x,y,n để có đầu ra là x=x+n*y ta viết đoạn chương trình như sau :
While n<>0 do
begin
  x :=x+y ;
  n :=n-1 ;
  end ;
  ketqua :=x ;

Hãy chứng minh đoạn chương trình trên đúng với ý đồ của người viết.
  Ta xét vị từ S(n) cho đoân chương trình trên như sau :
        ‘’  x,y  R, n  N : nếu đầu vào là x,y,n thì đầu ra là : x=x+n*y ‘’
  Chứng minh bằng quy nạp :
Với n=0 thì vòng lặp không thực hiện được chương trình thực hiện có kết quả = x+0*y=x
  vậy S(0) đúng.
Ta giả sử S(k) đúng tức đầu ra của đoạn chương trình là x=x+k*y.
Ta cần chứng minh S(k+1) đúng.
Thật vập do k>=0 ==> k>0 nên vòng lặp sẽ thực hiện thêm ít nhất là một lần nữa suy ra
  x=x+y=x+k*y+y=x+(k+1)*y nghĩa là S(k+1) đúng.
Vậy đoạn chương trình trên là đúng với ý đồ của người viết.
Đối tượng của những phương pháp kiểm chứng logic là tìm ra những bằng chứng tổng
quát sao cho bạn không cần theo dõi hết mọi điều kiện có thể. Thực hiện điều này liên
quan đến một vài dạng đại diện logic bằng biểu tượng và các kỹ thuật thực hiện những
phép suy luận logic. Một trong những kỹ thuật mạnh nhất cho mục đích này là phương
pháp toán học gọi là phép qui nạp. Phương pháp này áp dụng cho những biểu thức logic
với những tham số nguyên. Nó có tình trạng như sau :
1. Nếu biểu thức f (n) có thể được chứng minh là đúng đối với một giá trị n0 nào đó
2. Khi n > n0 và khi f (n) đúng, f (n + 1) cũng được chứng minh là đúng
3. Thì f (k) đúng với mọi k >= n0
   Sử dụng khái niệm này có thể tiết kiệm nhiều thời gian trong kiểm tra logic. Bạn bắt
   đầu bằng cách chứng minh rằng logic của một chương trình (ở đây là một biểu thức
   logic) là đúng cho trường hợp cơ bản. Sau đó bạn chứng minh rằng nếu logic này đúng
   cho một giá trị n lớn hơn nào đó thì nó cũng đúng cho n + 1, điều này là một bằng
   chứng đầy dủ cho mọi giá trị lớn hơn của n và bạn không cần tìm thêm một bằng chứng
   nào nữa.
Đây là một nguyên lý mạnh mẽ, nó phải được quan tâm sử dụng. Giả sử rằng bạn đang
  thực hiện một vòng lặp như sau:


    For i = 1 to 1000
                                                                                        16
Nguyên lý ngôn ngữ lập trình – Kiểm chứng chương trình
    BEGIN
       Do x y z
    END

  Nếu bạn kiểm tra và chứng thực rằng logic hợp lý ở những giá trị i = 1 , i =5 , i = 6 bạn
  có thể kết luận rằng nó đúng với mọi giá trị cao hơn của i. Tuy nhiên rõ ràng ở đây có
  một vấn đề khi mà i = 1001. Bài toán ở đây là cách mà kiểm chứng được thực hiện. Sau
  khi cho rằng logic là đúng ở i = 1, kế đến bạn cần kiểm tra trường hợp i = n. Bạn cho
  rằng logic là đúng khi giá trị i = n, nó cũng đúng cho i = n + 1. Chú ý rằng bạn không
  có chứng minh nó đúng cho i = n ; bạn giả sử điều này. Khảo sát bài toán, bạn có thể
  thấy rằng logic sẽ không làm việc khi n = 1000. Để tránh điều này bạn nên thực hiện
  cuộc kiểm tra với logic được sửa đổi như sau:


For i = 1 to limit
 BEGIN
  Do x y z
 END

  Đầu tiên bạn chứng thực rằng hàm logic đúng ở limit = 1 ; kế đến bạn chứng minh rằng
  nếu đúng với limit = n thì nó cũng đúng cho limit = n + 1. Khi đó nó cũng đúng với mọi
  giá trị cao hơn của limit. Ở đây n là một giá trị nguyên dương. Lại nữa bạn cũng cần
  bảo đảm rằng không có những giá trị phi số trong hàm xyz nó có thể làm sai lệch các
  cuộc thực nghiệm này. Một cách khác để tiếp cận nguyên lý này là xem có thể tìm thấy
  bất kỳ một giá trị n hay không, nơi mà chương trình thì đúng ở limit = n nhưng không
  đúng ở limit n + 1. Những vấn đề như thế được gây nên bởi những ràng buộc về bộ nhớ
  hoặc là kích thước của hệ thống số


I.6.6.Thực hiện bằng biểu tượng
Logic sau đây đưa ra bởi Mills cho thấy thực hiện bằng biểu tượng làm việc như t hế nào
  trong trường hợp đơn giản


Procedure Substitution (V1, V2, V3, V4)
 BEGIN
  V1 : = V2 ;
  V2 : = V4 ;
  V3 : = V1 ;
  V4 : = V3 ;
 END
                                                                                       17
Nguyên lý ngôn ngữ lập trình – Kiểm chứng chương trình
  Bảng sau cho ta kết quả. Logic này trông đơn giản nhưng logic đơn giản này dường như
  trở thành rất phức tạp khi nó liên quan đến tiến trình tuần tự. Ưu điểm của kiểm chứng
  bằng biểu tượng là nó bao phủ hết tất cả giá trị đặc trưng hơn là một số các trường hợp
  được test

        Chu kỳ              Function: Substitution (V1, V2, V3, V4)
        # Lệnh              V1           V2            V3           V4
           Trị khởi động    A            B             C            D
        1 V1 : = V2         B
        2 V2 : = V4                      D
        3 V3 : = V1                                    B
        4 V4 : = V3                                                 B
           Giá trị sau      B            D             B            B
              cùng

  Không có những hướng dẫn tổng quát nào cho việc là khi nào và làm thế nào để sử
  dụng sự thực thi bằng biểu tượng, tuy nhiên bạn nên kiểm tra chương trình của mình và
  sử dụng điều này trong bất kỳ trường hợp nào mà bạn thấy trong thực tế. Một trong
  những điểm hay nhất của những phương pháp kiểm chứng bằng toán học là nó cung cấp
  một cách được cấu trúc hóa để kiểm chứng một chương trình một cách logic.


I.6.7. Chứng thực đối tượng state machine
  Khi mà sản phẩm của bạn có một state machine, bạn nên chứng minh rằng nó được
  thiết kế một cách hợp lý và sử dụng một cách đúng đắn .Để quyết định một chương
  trình có là state machine hay không cần kiểm tra hành xử bên ngoài của nó. Một ví dụ
  là hành xử của bộ đọc ký tự đối với bộ đếm .Bộ đọc sẽ gửi tất cả ký tự tới bộ đếm.Tuy
  nhiên, khi nó phát hiện bắt đầu một dòng chú thích, nó sẽ bỏ qua tất cả những ký tự
  theo sau cho đến cuối dòng chú thích. Ở đây thì bộ đọc ký tự có hai trạng thái: dòng chú
  thích và dòng chương trình. Với những ký tự rõ ràng là input, trong một trường hợp nó
  không tạo ra output và trong trường hợp còn lại nó sẽ gởi các ký tự input ra output, khi
  một state machine được thiết kế đúng đắn thì nó phải có khả năng trả ra cho chương
  trình những trạng thái mà mọi điều kiện trạng thái phải đầy đủ và trực giao với nhau,
  bạn nên kiểm tra những ngữ cảnh lớn hơn của chương trình để đảm bảo rằng tất cả các
  state machine được định ra rõ ràng và được sử dụng một cách nhất quán.
  Người ta định nghĩa một tập các hàm là đầy đủ nghĩa là hội của mọi thành viên là đúng.
  Ví dụ như là một tập đầy đủ các hàm sẽ phủ mỗi hình vuông trên một bảng đồ
  Kanaugh. Một tập hàm gọi là trực giao nghĩa là mọi phần giao của các thành viên là
  rỗng hoặc bằng zero. Một tập các hàm trực giao không gối chồng lên nhau trên bảng đồ
  Kanaugh. Do đó, với một tập trực giao các chuyển dịch về trạng thái, mỗi một chuyển
                                                                                          18
Nguyên lý ngôn ngữ lập trình – Kiểm chứng chương trình
  dịch là duy nhất và không có sự nhầm lẫn về trạng thái kế tiếp. Để kiểm tra điều này thì
  một state machine thì thích hợp hơn và theo những bước như sau :
 Kiểm tra cấu trúc của state machine để bảo đảm rằng không có những cái bẫy tìm ẩn
  hoặc các vòng lặp để nó không thể dính vào trong một vòng lặp vô hạn nào đó và không
  bao giờ trả về cho ta một tình trạng được
 Kiểm tra thiết kế chương trình để bảo đảm rằng mọi tình trạng có thể được phân định
  rõ. Nó có đầy đủ hay không ? Một thiết kế chương trình là đầy đủ khi mà một trạng thái
  được định nghĩa cho mỗi cái nối kết có thể của những giá trị thuộc tính.
 Kiểm tra tính trực giao của tình trạng, đó là, đối với mọi tập các điều kiện thì chỉ có duy
  nhất một và chỉ một trạng thái có thể
 Kiểm chứng rằng các chuyển dịch từ mỗi trạng thái là đầy đủ và trực giao, đó là, từ mỗi
  một trạng thái một tình trạng duy nhất kế tiếp được định nghĩa cho mọi nối kết có thể
  của những giá trị input
  Hai phần sau đây sẽ cho ta những ví dụ làm thế nào để kiểm tra tính đúng đắn của state
  machine. Thứ nhất là state machine đơn giản Bset, thứ hai là Cdata


       Kiể m tra Bset và State Machine :

       Mẫu mô tả Bset được cho như sau :




                           Pop or Subtract


                             Empty State


   Push or Add                                          Pop ( n = 1) or
                                                        Subtract ( n = 1 và D thuộc Bset )

                             Member State
                                n>0



                         Add or Push or Pop ( n >1 ) or
                         Subtract ( D không thuộc Bset ) or
                         Subtract ( n >1 )
                                                                                        19
Nguyên lý ngôn ngữ lập trình – Kiểm chứng chương trình




      Dòng trên cùng mô tả trạng thái rỗng và 2 dòng ngay bên dưới cho trạng thái kế từ
      trạng thái rỗng
      Khi Bset là Empty State các thủ tục Pop hoặc Subtract được gọi.
      Dòng kế tiếp Member State, chỉ ra rằng khi Bset trong trạng thái Empty sẽ trở thành
      Member State khi hoặc là Push hoặc là Add được gọi.
      Trong Member State, điều kiện thì phức tạp hơn một chút. Member State sẽ trở
      thành Empty khi thủ tục Pop được gọi và chỉ có một thành phần duy nhất trong
      Bset ( n = 1). Nó cùng kết thúc trong Empty State khi Bset có một thành viên D và
      thủ tục Subtract được gọi với tham số D


           Empty State               Tập không có thành viên           n=0
               Empty State           Pop ( & D )  Subtract ( D )
               Member State          Push ( D )  Add ( D )
           Member State              Tập có 1 hoặc nhiều thành viên n >= 1
               Empty State           Pop ( & D )  ( n = 1 ) 
                                     [ ( Subtract ( D )  ( n = 1 )  D  Bset ) ]
                Member State         Push ( D )  Add ( D )  [ Pop ( & D )  ( n
                                     > 1) ] 
                                     [ Subtract ( D )  D Bset ]  [ Subtract ( D
                                     )  (n>1)]

      Các phương thức được trình bày như sau
     Push ( D ) : thêm tập D vào Bset ở vị trí thứ nhất, đẩy mọi thành viên đang tồn tại
      lên 1 vị trí
     Pop ( D ) : xóa từ vị trí đầu tiên của Bset, đặt vào trong D, và di chuyển mọi thành
      viên trong Bset xuống 1 vị trí
     Add ( D ) : nếu D không là thành viên của Bset, Push ( D )
     Subtract ( D ) : nếu D là thành viên của Bset, xóa nó và giảm đi một vị trí của
          tất cả thành viên cao hơn của Bset
      Để kiểm tra xem State machine có hoạt động tốt hay không hãy hỏi các câu hỏi sau
      đây
 1.   Bset có ẩn chứa vòng lặp hay không ?
 2.   Bset có là State machine đầy đủ không ?
      Đối với Bset chỉ có một thuộc tính mà ta quan tâm là n : số các thành viên trong
                                                                           20
Nguyên lý ngôn ngữ lập trình – Kiểm chứng chương trình
    Bset
    Có 2 trạng thái của Bset là N = 0 và n >= 1
 3. Các trạng thái của Bset có trực giao hay không ?
    Rõ ràng là trực giao vì không thể có n = 0 và n  0 đồng thời
    Các chuyển dịch từ mỗi trạng thái có đầy đủ và trực giao hay không ?




            Kiểm tra các bẫy tiềm ẩn hoặc các vòng lặp
                                                                                 21
Nguyên lý ngôn ngữ lập trình – Kiểm chứng chương trình




                                                 1
                                 EmptySet
                                 List State = = 0
                                 List Position = = 0



                                    6            2
                     1
                     1           First and Only
                                 List State = = 1
                             7   List Position = = 1


                                                                           2
                                        12       8
            1                                                              1
            6                                                      2
                                 First of Several                  2
                                 List State = = 2      1
                                 List Position = = 1
                                                       3


                         1
                         4              1        2
                                        8        3

        Middle of Several                                  List of Several
        List State = = 3                    20             List State = = 4
                                                           List Position = = N    25
 19     1 < List Position <
        N
                                            24
                                                                                         22
Nguyên lý ngôn ngữ lập trình – Kiểm chứng chương trình




Hình vẽ này được xây dựng từ mẫu trạng thái và trình bày mỗi chuyển dịch trong số các
trạng thái.
Ví dụ : EmptySet chuyển dịch tới First & Only theo điều kiện 2. Điều kiện 2 xảy ra khi
hoặc là phương thức Push hoặc AddSet được gọi.
Hình trên cũng cho ta thấy rằng State machine này không có bẫy hoặc các vòng lặp tiềm
ẩn, nó có thể ở bất kỳ trạng thái nào và chuyển tới bất kỳ trạng thái khác.
Ví dụ từ trạng thái LastOfSeveral có thể đến EmptySet theo điều kiện 21. Tương tự trạng
thái Empty State có thể chuyển dịch tới LastOfSeveral bởi dãy input 2, 8, 15.


I.6.8. Kiể m tra mọi trạ ng thái có thể
Kiểm tra mọi trạng thái có thể liên quan việc phân định tất cả các điều kiện có thể của hệ
thống. State machine liên quan đến tập dữ liệu chứa một số thành viên và một pointer trỏ
đến một trong các thành viên này.
Trong ví dụ State machine, chỉ có 5 trạng thái là có ích đối với chương trình đang được
thiết kế. Những trạng thái này là hệ thống có không, một hoặc vài số thành viên lớn hơn
và các pointer không trỏ đến gì cả, đến thành viên đầu tiên hoặc thành viên ở giữa, hoặc
thành viên cuối cùng. Các trạng thái là như sau:


EmptySet , ListState = 0 ; pointer không trỏ gì cả vì vậy ListPosition = 0
First & Only , ListState = 1 ; chỉ duy nhất một thành viên, pointer phải trỏ đến nó, vì vậy
ListPosition = 1
First of Several , ListState = 2 ; có một vài thành viên, pointer trỏ đến cái đầu tiên, vì
vậy ListPosition = 1
Middle of Several , ListState = 3 ; khi pointer trỏ đến thành viên ở giữa, phải có ít nhất 3
cái. Do đó listpointer lớn hơn 1 và bé hơn N, với N là số thành viên trong tập hợp
LastOfSeveral , ListState = 4 ; phải có 2 hoặc nhiều thành viên hơn với pointer trỏ đến
cái cuối cùng, vì vậy ListPosition = N
 I.6.9. Kiểm tra tính trực giao của trạng thái
Để xác định trạng thái là trực giao, bạn cần xác định 2 trạng thái bất kỳ tồn tại dưới cùng
một tham số. Bằng cách kiểm tra giá trị của ListState và ListPosition, bạn có thể thấy
rằng giá trị của ListState là duy nhất cho mỗI một kết nối của N và các tham số
ListPosition. Vậy thì, với mọi kết nối của N và ListPosition có một và chỉ một giá trị
ListState. Trạng thái như thế gọi là trực giao
                                                                                     23
Nguyên lý ngôn ngữ lập trình – Kiểm chứng chương trình




I.7. Quy trình kiểm chứng

     Quy trình kiểm chứng một chương trình được thực hiện qua nhiều bước, nhiều công
đoạn và có trò rất quan trọng đến kết quả của việc kiểm chứng. Vì vậy cần phải biết tại
mỗi bước cần kiểm chứng cái gì và kết quả muốn làm gì. Cho nên chúng ta phải thực
hiện một cách có thứ tự và lưu lại những việc đã làm để biết kết quả đã làm được những
gì.

I.7.1. Kiểm chứng tăng dần
     Việc kiểm chứng cần phải đi đôi với việc xây dựng chương trình. Một người viết
toàn bộ chương trình sau đó mới kiểm chứng tất cả sẽ gặp nhiều khó khăn và tốn nhiều
thời hơn cách tiếp cận tăng dần. Viết một phần của chương trình, kiểm chứng nó, viết
thêm mã nguồn, kiểm chứng nó và cứ tiếp tục như vậy. Nếu có hai phần được viết và
kiểm chứng độc lập, và khi tích hợp chúng với nhau chúng ta chỉ cần kiểm tra chúng có
hoạt động tốt với nhau không.

     Chẳng hạn như, khi ta kiểm chứng chương trình nào đó, bước đầu tiên là viết mã
nguồn vừa đủ để đọc giá trị nhập vào: điều này cho phép xử lý thực hiện dữ liệu nhập vào
một cách đúng đắn. Bước tiếp theo là chia các dòng dữ liệu nhập này tại dấu phẩy. Khi
những phần này hoạt động, ta chuyển sang xử lý phần trích dẫn, và dần dần tiến tới kiểm
chứng mọi thứ.

I.7.2. Kiểm chứng những phần đơn giản trước
      Cách tiếp cận tăng dần cũng được áp dụng để kiểm chứng các tính năng của chương
trình. Việc kiểm chứng cần phải tập trung vào những phần đơn giản và những phần
thường được thực hiện nhất của chương trình; chỉ khi chúng thực thi đúng mới chuyển
sang phần khác. Bằng cách này, ở mỗi giai đoạn, nên đưa ra nhiều phần hơn để kiểm
chứng và xây dựng với sự tin tưởng rằng nó sẽ hoạt động tốt. Những kiểm chứng đơn
giản sẽ giúp tìm ra những lổi đơn giản. Mỗi lần kiểm chứng góp phần tìm ra lỗi tiềm ẩn
tiếp theo. Mặc dù khó phát hiện các lỗi về sau hơn nhưng việc sửa lỗi không hẳn là khó
hơn.

    Trong phần này, ta sẽ chọn những biện pháp kiểm chứng hiệu quả và thứ tự áp dụng
chúng. Giả sử rằng ta có một hàm thực hiện việc tìm kiếm nhị phân trên một mảng các số
                                                                                        24
Nguyên lý ngôn ngữ lập trình – Kiểm chứng chương trình
nguyên. Ta sẽ bắt đầu với những kiểm chứng sau, được sắp xếp theo mức độ phức tạp
tăng dần:

     - Tìm kiếm trên mảng không có phần tử nào.

     - Tìm kiếm trên mảng chỉ cớ một phần tử và giá trị cần tìm:

         + Nhỏ hơn phần tử duy nhất của mảng.

         + Bằng phần tử duy nhất.

         + Lớn hơn phần tử duy nhất.

     - Tìm kiếm trên mảng có hai phần tử và một giá trị cần tìm:

         + Kiểm tra tất cả năm vị trí có khả năng.

     - Kiểm tra việc thực hiện trên mảng gồm hai phần tử giống nhau và giá trị cần tìm:

         + Nhỏ hơn giá trị trong mảng.

         + Bằng giá trị trong mảng.

         + Lớn hơn giá trị trong mảng.

     - Tìm kiếm trên mảng có ba phần tử tương tự như với hai phần tử.

     - Tìm kiếm trên mảng cớ bốn phần tử tương tự như với hai, ba phần tử.

     Nếu những kiểm chứng được thực hiện mà chương trình không có lỗi phát sinh thì
có vẻ chương trình này chạy tốt nhưng nó vẫn cần được kiểm chứng nhiều hơn nữa.

      Vì tập hợp những kiểm chứng này nhỏ nên ta có thể tiến hành thủ công, nhưng tốt
hơn là nên tự động hỏa quy trình này. Ta có thể quản lý chương trình điều khiển đơn
giản. Nó đợi vào các dòng dữ liệu nhập bao gồm một khóa để tìm kiếm và kích thước của
mảng. Đồng thời, nó sẽ tạo ra một mảng có kích thước đã cho chứa các giá trị 1, 3, 5, . . .
và thực hiện việc tìm khóa trên mảng này.

     /* Hàm main của việc kiểm chứng hàm tìm kiếm nhị phân */

     int main (void)

     {

     int i, key, nelem, arr [1000];
                                                                                       25
Nguyên lý ngôn ngữ lập trình – Kiểm chứng chương trình
     While ( scanf ( “%d %d”, &key, &nelem) != EOF {

         for ( i = 0 ; i < nelem, i++ )

         arr[i] = 2*i + 1;

         printf ( “%d\n”, Binsearch (key, arr, nelem) ) ;

         }

     return 0;

     }

      Điều này thật đơn giản nhưng nó cho thấy rằng việc thực hiện tự động thì hữu ích
không phải cồng kềnh, và dễ dàng mở rộng về sau để thực hiện các kiểm chứng tương tự,
và ít đòi hỏi con người can thiệp hơn.

I.7.3. Biết trước dữ liệu xuất
     Trong tất cả các kiểm chứng, cần phải biết kết quả đúng là gì; nếu không thì thật là
lãng phí thời gian. Điều này dường như hiển nhiên, bởi vì trong nhiều chương trình, thật
dễ dàng để xét xem chương trình có làm việc hay không. Chẳng hạn như, thao tác sao
chép, một tập tin thực hiện việc sao chép một tập tin hoặc không, dữ liệu xuất của một
hàm sắp xếp có được sắp xếp hoặc không.

      Quả thật là khó khăn để chỉ ra đặc điểm của hầu hết các chương trình trình biên dịch
(dữ liệu đầu ra có thực sự biên dịch đúng dữ liệu đầu vào không?), các thuật toán số học
(kết quả có chứa những lối có thể bỏ qua hay không?), đồ họa (các pixel có ở đúng vị trí
của nó không?)... Vì những lý do này, để đảm bảo dữ liệu xuất đúng ta thực hiện so sánh
chúng với các giá trị đã biết.

     - Để kiểm chứng một trình biên dịch, ta cần biên dịch và thực thi các tập tin thử
nghiệm. Chương trình thử nghiệm ngược lại sẽ phát sinh các dữ liệu xuất, và các kết quả
này sẽ được so sánh với những kết quả đã biết.

      - Để kiểm chứng một chương trình số học, ta phát sinh các trường hợp thử nghiệm
bao quát mọi trường hợp của thuật toán, từ những trường hợp đơn giản cho đến các
trường hợp phức tạp. Nếu có thể, bạn viết đoạn chương trình để kiểm tra tính đúng đắn
các thuộc tính của dữ liệu xuất. Chẳng hạn như, giá trị xuất của một phép tính tích phân
có thể được kiểm tra tính liên tục, và tính bị chặn của nó.
                                                                                     26
Nguyên lý ngôn ngữ lập trình – Kiểm chứng chương trình
      - Để kiểm chứng một chương trình đồ họa, nếu ta chỉ kiểm tra xem chương trình có
thể vẽ một hình hộp hay không thì chưa đủ, thay vào đó ta phải đọc từ màn hình và kiểm
tra xem các cạnh của không có nằm đúng vị trí hay không.

      Nếu một chương trình có khả năng thực hiện theo chiều ngược lại cần kiểm tra rằng
nó có thể khôi phục lại giá trị nhập hay không. Mã hóa giải mã là hai quá trình ngược
nhau, vì vậy nếu có thể thực hiện mã hóa nhưng lại không thể giải mã được thì chứng tỏ
có điều gì đó sai đã xảy ra. Tương tự, thuật toán nén không mất thông tin và giải nén là
ngược nhau. Nhờ đó sau khi nén tập tin thì vẫn có thể giải nén tập tin đúng với ban đầu
tập tin. Đôi khi có nhiều phương pháp đảo ngược; cần phải kiểm tra tất cả các trường hợp
này.

I.7.4. Kiểm chứng các thuộc tính Iưu trữ
       Nhiều chương trình dành lưu trữ các tính chất của dữ liệu nhập. Những công cụ như
wc (đếm số hàng, số từ, số ký tự) và sum (tính tổng) có thể kiểm chứng được các dữ liệu
xuất có cùng kích thước, có cùng số từ có các byte giống nhau theo một thứ tự nào đó.
Những chương trình so sánh các tập tin (cmp) hoặc đưa ra sự khác nhau của các tập tin
(diff). Các chương trình này và các chương trình tương tự thích hợp với hầu hết các môi
trường, và thu được kết quả tốt.

      Một chương trình tuần tự theo byte có thể được dùng để kiểm tra sự lưu trữ dữ liệu
và cũng để phát hiện những sự khác thường như những ký tự phi văn bản trong những tập
tin văn bản. Sau đây là một phiên bản của chương trình freq:

     #include <stdio . h>

     #include <ctype . h>

     #include <limits . h>

     unsigned long count [UCHAR_MAX + 1] ;

     /* Hàm min của freq: hiển thị tần xuất theo từng byte */

     int main (void)

     {

     int c;

     while ( ( c = getchar ( ) ) != EOF)
                                                                                      27
Nguyên lý ngôn ngữ lập trình – Kiểm chứng chương trình
         count [c] ++;

     for (c = 0; c <= UCHAR_MAX; c++)

         if (count [c] ! = 0)

         printf ( “%.2x      %c %lu\n”, c, isprint (c) ? c:

         ‘-’, count [c] );

     return 0;

     }

      Các thuộc tính lưu trữ cũng có thể được kiểm tra bên trong một chương trình. Một
hàm đếm các thành phần trong cấu trúc dữ liệu sẽ cho phép kiểm tra tính nhất quán giản
đơn. Một bảng băm có thuộc tính là mỗi phần tử sau khi thêm vào bảng băm đều có thể
truy xuất trở lại được. Ta có thể dễ dàng kiểm tra điều kiện này bằng cách tạo một hàm
sao chép nội dung của bảng băm vào một tập tin hay một mảng. Tại bất kỳ thời điểm nào,
số lượng các phần tử thêm vào trong cấu trúc dữ liệu trừ cho số lượng phần tử bị xoá bỏ
phải bằng với số lượng phần tử hiện có trong cấu trúc dữ liệu đó. Ta dễ dàng kiểm tra
được điều kiện này.

I.7.5 . So sánh các quá trình cài đặt độc lập
      Các quá trình cài đặt độc lập của một thư viện hay của một chương trình phải cho ra
cùng kết quả. Chẳng hạn như, trong hầu hết các trường hợp, hai trình biên dịch sẽ phải
tạo ra các chương trình hoạt động giống nhau trên cùng một máy.

      Đôi khi một kết quả có thể được tính theo hai cách khác nhau, hoặc bạn có thể viết
một phiên bản bình thường của chương trình sử dụng phép so sánh chậm nhưng thực hiện
độc lập. Nếu hai chương trình độc lập cho ra cùng kết quả thì có thể khẳng định cả hai
chương trình đó đều đúng; nhưng nếu hai chương trình đó cho ra các kết quả khác nhau
thì có ít nhất một chương trình bị sai.

I.7.6. Kiểm tra tính bao quát của việc kiểm chứng
      Một mục tiêu của kiểm chứng là đảm bảo mọi câu lệnh trong chương trình đều được
thi hành tại một thời điểm nào đó trong suốt quá trình kiểm chứng; việc kiểm chứng
không thể xem là hoàn tất nếu mỗi dòng của chương trình chưa được kiểm tra ít nhất một
lần. Tính bao quát hoàn toàn thường khó đạt được. Ngay cả khi bỏ qua các trường hợp
                                                                                       28
Nguyên lý ngôn ngữ lập trình – Kiểm chứng chương trình
“không thể xảy ra”, việc sử dụng các dữ liệu nhập thông thường để buộc chương trình
thực hiện các câu lệnh nào đó cũng gặp nhiều khó khăn.

      Có một số phần mềm thương mại dùng để đo lương tính bao quát. Nó cung cấp cách
tính tần xuất thực hiện của mỗi câu lệnh trong chương trình, và cho biết tính bao quát
trong các lần kiểm chứng cụ thể.

I.8. Giới thiệu về 2 phương pháp white box và black box :


      Một chương trình đều có thể được kiểm chứng theo 2 cách:

      - Hiểu rõ cách hoạt động của một hàm/ module hay sản phẩm. Các trường hợp kiểm
chứng có thể được xây dựng để đảm bảo tất cả các thành phần con khớp với nhau. Đó là
tất cả các thao tác nội bộ của hàm dựa vào các mô tả và tất cả các thành phần nội bộ đã
được kiểm chứng một cách thoả đáng.
                                                           Hình 2. White box testing
     - Hiểu rõ một chức năng cụ thể của một hàm hay
một module. Các trường hợp kiểm chứng có thể xây
dựng để kiểm tra tất cả các thao tác đó.

      Cách tiếp cận thứ nhất gọi là kiểm chứng hộp
trắng (white box testing). “White box” là kỹ thuật tập
trung kiểm tra trên cầu trúc điều kiển của chương
trình, các trường trường hợp kiểm chứng được tạo ra
có thể đảm bảo tất cả các câu lệnh được viết trong
chương trình được thực thi ít nhất một lần trong quá trình kiểm chứng và rằng tất cả các
điều kiện logic trong trương trình cũng đã được kiểm chứng trong đó. Cách tiếp cận thứ
hai được gọi là kiểm chứng hộp đen (black box testing). Trong khi “white box” được mô
tả như là một phương pháp kiểm chứng trên diện nhỏ và là một phương pháp tiêu biểu để
kiểm chứng các thành phần nhỏ của chương trình như module, hay những nhóm nhỏ
các module thì “black box” lại tập trung vào hướng kiểm chứng trên diện rộng, các
trường hợp được thiết kế tập trung phân tích/ phân mãnh vùng thông tin đầu vào và đầu
ra của chương trình.

      Khi đề cập đến kiểm chứng chương trình, “black
box testing” còn được biết như là kiểm chứng ở mức giao
diện (interface). Mặc dù khả năng hoạt động của hàm hay
module thật sự thì chúng được thiết kế để phát hiện lỗi.
                                                                                       29
Nguyên lý ngôn ngữ lập trình – Kiểm chứng chương trình
Black box testing còn được sử dụng để chứng minh chương trình và có thể cả một
chương trình lớn: các thông số đầu vào được chấp nhận như mô tả của hàm, giá trị trả về
cũng hoạt động tốt, đảm bảo các dữ liệu từ bên ngoài ví dụ như file dữ liệu được giữ/
đảm bảo tính nguyên vẹn của dữ liệu khi thực thi hàm.

     Trong khi đó, “white box testing” là kỹ thuật tập trung vào khảo sát chặt chẻ thủ tục
một cách chi tiết. Tất cả những đường diễn tiến logic trong chương trình được kiểm tra
bằng những trường hợp kiểm chứng kiểm tra trên các tập điều kiện và cấu trúc lặp cụ thể.
Kỹ thuật này sẽ kiểm tra trạng thái của chương trình tại rất nhiều điểm trong chương trình
nhằm xác giá trị mong đợi tại các điểm nay có khớp với giá trị thực tế hay không.

     Với những cách thức kiểm chứng trên thì kỹ thuật “white box testing” có lẽ sẽ dẫn
đến một chương trình chính xác tuyệt đối.




II. Thực nghiệm kiểm chứng chương trình :

II.1. Trường hợp đơn giản
                                                                                      30
Nguyên lý ngôn ngữ lập trình – Kiểm chứng chương trình
       Bạn muốn biết đọan mã lệnh có thực hiện hay không ? Làm sao kiểm chứng điều
  này? Có rất nhiều cách. Sử dụng kỹ thuật bẫy lỗi (debug) hay chạy từng bước để kiểm
  tra kết quả từng đọan chương trình. kỹ thuật bẫy lỗi là ý tưởng khá hay nhưng lại
  không tự động kiểm tra, bạn phải thực hiện mỗi khi có sự thay đổi. Kỹ thuật chạy
  từng bước cũng tốt nhưng nó làm cho đọan mã lệnh không được dễ nhìn và hơn hết là
  kết quả đưa ra có nhiều thông tin dư thừa.


       Kiểm chứng bằng CppUnit có thể thưc hiện tự động, dễ cài đặt và bạn chỉ phải
  viết một lần. Kiểm chứng bằng CppUnit giúp bạn thấy tự tin về chất lượng đọan mã
  lệnh
  Để thực hiện việc kiểm chứng, tất cả những gì bạn phải làm là tạo 1 lớp con
  TestCase, được Override phương thức runTest(). Khi bạn muốn kiểm tra, gọi
  CPPUNIT_ASSERT(bool) và truyền vào biểu thức cần kiểm tra. Nếu kết quả trả về
  là True thì việc kiểm chứng thành công.


  Đây là một ví dụ cho việc kiểm chứng so sánh hai số phức:
  Class ComplexNumberTest: public CppUnit::TestCase {
  Public:
       ComplexNumberTeast (std::string name) : CppUnit::TestCase(name) {}
       Void runTest() {
             CPPUNIT_ASSERT (Complex (10,1) ==Complex(10,1));
             CPPUNIT_ASSERT (!Complex (1,1) ==Complex(2,2));
       }
  };


  Như bạn thấy, chương trình trên rất đơn giản. Tuy nhiên thường ta cần kiểm chứng
  nhiều trường hợp nhỏ và ta muốn kiểm chứng trên cùng một tập các đối tượng. Để
  thực hiện điều này ta sử dụng Fixture
                                                                                         31
Nguyên lý ngôn ngữ lập trình – Kiểm chứng chương trình
       1. Fixture


       Fixture là một tập các đối tượng mà phục vụ cho lớp Test case cơ sở. Fixture sẽ
  đảm bảo chắc chắn khi bạn kiểm chứng


       Chúng ta sẽ khảo sát mẫu này. Giả sử chúng ta thực sự muốn phát triển một lớp số
  phức. Chúng ta bắt đầu bằng việc định nghĩa lớp Complex rỗng như sau:


              Class Complex ();


       Bây giờ chúng ta sẽ tạo một thể hiện của lớp ComplexNumberTest ở trên, biên
  dịch, chạy và xem kết quả. Trước tiên, chúng ta sẽ thấy lỗi biên dịch. Chương trình
  test sử dụng tóan tử ==, nhưng chưa định nghĩa. Chúng ta sẽ sửa như sau:


  Bool operato == (const Complex &a, const Complex &b)
  {
       Return true;
  }


       Bây giờ, biên dịch lại và chạy. Lúc này bạn sẽ không thấy lỗi biên dịch nữa.
  Chúng ta cần thêm một chút vào operator == như sau:


  Class Complex {
       Friend bool operator == (const Complex &a, Const Complex &b
       Double real, imaginary;
  Public:
       Complex (double r, double i=0): real (r), imaginary (i) {}
  };
  Bool operator== (const Complex &a, const Complex &b)
                                                                                     32
Nguyên lý ngôn ngữ lập trình – Kiểm chứng chương trình
  {
      Return a.real== b.real && a.imaginary == b.imaginary;
  }


  Chúng ta biên dịch lại và việc kiểm chứng của chúng ta đã xong.
      Tiếp theo chúng ta thêm một phép toán mới và kiểm chứng và ta làm như sau:
             Thêm biến cho mỗi phần của fixture
             Override setUp() để khởi tạo biến
             Override tearDown() để giải phóng bất cứ tài nguyên nào đang tồn tại
                 trong setUp()


  Class ComplexNumberTest: public CppUnit::TestFixture{
      Private:
             Complex *m_10_1, *m_1_1, *m_11_2;
      Public:
             Void setUp()
             {
             m_10_1 = new Complex(10,1);
             m_1_1= new Complex(1,1);
             m_11_2 = new Complex (11,2);
             }
             void tearDown ()
             {
                     delete m_10_1;
                     delete m_1_1;
                     delete m_11_2 ;
             }
                                                                    33
Nguyên lý ngôn ngữ lập trình – Kiểm chứng chương trình
  }


      2. Test Case


  Làm thế nào để gọi kiểm chứng sử dụng fixture? Có hai bước
             Viết testcase như là phương thức trong lớp fixture
             Tạo một TestCaller mà chạy như phương thức ngoại lệ
  Đây là một ví dụ testcase:


  Class ComplexNumberTest: public CppUnit::TestFixture {
      Private:
             Complex *m_10_1, *m_1_1, *m_11_2;
      Public:
             Void setUp()
             {
             m_10_1 = new Complex(10,1);
             m_1_1= new Complex(1,1);
             m_11_2 = new Complex (11,2);
             }
             void tearDown ()
             {
                     delete m_10_1;
                     delete m_1_1;
                     delete m_11_2 ;
             }
             void testEquality ()
             {
                     CPPUNIT_ASSERT (*m_10_1== *m_10_1);
                     CPPUNIT_ASSERT (!(*m_10_1)==*m_11_2);
                                                                                      34
Nguyên lý ngôn ngữ lập trình – Kiểm chứng chương trình
              }
              void testAdditiion()
              {
                     CPPUNIT_ASSERT (*m_10_1 + *m_1_1== *m_11_2);
              }
  };


  Ta tạo và chạy những thể hiện cho mỗi testcase giống như sau:


  CppUnit::TestCaller<ComplexNumber> tests (“testEquality”,
  &ComplexNumberTest::testEquality);
  CppUnit::TestResult result;
  Test.run (&result);


       Tham số thứ hai trong TestCaller là địa chỉ của phương thức
  ComplexNumberTest. Khi chương trình chạy, phương thức đặc tả sẽ chạy. Điều này
  thì không có ích lắm, tuy nhiên kết quả phân tích không hiển thị. Thường sử dụng
  TestRunner để hiển thị kết quả


       3. Suite


       Làm sao cài đặt chương trình test của bạn để mà bạn có thể chạy chúng tất cả chỉ
  một lần ? CppUnit cung cấp 1 lớp TestSuite mà chạy với bất kỳ số TestCases
  Chúng ta đã khảo sát cách chạy một chương trình testcase đơn giản


  Để tạo một bộ gồm 2 hay nhiều bộ test, ta làm như sau:
  CppUnit::TestSuite suite;
  CppUnit::TestResult result;
                                                                                      35
Nguyên lý ngôn ngữ lập trình – Kiểm chứng chương trình
  Suite.addTest (new CppUnit::TestCaller<ComplexNumberTest> (“testEquality”,
  &ComplexNumberTest::testEquality));
  Suite.addTest(new CppUnit::TestCaller<ComplexNumberTest>(“testAddition”,
  &ComplexNumberTest::testAddition));
  Suite.run (&result);


     TestSuite không chỉ bao gồm lời gọi hàm TestCases.Chúng có thể chứa bất kỳ đối
  tượng mà được cài đặt ở mức giao diện (interface) Test. Ví dụ, bạn có thể tạo một
  TestSuite trong đoạn mã lệnh của bạn và tôi có thể tạo TestSuite trong đoạn mã lệnh
  của tôi, và chúng ta có thể chạy cùng nhau bởi việc tạo một TestSuite chứa cả hai như
  sau:
  CppUnit::TestSuite suite;
  CPPUnit::TestResult result;
  Suite.addTest(ComplexNumberTest::suite());
  Suite.addTest(SurrealNumberTest::suite());
  Suite.run (&result);


     4. TestRunner


     Làm sao bạn chạy chương trình test của bạn và thu thập các kết quả đó? Mỗi khi
  bạn có một test suite, bạn muốn chạy nó. CppUnit cung cấp công cụ cho phép bạn
  định nghĩa suite để chạy và hiện thị kết quả. Bạn tạo một suite để truy cập vào chương
  trình TestRunner với phương thức tĩnh làa suite để trả về một test suite.
  Ví dụ, để tạo một suite ComplexNumber tới TestRunner, thêm đoạn code sau vào
  ComplexNumberTest:
  Public :
     Static : CppUnit::Test *suite()
     {
                                                                                36
Nguyên lý ngôn ngữ lập trình – Kiểm chứng chương trình
             CppUnit::TestSuite *suiteOfTests = new CppUnit::TestSuite
   (“ComplexNumberTest”);
      suiteOfTests -> addTest(new
   CppUnit::TestCaller<ComplexNumberTest>(“testEquality”,&ComplexNumberTest::t
   estEquality));
      suiteOfTests->addTest (new
   CppUnit::TestCaller<ComplexNumberTest>(“testAddition”,
   &ComplexNumberTest::testAddition));
      return suiteOfTests;
      }


      Để sử dụng lại, ta include tập tin TestRunner.h vào tập tin Main.cpp
      #include <cppunit/ui/text/TestRunner.h>
      #include “ExampleTestCase.h”
      #include “ComplexNumberTest.h”
      Và thêm lời gọi hàm addTest(CppUnit::Test *) trong hàm main ()
      Int main (int argc, char **argv)
      {
             CppUnit::TextUi::TestRunner runner;
             Runner.addTest (ExampleTestCase::suite());
             Runner.addTest(ComplexNumberTest::suite());
             Runner.run ();
             Return 0;
      }


      TestRunner sẽ chạy đoạn kiểm chứng. Nếu tất cả chạy qua, bạn sẽ nhận được một
thông báo. Ngựơc lại, bạn sẽ nhận được những thông báo sau:
      Tên của test case sai
      Tên của tập tin nguồn chứa kiểm chứng
                                                                                         37
Nguyên lý ngôn ngữ lập trình – Kiểm chứng chương trình
      Dòng bị lỗi
      Nội dung trong CPPUNIT_ASSERT sẽ hiển thị
      CppUnit phân biệt giữa failures và errors. Faiure là những lỗi có thể đoán, còn
error thì không đoán trứơc được. Ví dụ như lỗi chia cho 0 là dạng error.


      5. Helper Macros


   Như ta đã thấy, phương thức suite() được lặp đi lặp lại, kết xuất được tạo tự động.
Đoạn mã lệnh sau viết lại phương thức ComplexNumberTest
   #include <cppunit/extensions/HelpMacros.h>
   Class ComplexNumberTest: public CppUnit::TestFixture {}


   Trước hết, ta khai báo suite, gửi tên lớp vào marco
   CPPUNIT_TEST_SUITE (ComplexNumberTest);


   Suite được tạo từ phương thức site() có tên sau tên lớp. Sau đó, chúng ta sẽ khai báo
   cho mỗi test case của fixture:
   CPPUNIT_TEST (testEquality);
   CPPUNIT_TEST (testAddition);
   Cuối cùng, chúng ta khai báo:
   CPPUNIT_TEST_SUITE_END();


   Tại thời điểm này, phương thức sau đã được cài đặt:
   Static CppUnit::TestSuite *suite();


   Phần còn lại của fixture thì không thay đổi:
   Private:
              Complex *m_10_1, *m_1_1, *m_11_2;
   Public:
                                                                                      38
Nguyên lý ngôn ngữ lập trình – Kiểm chứng chương trình
  Void setUp()
  {
  m_10_1 = new Complex(10,1);
  m_1_1= new Complex(1,1);
  m_11_2 = new Complex (11,2);
  }
  void tearDown ()
  {
       delete m_10_1;
       delete m_1_1;
       delete m_11_2 ;
  }
  void testEquality ()
  {
       CPPUNIT_ASSERT (*m_10_1== *m_10_1);
       CPPUNIT_ASSERT (!(*m_10_1)==*m_11_2);
  }
  void testAdditiion()
  {
       CPPUNIT_ASSERT (*m_10_1 + *m_1_1== *m_11_2);
  }
  };


  Tên của TestCaller thêm vào suite là sự kết hợp của tên fixture và tên của phương
  thức.
  Lúc này, tên của fixture là : “ComplexNumberTest.testEquality” và của phương thức
  là “ComplexNumberTest.testAddition”
                                                                                     39
Nguyên lý ngôn ngữ lập trình – Kiểm chứng chương trình
  Helper Macros giúp bạn viết xác nhận chung chung. Ví dụ, để kiểm tra
  ComplexNumber thông qua MathException khi chia cho 0:
  Thêm một trường hợp bằng việc sử dụng CPPUNIT_TEST_EXCEPTION, đặc tả loại
  exception này


  Viết một phương thức kiểm tra
  CPPUNIT_TEST_SUITE (ComplexNumberTest);
  //{...}
  CPPUNIT_TEST_EXCEPTION (testDivideByZeroThrows, MathException);
  CPPUNIT_TEST_SUITE_END();
  // {...}
  void testDivideByZeroThrows()
  {
      // Hàm sau nên gửi qua MathException
      *m_10_1/ComplexNumber(0);
  }
  Nếu exception không được thực thi thì sự xác nhận sẽ hiển thị lên.


      6. TestFactoryRegistry


      TestFactoryRegistry dùng để giải quyết 2 lỗi:
  Quên thêm fixture site vào Test runner
  Giải quyết sự cố “tắc nghẽn cổ chai” khi include tất cả các test case vào header
  TestFactoryRegistry được khai báo nơi có thể được đăng ký tại thời điểm khởi tạo


  Để đăng ký ComplexNumber, trong tập tin .cpp, thêm vào:
  #include <cppunit/extensions/HelperMacros.h>
  CPPUNIT_TEST_SUITE_REGISTRATION (ComplexNumberTest);
                                                                                        40
Nguyên lý ngôn ngữ lập trình – Kiểm chứng chương trình
   Khi đó biến AutoRegisterSuite được khai báo, trong constructor, nó sẽ đăngký
   TestSuiteFactory vào TestsFactoryRegistry. TestSuiteFactory trả về TestSuite trong
   ComplexNumber::suite()


   Để chạy kiểm chứngn, sử dụng Test Runner, chúng ta không cần phải include nữa
   #include <cppunit/extensions/TestFactoryRegistry.h>
   #include <cppunit/ui/text/TestRunner.h>
   int main (int argc, char **argv)
   {
       CppUnit::TestUi::TestRunner runner;
   }


   Trứơc hết, chúng ta truy cập thể hiện của TestFactoryRegistry:
   CppUnit::TestFactoryRegistry &registry =
   CppUnit::TestFactoryRegistry::getRegistry();
   Sau đo, chúng ta thêm TestSuite bởi TestFactoryRegistry mà chứa tất cả những kiểm
   chứng bằng việc sử dụng CPPUNT_TEST_SUITE_REGISTRATION()
   Runner.addTest(registry.makeTest());
   Runner.run ();
   Return 0;


       7. Post- build check


Bây giờ, chúng ta có chương trình kiểm chứng. Việc tích hợp modul này vào tiến trình
buid thì sao? Để làm điều này, ứng dụng phải trả về một giá trị khác 0 để chỉ ra một lỗi.
TestRunner::run() trả về TRUE nếu thành công.
Cập nhật lại chương trình chính như sau:
   #include <cpp/extensions/TestFactoryRegistry.h>
   #include <cppunit/ui/text/TestRunner.h>
                                                                                     41
Nguyên lý ngôn ngữ lập trình – Kiểm chứng chương trình
   int main (int argc, char **argv)
   {
        CppUnit::TestUi::TestRunner runner;
        CppUnit::TestFactoryRegistry & registry =
   CppUnit::TestFactoryRegistry::getRegistry();
        Runner.addTest (registry.makeTest());
        Bool wasSuccessful = runner.run(“”, false);
        Return wasSuccefull;
   }
Bây giờ, sau khi biên dịch chúng ta có thể chạy ứng dụng
Với Visual C++, làm điều này trong Project Ssetting/Post-Build step bằng cách thêm vào
dòng lệnh sau: example/cppunittest/CppUnitTestMain.cpp


III. Kế t luậ n
      Kiểm chứng là quá trình để đảm bảo chất lượng phần mềm và ngày càng đóng vai
trò quan trọng trong toàn bộ qui trình phát triển phần mềm. Để sản phẩm hoàn thiện, hoạt
động ổn định và đúng mục tiêu đề ra thì qui trình kiểm nghiệm là không thể xem nhẹ.

      Có nhiều hướng tiếp cận để kiểm chứng phần mềm và các phương pháp này ngày
càng được phát triển và mang tính khoa học. Qua bài viết này tác giả đã tập hợp những
nét chính, cũng như nghiên cứu, phân tích các kỹ thuật, các quy trình kiểm chứng phần
mềm nổi bật đang được sử dụng và phát triển hiện nay. Từ đó có thể ứng dụng trong qui
trình tạo ra sản phẩm phần mềm.

       Một quy tắc cơ bản của việc kiểm chứng là hãy thực hiện kiểm chứng!
                                                                                  42
Nguyên lý ngôn ngữ lập trình – Kiểm chứng chương trình
    Tài Liệu Tham Khảo


             [1] Bài thu hoạch nguyên lí và phương pháp ngôn ngữ lập trình – Kiểm
chứng (do giảng viên cung cấp )


             [2] Hoàng Văn Kiếm, Giáo trình chuyên đề Nguyên lý và phương pháp
ngôn ngữ lập trình, Đại học Công nghệ thông tin TP. Hồ Chí Minh, 2006.




              [3] Lê Hoài Bắc, Nguyễn Thanh Nghị, Kỹ năng lập trình, NXB. Khoa học
và kỹ thuật, 2005.


             [4] Software Testing and Quality Control - Knowledge Bases,
http://www.compinfo-center.com/tpsw12-t.htm



            [5] Bài báo cáo về đề tài nguyên lí lập trình 1 - Lê Hùng - Vũ Thế Hiển -
      Nguyễn Đình Hiền - Phạm Đào Minh Vũ - Trương Quang Bình Long



            [6] Guideline_Software Testing - FPT

				
DOCUMENT INFO
Shared By:
Categories:
Tags:
Stats:
views:75
posted:6/27/2012
language:Vietnamese
pages:42