• Khi XD 1 CT lớn, 1 LTV chuyên nghiệp sẽ dành thời gian cho việc viết test code không ít hơn tg dành cho viết bản thân CT • LTV chuyên nghiệp là người có khả năng, kiến thức rộng về c
Trang 11
Trang 2• Khi XD 1 CT lớn, 1 LTV chuyên nghiệp sẽ
dành thời gian cho việc viết test code
không ít hơn tg dành cho viết bản thân CT
• LTV chuyên nghiệp là người có khả năng,
kiến thức rộng về các kỹ thuật và chiến
lược testing
Trang 3Testing and debugging
• Testing & debugging i cùng v i nhau nh 1 c p: đ ớ ư ặ
• Testing tìm errors; debugging định vị và sửa chúng.
• Ta có mô hình “testing/debugging cycle”:
Ta test, rồi debug, rồi lặp lại.
• Bất kỳ 1 debugging nào nên được tiếp theo
là 1 sự áp dụng lại của hàng loạt các tests liên quan, đặc biệt là các bài tests hồi quy Điều này giúp tránh nảy sinh các lỗi mới khi debugging
• Testing & debugging không nên được thực hiện bởi cùng 1 người (thường là không nên).
Trang 4i và k t qu th c t
Trang 5Right/WrongSpecification
?
Trang 6ProbablyRight/WrongSpecification
Trang 7External vs Internal Testing
Trang 8External Testing
• External testing: TK d li u ữ ệ để test CT
(1) Kiểm chứng giá trị biên : Boundary
testing
(2) Kiểm chứng lệnh : Statement testing
(3) Kiểm chứng có hệ thống : Path testing
(4) Stress testing
Trang 9Boundary Testing
(1) Boundary testing
• “Là kỹ thuật kiểm chứng sử dụng các giá trị nhập vào ở trên hoặc dưới một miền giới hạn của 1 đầu vào và với các giá
trị đầu vào tạo ra các đầu ra ở biên của
1 đầu ra.”
‒ Glossary of Computerized System and Software Development Terminology
• Còn g i là ki m tra i u ki n biên- ọ ể đ ề ệ corner case testing
• H u h t các l i ầ ế ỗ đề u x y ra các i u ki n biên - boundary ả ở đ ề ệ
conditions
• N u CT làm vi c k biên, nó s làm vi c úng v i các k khác ế ệ ở đ ẽ ệ đ ớ đ
Trang 10Boundary Testing Example
• VD : đọ c 1 dòng t stdin và ừ đư a vào m ng ký t ả ự
• Boundary conditions
• Dòng rỗng -Input starts with '\n'
• In ra empty string (“\0”) => in ra “||” , ok
• Nếu gặp EOF - End of file trước '\n‘
• Ti p t c g i getchar() và l u ế ụ ọ ư ӱ vào s[i]
• Nếu gặp ngay EOF (empty file)
• Ti p t c g i getchar() và l u ế ụ ọ ư ӱ vào s[i]
Trang 11Boundary Testing Example (cont.)
• Boundary conditions (tt)
• Dòng chứa đúng MAXLINE-1 ký tự
• In ra úng, v i ‘\0’ t i s[MAXLINE-1] đ ớ ạ
• Dòng chứa đúng MAXLINE ký tự
• Ký t cu i cùng b ghi è, và dòng m i không bao gi c ự ố ị đ ớ ờ đ đọ c
• Dòng dài hơn MAXLINE ký tự
Trang 12Boundary Testing Example (cont.)
• Rewrite the code
• Another boundary condition: EOF
• What are other boundary conditions?
s[i] = '\0';
for (i=0; i<MAXLINE-1; i++)
if ((s[i] = getchar()) == '\n' || s[i] == EOF) break;
s[i] = '\0';
This is wrong
Why?
Trang 13Boundary Testing Example (cont.)
Where’s the ‘d’?
for (i=0; ; i++) { int c = getchar();
if (c==EOF || c=='\n' || i==MAXLINE-1) {
s[i] = '\0';
break;
} else s[i] = c;
}
Trang 14Ambiguity in Specification
• N u dòng quá dài, x lý th nào? ế ử ế
lại?
cho lần gọi sau của input function?
• Có th ph n ể ầ đặ ả c t - specification không h ề đề ậ c p khi MAXLINE b quá ị
trong mọi trường hợp
Trang 15V n ấ đề đạ o đứ c
• Ph c t p, các tr ứ ạ ườ ng h p ranh gi i l n x n th ợ ớ ộ ộ ườ ng là
tri u ch ng c a vi c thi t k t i hay mô t ệ ứ ủ ệ ế ế ồ ả đặ đ ể c i m k ỹ
thu t t i ậ ồ
• Xóa b ỏ đặ ả ế c t n u b n có th ạ ể
• N u không th s a specification, thì hãy s a code ế ể ử ử
Trang 16Ki m tra k tr ể đ ướ c và k sau đ
• Xác nh nh ng thu c tính c n i tr đị ữ ộ ầ đ ướ c ( k tr đ ướ c) và sau ( k sau) mã ngu n đ ồ
c thi hành
đ
• Ví d : các giá tr ụ ị đầ u vào ph i thu c 1 ph m vi cho tr ả ộ ạ ướ c
double avg( double a[], int n) {
int i; double sum=0.0;
for ( i = 0; i<n; i++)
sum+=a[i];
return sum/n;
}
N u n=0 ?, n u n<0 ? ế ế
Có th thay : return n <=0 ? 0.0: sum/n; ể
Tháng 11/1998, chi n h m Yorktown b chìm : nh p vào giá tr 0, Ct không ki m tra ế ạ ị ậ ị ể
dl nh p d n ậ ẫ đế n chia cho 0, và l i làm t u r i lo n, h th ng ỗ ầ ố ạ ệ ố đẩ y ng ng ho t ư ạ
ng, tàu chìm !!!
độ
Trang 17Statement Testing
(2) Statement testing
• “Testing để thỏa mãn điều kiện rằng mỗi statement trong 1 CT phải thực hiện ít
nhất trong khi testing.”
‒ Glossary of Computerized System and Software
Development Terminology
Trang 18statement2;
…
if (condition2) statement3;
Trang 19Path Testing
(3) Path testing
• “Kiểm tra để đáp ứng các tiêu chuẩn đảm bảo rằng
mỗi đường dẫn logic xuyên suốt chương trình được
kiểm tra Thường thì đường dẫn xuyên suốt chương
trình này được nhóm thành một tập hữu hạn các lớp Một đường dẫn từ mỗi lớp sau đó được kiểm tra "
‒ Glossary of Computerized System and Software Development Terminology
• Khó h n nhi u so v i statement testing ơ ề ớ
• Với các CT đơn giản, có thể liệt kê các
nhánh đường dẫn xuyên suốt code
• Ngược lại, bằng các đầu vào ngẫu nhiên tạo các đường dẫn theo ct
Trang 20Path Testing Example
• Example pseudocode:
• Đ òi h i 4 t p d li u: ỏ ậ ữ ệ
•condition1 là true và condition2 là true
•condition1 là true và condition2 là false
•condition1 là false và condition2 là true
•condition1 là false và condition2 la false
• Ch ươ ng trình th c t => bùng n các t h p!!! ự ế ổ ổ ợ
if (condition1) statement1;
else
statement2;
…
if (condition2) statement3;
Trang 214 5
Trang 22F B<0T
Trang 23Consider ANOTHER example…
T
T
B<0
Trang 24Stress Testing
(4) Stress testing
thống hay thành phần tại hoặc vượt quá các
‒ Glossary of Computerized System and Software Development Terminology
• Ph i t o : ả ạ
• Một tập lớn đầu vào - Very large inputs
• Các đầu vào ngẫu nhiên - Random inputs (binary vs ASCII)
• Nên dùng máy tính để ạ đầ t o u vào
Trang 25Stress Testing Example 1
Stress testing: Ph i cung c p ả ấ
random (binary and ASCII)
inputs
Trang 26Stress testing: Ph i cung c p ả ấ
very large inputs
Trang 27Uses of assert
• Typical uses of assert
• Validate formal parameters
• Check for “impossible” logical flow
• Make sure dynamic memory allocation requests worked
assert(ptr != NULL);
size_t Str_getLength(const char *str) { assert(str != NULL);
… }
switch (state) { case START: … break;
case COMMENT: … break;
… default: assert(0); /* Never should get here */ }
Trang 28Internal Testing
• Internal testing: Thi t k CT ế ế để CT t test itself ự
(1) Kiểm tra bất biến - Testing invariants (2) Kiểm tra các thuộc tính lưu trữ
-Verifying conservation properties (3) Kiểm tra các giá trị trả về -Checking function return values
(4) Tạm thay đổi code -Changing code
temporarily (5) Giữ nguyên mã thử nghiệm -Leaving
testing code intact
Trang 29Testing Invariants
(1) Testing invariants
thay đổi
tra các bất biến ở đầu và cuối nó
• Ki m tra ể ở đầ u và cu i ố
• Xoay doubly-linked list
• Khi node x tr ng ỏ ượ ạ c l i node y, thì li u node y có tr ng ệ ỏ ượ ạ c l i node x?
function
• Ki m tra ể ở đầ u và cu i ố
• Xoay tree
Trang 30Testing Invariants (cont.)
#ifndef NDEBUG
int isValid (MyType object) {
…
Test invariants here.
Return 1 (TRUE) if object passes
all tests, and 0 (FALSE) otherwise.
Trang 31Ki m tra các thu c tính l u tr ể ộ ư ữ
• Khái quát hóa của testing invariants
• 1 hàm cần kiểm tra các cấu trúc dữ liệu bị tác động tại các điểm đầu và cuối
• T i i m ạ đ ể đầ u, tìm độ dài c a 2 xâu ã cho; tính t ng ủ đ ổ
• T i i m cu i, tìm ạ đ ể ố độ dài c a xâu k t qu ủ ế ả
• 2 độ dài có b ng nhau không ? ằ
-List insertion function
• T i i m kh i ạ đ ể ở đầ u, tính độ dài ds
• T i i m cu i, Tính ạ đ ể ố độ dài m i ớ
• Độ dài m i = ớ độ dài c + 1?ũ
Trang 32• Ph ươ ng th c b phát hi n có l i có th tung ra m t “checked exception” ứ ị ệ ỗ ể ộ
• Ph ươ ng th c tri u g i ph i x lý ngo i l ư ệ ọ ả ử ạ ệ
• Không có c ch x lý exception ơ ế ử
• Hàm phát hi n có l i ch y u thông qua giá tr tr v ệ ỗ ủ ế ị ả ề
• Ng ườ i LT th ườ ng d dàng quên ki m tra GT tr v ễ ể ả ề
• Nói chung là chúng ta nên ki m tra GT tr v ể ả ề
Trang 33Checking Return Values (cont.)
trị đc đọc
ra file và đĩa bị đầy; Hàm này trả
về số ký tự được ghi ( không phải
giá trị)
int i;
if (scanf("%d", &i) != 1) /* Error */
int i = 100;
if (printf("%d", i) != 3) /* Error */
Trang 34T m thay ạ đổ i code
• Tạm thay đổi code để tạo ranh giới nhân tạo
hoặc stress tests
void *testmalloc( size_t n) {
static int count =0;
Trang 35nguyên o n code ki m tra
• C n tr ng v i mâu thu n - conflict: ẩ ọ ớ ẫ
• Mở rộng thử nghiệm nội bộ có thể giảm chi phí bảo trì
• Code rõ ràng có thể giảm chi phí bảo trì
• Nhưng Mở rộng thử nghiệm nội bộ có
thể làm giảm độ rõ ràng của Code !
Trang 36Các chi n l ế ượ c testing
(1) Kiểm chứng tăng dần -Testing
Trang 37Testing Incrementally
(1) Testing incrementally
• Thêm tests khi t o 1 l a ch n m i - new cases ạ ự ọ ớ
• Test ph n ầ đơ n gi n tr ả ướ c ph n ph c t p ầ ứ ạ
• Test units (t c là t ng module riêng l ) tr ứ ừ ẻ ướ c khi testing toàn h th ng ệ ố
thử hồi quy
• X lý c 1 l i th ử đ ỗ ườ ng t o ra nh ng l i m i trong 1 he th ng l n, vì v y ạ ữ ỗ ớ ố ớ ậ
…
• Ph i ả đả m b o ch c ch n h th ng không “thoái lui” ki u nh ch c n ng ả ắ ắ ệ ố ể ư ứ ă
tr ướ c kia ang làm vi c gi b broken, nên… đ ệ ờ ị
• Test m i kh n ng ọ ả ă để so sanh phiên b n m i v i phiên b n c ả ớ ớ ả ũ
Trang 38Testing Incrementally (cont.)
(1) Testing incrementally (cont.)
- stubs để test đoạn code mà ta quan tâm
Đoạn code cần quan tâm
Trang 39viện string.h
bài toán có thể giải = 2 phương pháp, thuật toán
# nhau Ta có thể xd cả 2 CT, nếu chúng có cùng
KQ thì có thể khẳng định cả 2 cùng đúng, còn kq khách nhau thì ít nhất 1 trong 2 ct bị sai
Trang 40Ki m ch ng t ể ứ ự độ ng - Automation
(3) Automation
• Testing thủ công rất nặng nhọc và tốn kém và nhàm chán thậm chí không đủ đọ tin cậy.
• Ba quá trình kiểm chúng bao gồm :
• Tạo testing code
• Vi t 1 b ki m ch ng ế ộ ể ứ để ể ki m tra toàn b ch ộ ươ ng trình m i khi có s thay ỗ ự
i, sau khi biên d ch thành công
• Cần biết cái gì được chờ đợi
• T o ra các ạ đầ u ra, sao cho d dàng nh n bi t là úng hay sai ễ ậ ế đ
• T ự độ ng ki m ch ng có th cung c p: ể ứ ể ấ
• Tốt hơn nhiều so với kiểm chứng thủ công
Trang 41• Ngôn ng scripts : cho phép vi t các o n script ữ ế đ ạ để test tu n t ầ ự
• Unix : có các thao tác trên t p tin nh cmp và diff ệ ư để so sanh d li u xu t, sort s p x p các ữ ệ ấ ắ ế
ph n t , grep ầ ử để ể ki m ch ng d li u xu t, c, sum va freq ứ ữ ệ ấ ư để ttong k t d li u xu t ế ữ ệ ấ
• Khi kiểm chứng lùi, cần đảm bảo phiên bản cũ
là đúng, nếu sai thì rất khó xác định và kết quả sẽ không chính xác
• Cần phải kiểm tra chính việc kiểm chứng lùi 1 cách định kỳ để đảm bảo nó vẫn hợp lệ
Trang 42• T o ra nh ng ki m ch ng ạ ữ ể ứ độ ậ c l p
• Kiểm chứng độc lập với các giá trị nhập và giá trị xuất
mong đợi sẽ bổ xung cho kiểm chứng lùi
• Ví dụ : dùng ngôn ngữ NewAwk thực hiện kiểm chứng 1 ct
ngắn, dữ liệu xuất đc ghi vào 1 tệp tin, kq đúng đc ghi vào
1 tệp khác rồi so sánh 2 tệp, nếu khác nhau thì tbaos lỗi echo 3 5 | newawk ‘{i=1; print ($si)++; print $i ,i}’ > out1
echo ‘3 4 1’ > out2 #két quả đúng
if ! Cmp –s out1 out2 # nếu kq so sánh khác nhau
Trang 43Bug-Driven Testing
(4) Ki m ch ng h ể ứ ướ ng l i : Bug-driven testing ỗ
lỗi
(5) Fault injection
Trang 44Ai test cái gì - Who Tests What
• Programmers
kê/viết
• Quality Assurance (QA) engineers
• Customers
• Field testing
thích tham gia vào quá trình test ;
Trang 45Testing Techniques
• Black-Box: Testing ch d a trên vi c phân tích các yêu ỉ ự ệ
documentation, v.v.) Còn đượ ọ c g i là functional testing.
• White-Box: Testing d a trên vi c phân tích các logic bên ự ệ
trong - internal logic (design, code, v.v.) (Nh ng k t qu ư ế ả
mong đợ ẫ đế ừ i v n n t requirements.) Còn c g i là đ ọ
structural testing.
Trang 46Levels or Phases of Testing
• Unit: testing các m u công vi c nh nh t c a LTV ẫ ệ ỏ ấ ủ để có th l p ể ậ
k ho ch và theo dõi h p lý (vd : function, procedure, module, ế ạ ợ
object class, ….)
• Component: testing 1 t p h p các units t o thành 1 thành ph n (vd ậ ợ ạ ầ
: program, package, task, interacting object classes, …)
• Product: testing các thành ph n t o thành 1 s n ph m ầ ạ ả ẩ
( subsystem, application, …)
• System: testing toàn b h th ng ộ ệ ố
• Testing th ườ ng:
• Bắt đầu = functional (black-box) tests,
• Rồi thêm = structural (white-box) tests,
và
• Tiến hành từ unit level đến system level
với 1 hoặc một vài bước tích hợp
Trang 47T i sao không "test everything"? ạ
•Chi phí cho 'exhaustive' testing:
20 x 4 x 3 x 10 x 2 x 100 = 480,000 tests
•Nếu 1 giây cho 1 test, 8000 phút, 133 giờ, 17.7 ngày
(not counting finger trouble, faults or retest)
nếu 10 secs = 34 wks, 1 min = 4 yrs, 10 min = 40 yrs
Trang 48- Khi b n tin t ạ ưở ng r ng HT ho t ằ ạ độ ng t t ố
- Ph thu c vào risks for your system ụ ộ
Càng ít th i gian, càng nhi u ờ ề để
Th i gian ờ để test luôn có gi i h n ớ ạ
Dùng RISK để xác nh: đị
- Cái gì phải test trước
- Cái gì phải test nhiều
- Mỗi phần tử cần test kỹ như thế nào ? Tức là đâu là trọng tâm
- Cái gì khong cần test (thời điểm này)
Trang 51• Verifying conservation properties
• Checking function return values
• Changing code temporarily
• Leaving testing code intact