D) CÁC CÁCH BIỂU DIỄN CỦA MÔ HÌNH PHÂN TÍCH
f. Đặc tả giao diện đối tượng
7.3. KIỂM THỬ THÀNH PHẦN
Kiểm thử thành phần (đôi khi còn được gọi là kiểm thử đơn vị) là một tiến trình kiểm thử các thành phần độc lập trong hệ thống. Như đã thảo luận trong phần giới thiệu, đối với hầu hết các hệ thống, người phát triển thành phần chịu trách nhiệm kiểm thử thành phần do mình tạo ra. Các kiểu kiểm thử khác nhau được kiểm tra trong giai đoạn này là:
1. Kiểm thử các chức năng hoặc các phương thức độc lậpcủa lớp đối tượng.
2. Kiểm thử các lớp đối tượng có một số thuộc tính và phương thức.
3. Kiểm thử các thành phần hợp thành từ các đối tượng hoặc chức năng khác nhau. Những
thành phần hợp thành này có giao diện xác định được sử dụng để truy cập vào các chức năng của chúng.
7.3.1. Kiểm thử lớp đối tượng
Các chức năng hoặc phương thức độc lập là kiểu đơn giản nhất của thành phần và được kiểm thử như một tập những lời gọi các phương thức này từ các tham số đầu vào khác nhau. Ta có thể sử dụng cách tiếp cận này để thiết kế các trường hợp kiểm thử. Khi đang kiểm thử các lớp đối tượng, nên thiết kế các kịch bản kiểm thử bao trùm được tất cả các tính năng của đối tượng. Tuy nhiên, lớp đối tượng kiểm thử thường bao gồm:
1. Kiểm thử cách ly tất cả các chức năng của đối tượng.
2. Thiết lập và truy vấn tất cả các thuộc tính của đối tượng.
3. Kiểm tra đối tượng với tất cả các trạng thái có thể. Điều này có nghĩa là tất cả các sự kiện dẫn đến sự thay đổi trạng thái của đối tượng đều phải mô phỏng.
Ví dụ, hình 7.6 là giao diện của hệ thống trạm khí tượng được nêu ra ở chương trước. Đối tượng này chỉ có một thuộc tính xác định số hiệu của trạm, đây là một hằng số được đặt khi trạm được thiết lập. Tuy nhiên, thuộc tính này chỉ cần kiểm tra khi nó được thiết lập. Nhưng ta cần xây dựng các trường hợp kiểm thử các phương thức của đối tượng như: reportWeather, calibrate…
Một cách lý tưởng, các phương thức phải kiểm tra một cách độc lập, nhưng trong một số trường hợp, kiểm thử tuần tự là cần thiết. Ví dụ, khi kiểm tra phương thức shutdown, cần phải thực thi phương thức Start.
Hình 7.6. Giao diện của đối tượng WeatherStation
Để kiểm tra trạng thái của trạm thời tiết, ta sử dụng mô hình trạng thái chỉ ra trong hình 7.7. Qua mô hình này ta có thể xác định thứ tự các biến đổi trạng thái, do đó phải kiểm tra và xác
WeatherStation identifier reportWeather() celibrate (instruments) test() startup(instruments) shutdown(instruments)
định thứ tự các sự kiện gây ra sự biến đổi trạng thái. Về cơ bản, ta cần phải kiểm thử tất cả các trạng thái biến đổi có thể, mặc dù trên thực tế nó rất tốn kém.
Hình 7.7. Mô hình trạng thái của đối tượng Weather Station trong hệ thống trạm thời tiết
Ví dụ về thứ tự các trạng thái biến đổi nên được kiểm thử trong trạm thời tiết bao gồm:
Shutdown -> waiting -> Shutdown
Waiting ->calibrationg -> Testing -> transmiting – Waiting
Waiting -> Collecting -> Waiting -> Summarising -> Transmitting -> Waiting
Nếu trong hệ thống có các lớp kế thừa thì sẽ khó thiết kế các trường hợp kiểm thử cho các lớp đối tượng. Khi một lớp cha cung cấp các phương thức được kế thừa cho các lớp con khác nhau, tất cả các lớp con phải được kiểm thử các phương thức kế thừa này. Lý do phải kiểm thử lại là những thuộc tính hoặc phương thức kế thừa này đã thay đổi trong các lớp con.
7.3.2. Kiểm thử giao diện
Nhiều thành phần trong hệ thống không phải là những chức năng hoặc đối tượng đơn giản mà nó được tích hợp từ một số đối tượng khác nhau. Khi đó ta cần truy nhập vào những chức năng của các thành phần sau đó kiểm tra xem giao diện của các thành phần này có tương hợp với đặc tả hay không.
Hình 7.8 minh họa tiến trình kiểm tra giao diện. Giả sử rằng các thành phần A, B, C được tích hợp để tạo ra những thành phần lớn hoặc các hệ thống con. Các trường hợp kiểm thử không được xây dựng cho từng thành phần độc lập nhưng giao diện của thành phần hợp thành được tạo ra bằng việc kết hợp các thành phần này.
Hình 7.8. Tiến trình kiểm thử giao diện
Kiểm thử giao diện đặc biệt quan trọng trong phát triển phần mềm theo phương pháp hướng đối tượng hoặc hướng thành phần. Các đối tượng và các thành phần được xác định bởi giao diện của nó và có thể được tái sử dụng bằng việc kết hợp với các thành phần khác trong các hệ thống khác nhau. Những lỗi giao diện trong thành phần hợp thành không thể phát hiện khi kiểm thử các đối tượng hoặc thành phần độc lập. Những lỗi trong các thành phần hợp thành có thể phát sinh bởi sự tương tác giữa các thành phần trong nó.
Có các kiểu giao diện khác nhau giữa các thành phần chương trình, kết quả là có những lỗi giao diện khác nhau có thể xảy ra:
1. Giao diện dạng tham số: giao diện là dữ liệu hoặc đôi khi là chức năng được chuyển từ thành phần này sang thành phần khác.
2. Giao diện bộ nhớ được chia sẻ: là những giao diện mà các khối bộ nhớ được chia sẻ giữa các thành phần. Dữ liệu được đặt trong bộ nhớ bởi một hệ thống con và được đưa ra từ những hệ thống con khác.
3. Giao diện thủ tục: là những giao diện mà một thành phần ẩn trong nó một tập hợp các thủ tục có thể được gọi từ những thành phần khác. Các đối tượng và các thành phần có thể tái sử dụng có dạng giao diện này.
4. Giao diện chuyển thông điệp: những giao diện này thực hiện việc chuyển các thông điệp
từ thành phần này sang thành phần khác. Một thông điệp trả về sẽ bao gồm kết quả của việc thực thi dịch vụ. Một số hệ thống hướng đối tượng có giao diện dạng này, chẳng hạn như hệ thống client-server.
Lỗi trong giao diện thường rơi vào 3 loại sau:
1. Sử dụng sai giao diện: một thành phần gọi thành phần khác qua giao diện và gặp lỗi trong sử dụng giao diện. Kiểu lỗi này thường gặp khi truyền các tham số sai kiểu, sai thứ tự.
2. Hiểu sai giao diện: một thành phần gọi một thành phần khác thông qua giao diện nhưng lại hiểu sai về hoạt động của thành phần đó, gọi thành phần không có những hoạt động mong đợi. Ví dụ: khi tìm kiếm nhị phân có thể được gọi trong một mảng không được sắp xếp, do đó việc tìm kiếm sẽ thực hiện sai.
Các trường hợp kiểm thử
3. Lỗi thời gian: lỗi này xảy ra trong các hệ thống thời gian thực có sử dụng việc chia sẻ bộ nhớ hoặc giao diện truyền thông điệp. Việc sinh ra và xử lý dữ liệu đôi khi không đồng bộ (tốc độ xử lý khác nhau).
Kiểm thử để phát hiện những khiếm khuyết của giao diện là khó vì đôi khi những lỗi giao diện này chỉ sinh ra trong các trường hợp sử dụng bất thường. Một vấn đề nữa nảy sinh do sự tương tác giữa các lỗi trong các module hoặc các đối tượng khác nhau. Lỗi trong một đối tượng có thể chỉ được phát hiện khi một đối tượng khác hoạt động không đúng.
Các kỹ thuật kiểm thử tĩnh thường hiệu quả hơn về mặt chi phí trong việc khám phá ra các lỗi giao diện. Một kiểu ngôn ngữ lập trình mạnh như Java cho phép nhiều lỗi giao diện được phát hiện khi biên dịch. Trong khi đó các ngôn ngữ yếu hơn, chẳng hạn như C, sử dụng phân tích tĩnh có thể giúp phát hiện các lỗi giao diện. Kiểm tra chương trình có thể tập trung vào các giao diện thành phần và những câu hỏi về giao diện thực hiện trong quá trình thẩm tra.
7.4. THIẾT KẾ TRƯỜNG HỢP KIỂM THỬ (TEST CASE DESIGN)
Mục tiêu của tiến trình thiết kế các trường hợp kiểm thử là tạo ra một tập các trường hợp kiểm thử hiệu quả trong việc phát hiện ra những lỗi của chương trình và chỉ ra rằng hệ thống đáp ứng được yêu cầu.
Để thiết kế một trường hợp kiểm thử, ta cần lựa chọn một tính năng của hệ thống hoặc một thành phần đang kiểm thử, sau đó chọn một tập dữ liệu đầu vào để thực thi tính năng này.
Dưới đây là một số cách tiếp cận khác nhau được dùng để thiết kế các trường hợp kiểm thử:
1. Kiểm thử dựa trên yêu cầu: các trường hợp kiểm thử được thiết kế để kiểm tra các yêu
cầu của hệ thống. Kỹ thuật này thường được sử dụng trong các giai đoạn kiểm thử hệ thống. Với mỗi yêu cầu cần xác định các trường hợp kiểm thử để có thể chứng minh rằng các yêu cầu của hệ thống được đáp ứng.
2. Kiểm thử phân vùng (partition): xác định các phân vùng dữ liệu đầu vào (input) và phân
vùng kết quả đầu ra (output), thiết kế các trường hợp kiểm thử sao cho hệ thống thực thi từ tất cả các phân vùng và sinh ra tất cả các phân vùng của kết quả đầu ra. Các phân vùng là những nhóm dữ liệu có các thuộc tính chung, chẳng hạn như tất cả các số âm, tất cả những tên có độ dài <30 kí tự, tất cả các sự kiện sinh ra khi chọn một mục trên menu…
3. Kiểm thử cấu trúc: sử dụng kiến thức về cấu trúc chương trình để thiết kế các trường hợp kiểm thử thực thi tất cả các phần của chương trình. Về cơ bản, khi kiểm thử một chương trình ta nên cố gắng thực thi mỗi câu lệnh ít nhất một lần. Kiểm thử cấu trúc giúp xác định các trường hợp kiểm thử có thể.
Kiểm thử dựa trên yêu cầu là một cách tiếp cận ngữ nghĩa (semantic) để thiết kế các trường hợp kiểm thử thông qua việc xem xét mỗi yêu cầu và sinh ra một tập các trường hợp kiểm thử cho các yêu cầu này. Kiểm thử dựa trên yêu cầu được xem là kiểm thử thẩm định hơn là kiểm thử khiếm khuyết – nghĩa là ta đang cố gắng chứng minh rằng hệ thống hoạt động đúng như đặc tả.
Ví dụ, hãy xem xét những yêu cầu cho hệ thống quản lý thư viện LIBSYS:
1. Người sử dụng có thể tìm kiếmtừ tập hợp cơ sở dữ liệu ban đầu hoặc từ một tập con của tập cơ sở dữ liệu ban đầu đó.
2. Hệ thống phải cung cấp công cụ hiển thị hợp lý để người sử dụng xem được tài liệu trong kho tài liệu.
3. Mỗi phiếu đặt sách phải được cấp một số hiệu duy nhất để người sử dụng có thể sao lưu qua tài khoản trong vùng lưu trữ thường trực cá nhân.
Giả sử ta đang xây dựng các kịch bản kiểm thử cho chức năng tìm kiếm, khi đó những trường hợp kiểm thử có thể sinh ra từ những yêu cầu trong chức năng tìm kiếm là:
- Tìm kiếm trong một cơ sở dữ liệu với hai trường hợp: tài liệu có và không có trong cơ sở dữ liệu.
- Tìm kiếm trong hai cơ sở dữ liệu với hai trường hợp: Tài liệu có và không có trong cơ sở dữ liệu.
- Tìm kiếm trong nhiều hơn hai cơ sở dữ liệu với hai trường hợp: Tài liệu có và không có trong cơ sở dữ liệu.
- Chọn một trong những cơ sở dữ liệu từ các thiết lập của người sử dụng và bắt đầu tìm kiếm các tài liệu mà được biết là có mặt và không có mặt trong cơ sở dữ liệu đã chọn.
- Chọn nhiều hơn một cơ sở dữ liệu trong tậpcơ sở dữ liệu và bắt đầu tìm kiếm các tài liệu mà được biết là có mặt và được biết không có mặt trong các cơ sở dữ liệu đã chọn.
Thông qua ví dụ này, ta có thể nhận thấy việc kiểm thử một yêu cầu không chỉ viết một
trường hợp kiểm thử mà thông thường ta phải viết vài kịch bản kiểm thử để đảm bảo rằng các kịch bản kiểm thử này đã bao phủ được tất cả các trường hợp của yêu cầu.
Kiểm thử các yêu cầu khác trong hệ thống LYBSYS có thể được thực hiện giống như trên. Với yêu cầu thứ hai, ta sẽ đưa ra các trường hợp kiểm thử để phân phối tất cả các kiểu tài liệu có thể được xử lý bởi hệ thống và kiểm tra việchiển thị các tài liệu đó. Với yêu cầu thứ ba, ta có thể đưa vào một vài yêu cầu về việc đặt tài liệu, sau đó kiểm tra định danh yêu cầu được hiển thị trong phiếu chứng nhận của người dùng và kiểm tra định danh yêu cầu đó có phải là duy nhất
hay không.
7.4.2. Kiểm thử phân vùng
Dữ liệu đầu vào và kết quả đầu ra của một chương trình thường rơi vào một số lớp khác nhau có chung các thuộc tính, chẳng hạn như tập số âm, tập số dương và việc lựa chọn từ thanh thực đơn. Các chương trình vận hành theo cách để có thể so sánh được tất cả các thành viên của một lớp. Nghĩa là, nếu cần kiểm thử một chương trình có một số phép toán và yêu cầu có 2 số dương, ta mong rằng chương trình cũng được thực thi như thế với tất cả các số dương.
Những lớp này đôi khi được gọi là phân vùng tương đương. Một cách tiếp cận có hệ thống để thiết kế các trường hợp kiểm thử là dựa trên việc xác định tất cả các vùng cho một hệ thống hoặc một thành phần. Các trường hợp kiểm thử được thiết kế sao cho dữ liệu kiểm thử và kết quả đầu ra nằm trong những vùng này. Kiểm thử phân vùng có thể được sử dụng để thiết kế
các trường hợp kiểm thử cho cả hệ thống và các thành phần.
Trong hình 7.9, mỗi vùng tương đương được chỉ ra trong một hình ellipse. Các vùng dữ liệu kiểm thử tương đương là các tập dữ liệu mà tất cả các thành viên của tập hợp nên được xử lý cùng một cách. Vùng kết quả đầu ra tương đương là các chương trình có những đặc tính chung, do đó chúng có thể được xem như một lớp riêng biệt. Ta cũng có thể xác định các vùng mà dữ liệu kiểm thử nằm bên ngoài các vùng do ta lựa chọn. Trường hợp kiểm thử này được thực hiện ngay khi chương trình xử lý dữ liệu đầu vào không đúng một cách hợp lý. Dữ liệu đúng và không đúng cũng tạo nên các vùng tương đương nhau.
Hình 7.9. Phân vùng tương đương
Khi có một tập các vùng xác định, ta có thể lựa chọn các trường hợp kiểm thử từ các vùng này. Một nguyên tắc nhỏ cho việc lựa chọn các trường hợp kiểm thử là nên lựa chọn các trường hợp nằm ở vùng biên hơn là những trường hợp nằm giữa vùng. Lý do căn bản cho cách lựa chọn này là người thiết kế và lập trình chỉ chú ý tới những giá trị điển hình của dữ liệu đầu vào khi phát triển hệ thống. Ta kiểm tra trường hợp này với dữ liệu thuộc điểm giữa của phân vùng. Những giá trị ngoại biên thường là không đúng kiểu, vì thế nó hay nằm ngoài tầm kiểm soát của người phát triển. Lỗi chương trình thường xảy ra khi thực thi với những dữ liệu này.
Khi xác định các phân vùng ta thường sử dụng tài liệu đặc tả hoặc tài liệu người dùng.
Hệ thống
Tập các đầu ra
Đầu vào hợp lệ Đầu vào không
Hình 7.10. Các phân vùng tương đương
Để minh họa cho nguồn gốc của các trường hợp kiểm thử, ta sử dụng đặc tả của chương trình tìm kiếm được chỉ ra trong hình 7.11. Đoạn chương trình này tìm kiếm trong một dãy các thành phần đầu ra, một thành phần có giá trị định trước. Chương trình sẽ trả lại vị trí của thành phần trong dãy nếu nó tìm thấy. Trong trường hợp này, ta xác định phân vùng bằng việc xác định tiền điều kiện, nó đúng khi chương trình được gọi và một hậu điều kiện, nó đúng sau khi chương trình được thực thi.
Tiền điều kiện chỉ ra rằng thuật toán tìm kiếm chỉ thực hiện với một mảng không rỗng. Hậu điều kiện chỉ ra rằng biến tìm ra được thiết lập nếu như thành phần khóa nằm trong dãy. Vị