Kiểm thử on-the-fly là cách dễ nhất để bắt đầu kiểm thử với công cụ ct. Đối với kiểm thử này, không cần thiết phải tạo một bộ kiểm thử hay tạo kịch bản. Tất cả những gì kiểm thử viên cần là một thực hiện (Implementation), một MP, và một bản khai thác kiểm thử hay là một stepper. Chiến lƣợc đƣợc cài đặt sẵn của công cụ ct là kiểm thử ngẫu nhiên, có nghĩa là trong mỗi trạng thái, chọn một hành động đƣợc kích hoạt ngẫu nhiên.
Một MP sẽ luôn luôn đạt đƣợc một trạng thái chết hoặc một trạng thái chấp nhận, do đó không phải làm bất cứ sự sắp đặt (đặt điều kiện) nào để dừng test run.
Thông thƣờng, một kiểm thử ngẫu nhiên tạo ra nhiều đƣờng chạy kiểm thử dễ dàng, nhƣng nhiều đƣờng chạy ngẫu nhiên đó không tiến hành Impl một cách triệt để, vì thế chiến lƣợc ngẫu nhiên đƣợc cài đặt sẵn không đạt đƣợc độ bao phủ tốt một cách
nhanh chóng. Để kiểm thử đƣợc tốt hơn thì có thể lập trình chiến lƣợc của riêng mình và có thể nạp vào ct với tùy chọn /strategy.
Xét ví dụ về thực hiện của một bag đƣợc chỉ ra trong hình 3.12. Ví dụ này là nhỏ và dễ dàng hiểu một MP với trạng thái phức tạp và hành vi vô hạn.
Thực hiện (Implementation): Một bag là một bộ sƣu tập không có thứ tự của các phần tử. Một phần tử có thể đƣợc thêm vào bag, bị xóa khỏi bag, và đƣợc tìm kiếm trong bag. Sự đa dạng của một phần tử là số lần nó xảy ra trong bag không bị giới hạn. Việc tìm kiếm một phần tử trong bag trả về sự đa dạng của phần tử đó. Một phần tử không ở trong bag nếu và chỉ nếu sự đa dạng của nó là số 0. Tổng số lƣợng các phần tử trong bag cũng có thể đƣợc đếm. Thực hiện bag không phải là một kiểu giá trị.
Mô hình (Model): Mô hình bag có một vốn từ vựng hành động tƣơng ứng với các phƣơng thức của thực hiện bag. MP đƣợc chỉ ra trong hình 3.13. Dấu vết hành động sau đây là một ví dụ của một hành động đúng của bag:
Add("elem1"), Add("elem1"), Count_Start(), Count_Finish(2), Lookup_Start("elem1"), Lookup_Finish(2), Lookup_Start("elem2"), Lookup_Finish(0), Delete("elem1"), Lookup_Start("elem1"), Lookup_Finish(1).
Hình 3.12: Bag implementation
Biến content là biến trạng thái duy nhất của MP. Trong trạng thái khởi tạo, giá trị của content là bag rỗng. MP bag định nghĩa một máy trạng thái vô hạn bởi vì các
miền tham số đầu vào của các hành động là không bị chặn và kích cỡ của bag là không bị chặn. Một cách để ràng buộc tập hợp các tham số đầu vào có thể là cung cấp một tính năng riêng biệt của mô hình mà cho phép chỉ một tập hợp cố định các phần tử xảy ra nhƣ các đối số đầu vào cho các hành động tƣơng ứng. Một tính năng đƣợc chỉ trong hình 3.14. Tính năng này hạn chế tập hợp các phần tử có thể về null, " ", và "b". Nó sử dụng thuộc tính Domain để kết hợp một tập hợp cố định các phần tử với mỗi tham số đầu vào.
Phƣơng thức factory CreateScenario tạo ra một mô hình hạn chế (bị giới hạn) mà các tham số đầu vào cho các hành động là bị giới hạn các phần tử nhất định. Mô hình kịch bản đƣợc cung cấp bởi CreateScenario vẫn là vô hạn bởi vì kích cỡ của bag là không bị chặn. Tuy nhiên, không giống nhƣ MP hợp đồng, MP đƣợc tạo bởi
CreateScenario là có thể thăm dò bởi vì tất cả các miền tham số là hữu hạn.
Hình 3.14: Một tính năng của mô hình và kịch bản
Stepping the implementation: Khi stepper thực hiện một hành động, nó gọi IUT với các đối số đầu vào tƣơng ứng. Các đầu vào đƣợc mã hóa trong hành động là trừu tƣợng và không nhất thiết phải là giá trị cụ thể theo yêu cầu bởi IUT. Tuy nhiên, phải có một ánh xạ đƣợc định nghĩa rõ ràng từ các hành động đầu vào trừu tƣợng đến các giá trị đầu vào cụ thể. Việc lập ánh xạ này là một phần không thể thiếu của stepper.
Việc thực hiện một hành động trong stepper có thể làm cho stepper trả về một hành động đầu ra nhƣ một giá trị trả về. Hành động này hoặc tƣơng ứng với giá trị trả về ngay lập tức của một phƣơng thức hoặc biểu diễn một trừu tƣợng của trạng thái kết quả của IUT. Phải có một ánh xạ đƣợc định nghĩa rõ ràng từ giá trị trả về cụ thể của IUT đến các hành động trừu tƣợng đƣợc trả về bởi stepper.
Các stepper là các thực hiện của giao diện IStepper của thƣ viện mô hình : public interface IStepper
{
Action DoAction(Action action); void Reset();
Một stepper cho BagImpl đƣợc chỉ ra trong hình 3.15. Để ánh xạ các hành động đầu vào của stepper đến các đầu vào cụ thể cho thực hiện bag, stepper phải trích xuất đối số đầu tiên của hành động đầu vào a, bằng cách sử dụng biểu thức chỉ mục a[0] và một sự đổi kiểu thành string. Để xây dựng các hành động đầu ra tƣơng ứng với các giá trị trả về của các hoạt động tìm kiếm và đếm, stepper sử dụng chức năng hữu ích Action.Create để tạo một hành động đầu ra từ một tên hành động nhất định và các đối số đƣợc cho là các giá trị .NET.
Hình 3.15: Bag stepper 3.2.5.2. Các chiến lƣợc
Ngoài trạng thái mô hình, một tester cũng có một trạng thái tester. ví dụ, tester có thể có một truy cập của nhiều bƣớc (các chuyển tiếp) kiểm thử cá nhân đƣợc thực hiện trong tổng số để có thể phân biệt giữa các lần xuất hiện khác nhau của cùng trạng thái mô hình. Trong trƣờng hợp ngoại tuyến (offline) giá trị của truy cập là đủ cho tester biết đƣợc hành động nào để lựa chọn hoặc để mong đợi tiếp theo.
Với kiểm thử on-the-fly, việc lựa chọn hành động là tự động và xảy ra trong suốt quá trình kiểm thử; không có bộ kiểm thử nào đƣợc tính toán trƣớc và máy trạng thái đầy đủ không cần đƣợc biết trƣớc. Trạng thái tester cần đủ nhiều để ghi lại thông
tin cần thiết khi lựa chọn hành động tiếp theo. Đặc biệt, trạng thái tester phải có một tham chiếu đến trạng thái mô hình hiện tại để biết những hành động nào đƣợc kích hoạt. Một hành động không đƣợc kích hoạt trong mô hình không đƣợc lựa chọn bởi tester, bởi vì điều kiện phù hợp với mô hình sẽ bị vi phạm.
Một cách để hiện thực hóa một tester on-the-fly cụ thể là thực hiện một chiến lƣợc tùy chỉnh. Công cụ ct có thể đƣợc cung cấp với một chiến lƣợc tùy chỉnh bằng cách sử dụng tùy chọn strategy. Một chiến lƣợc đƣợc thực hiện bằng cách cung cấp giao diện IStrategy đƣợc chỉ ra trong hình 3.16.
Hình 3.16: Giao diện IStrategy
Chiến lƣợc mặc định: Một chiến lƣợc mặc định hoặc cơ bản cho một MP nhất định đƣợc cung cấp bởi lớp Strategy. Chiến lƣợc cơ bản không có trạng thái tester bổ sung, nó thực hiện một chiến lƣợc lựa chọn hành động ít bộ nhớ đƣợc gọi.
Tester có thể đƣợc sử dụng phù hợp với ct để chạy MP bag bị giới hạn so với stepper bag. Khi nó xảy ra, mọi kiểm thử đầu tiên không thành công với một dấu vết bao gồm một hành động Lookup_Start (null) với một lý do thất bại rằng null không thể là một từ khóa trong từ điển đƣợc sử dụng để thực hiện bag. Lỗi có thể đƣợc sửa dễ dàng bằng cách đếm các giá trị null riêng biệt và không cố chèn thêm null hoặc tìm nó trong từ điển. Bây giờ, hãy giả định rằng tập hợp tham số bị giới hạn với các giá trị : " " và "b", có nghĩa là đổi định nghĩa của E trong hình 3.14 thành: readonly static Set<string> E = new Set<string>("","b");
Sau một vài thực thi của ct, tester nhận đƣợc một dấu vết thất bại khác. TestResult(2, Verdict("Failure"),
Unexpected return value of finish action, expected: Count_Finish(2)
Unexpected finish action", Trace( Count_Start(), Count_Finish(0), Delete(""), Add(""), Add("b"), Add(""), Delete("b"), Delete("b"), Count_Start(), Count_Finish(1) ) )
Ở đây, lỗi là lời gọi cuối cùng đến Count trả về 1 thay vì 2. Chú ý rằng phải có hai chuỗi rỗng trong bảng vào thời điểm này. Bằng cách kiểm tra thực hiện ta có thể nhìn thấy rằng khi một phần tử bị xóa, một trƣờng hợp bị thiếu cho tình huống khi số lƣợng phần tử bị xóa trở thành 0. Nếu điều này xảy ra sau đó việc xóa cũng nên loại bỏ phần tử từ bảng.
CHƢƠNG 4. XÂY DỰNG DEMO VÀ KIỂM THỬ HỆ THỐNG VỚI NMODEL 4.1. Giới thiệu NModel
4.1.1. Cài đặt NModel
Để cài đặt NModel, máy tính phải có .NET và không cần thiết phải có Visual Studio.
Phiên bản .Net có thể làm việc là Framwork .NET 3.5. Nếu có sẵn phiên bản 2 hoặc 3 thì cũng làm việc đƣợc. Sau đó làm theo các bƣớc sau để cài đặt :
Bƣớc 1 : Download Nmodel.msi. Mở và cài đặt (chọn Typical Install).
Việc thực thi file .msi cài đặt thƣ viện Nmodel, 4 chƣơng trình mpv, mp2dot, otg, và ct, và trợ giúp trực tuyến (online help). Đây là tất cả những gì cần chạy chƣơng trình, tạo và sử dụng các chƣơng trình mô hình của riêng mình.
Bƣớc 2: Để chạy mpv, công cụ bố cục đồ họa (the graph layout engine) GLEE phải đƣợc cài đặt. Chú ý rằng GLEE sử dụng giấy phép bản quyền ít hơn Nmodel. Sau khi đã cài đặt cả NModel và GLEE, thì phải copy GLEE DLLs vào trong thƣ mục bin của NModel. Trong quá trình cài đặt nơi mà cả hai đƣợc cài đặt ở vị trí mặc định, điều đó có thể đƣợc thực hiện bằng đƣờng dẫn:
Cd C: \Program Files\Microsoft Research\GLEE\bin Copy *.dll…\...\...\Nmodel\bin
Ngoài mpv ra, mp2dot (Model Program to Dot) cũng có thể đƣợc sử dụng. Chƣơng trình mp2dot không yêu cầu GLEE, và đƣợc bao gồm bởi giấy phép bản quyển của NModel nên dễ dàng hơn.
Bƣớc 3: Sau khi cài đặt xong phải thiết lập biến môi trƣờng bằng cách:
Nhấn phải chuột vào biểu tƣợng Computer. Khi đó, xuất hiện hộp thoại, chọn Remote Settings =>chọn Advanced => chọn Environment Variables => chọn Path => Copy đƣờng dẫn C:\Windows\Microsoft.NET\Framework\v3.5 và C:\Program Files\NModel\bin trong ổ C và dán vào ô Variable value và chọn OK.
4.1.2. Cách sử dụng các công cụ mpv, otg, ct 4.1.2.1. Công cụ mpv 4.1.2.1. Công cụ mpv
Công cụ mpv đƣợc sử dụng để hình dung và phân tích hành vi của một hoặc nhiều chƣơng trình. Nó thực hiện thăm dò, nó tạo ra một máy trạng thái hữu hạn FSM từ một MP. MPV hiển thị đồ thị của FSM đƣợc tạo, đồng thời khảo sát và hiển thị thành phần của tất cả các chƣơng trình mô hình đƣợc có tên trên dòng lệnh, nó có thể là các MP C# hoặc các FSM. MPV cung cấp nhiều lựa chọn (trên dòng lệnh và giao diện sử dụng của nó) để điều chỉnh đồ thị đƣợc hiển thị, lƣu trữ và khôi phục các kết quả của việc thăm dò. Nó cũng cung cấp cơ sở để kiểm tra các trạng thái (biến chƣơng trình và giá trị của chúng), và để khám phá các chƣơng trình tƣơng tác (từng bƣớc, làm việc chuyển tiếp từ một vài trạng thái quan tâm).
Bằng cách tìm kiếm FSM, mpv có thể thực hiện phân tích an toàn để kiểm tra xem hệ thống có đạt đƣợc các trạng thái bị cấm không, và phân tích tính hoạt động đƣợc để xác định các trạng thái chết.
Công cụ mpv đòi hỏi phần mềm GLEE phải đƣợc cài đặt. Các công cụ còn lại không yêu cầu GLEE.
Cách sử dụng (Usage) mpv: mpv [/reference:<string>]*[/mp:<string>]* /initialTransitions:<int>]* [/transitionLabels:{None|ActionSymbol|Action}]* [/nodeLabelsVisible[+|-]]* [/initialStateColor:<string>]* [/hoverColor:<string>]* [/selectionColor:<string>]* [/deadStateColor:<string>]* [/deadStatesVisible[+|-]]* [/unsafeStateColor:<string>]* [/maxTransitions:<int>]* [/loopsVisible[+|-]]* [/mergeLabels[+|-]]* [/acceptingStatesMarked[+|-]]* [/stateShape:{Box|Circle|Diamond|Ellipse|Octagon|Plaintext}]* [/direction:{TopToBottom|LeftToRight|RightToLeft|BottomToTop}]* [/combineActions[+|-]]* [/livenessCheckIsOn[+|-]]* [/safetyCheckIsOn[+|-]]*
[/testSuite:<string>]* [/fsm:<string>]* [/startTestAction:<string>]* [/group:<string>]* <model>* @<file> Ví dụ: mpv @mpv args.txt mpv /fsm:M1.txt /fsm:M2.txt mpv /testSuite:ContractTest.txt mpv /r:NewsReaderUI.dll NewsReader.Factory.Create mpv /r:NewsReaderUI.dll /mp:NewsReader
mpv /r:Controller.dll Reactive.Factory.Create /safetyCheckIsOn+ mpv /r:Controller.dll /mp:Reactive /safetyCheckIsOn+
41.2.2. Công cụ otg
Công cụ otg tạo ra một bộ kiểm thử ngoại tuyến (offline test suite) mà đạt đƣợc độ bao phủ liên kết của máy trạng thái hữu hạn (FSM) đƣợc tạo ra từ một MP. Sau đó, bộ kiểm thử có thể đƣợc thực hiện bởi Conformance Tester (công cụ ct).
Cách sử dụng otg:
otg [/reference:<string>]* [/mp:<string>]* [/file:<string>]* [/append[+|-]]* [/fsm:<string>]* <model>* @<file>
Ví dụ:
otg @otg args.txt
otg /r:ClientServer.dll ClientServer.Factory.Create /fsm:Scenario.txt otg /r:ClientServer.dll /mp:ClientServer /fsm:Scenario.txt
otg /r:ClientServer.dll ClientServer.Factory.Create /file:ContractTest.txt
otg /r:ClientServer.dll /mp:ClientServer /file:ContractTest.txt
4.1.2.3. Công cụ ct
Để thực hiện các test bằng cách sử dụng test runner ct, một bản khai thác kiểm thử phải đƣợc viết bằng C# để kết nối thực hiện đến ct. Một bộ kiểm thử đƣợc tạo ra từ một MP bởi công cụ otg, hoặc ct có thể tạo ra các ca kiểm thử trực tiếp từ một MP khi test run thực thi, và một chiến lƣợc tùy chỉnh có thể đƣợc viết bằng C# mà ct sử dụng để tối đa hóa độ bao phủ theo tiêu chí đƣợc xác định.
ct /iut:<string> [/modelStepper:<string>] /reference:<string>+ [/mp:<string>]*
[/coverage:<string>]* [/steps:<int>]* [/maxSteps:<int>]* [/runs:<int>]*
[/observableAction:<string>]* [/cleanupAction:<string>]* [/internalAction:<string>]* [/waitAction:<string>]* [/timeoutAction:<string>]*
[/timeout:<int>]* [/continueOnFailure[+|-]]* [/logfile:<string>]* [/randomSeed:<int>]* [/overwriteLog[+|-]]* [/testSuite:<string>]* [/fsm:<string>]* [/startTestAction:<string>]* <model>* @<file>
Ví dụ:
ct @ct args.txt
ct /r:Stepper.dll /iut:ClientServerImpl.Stepper.Create /testSuite:ContractTest.txt
ct /r:ClientServer.dll ClientServer.Factory.Create /r:Stepper.dll ^ /iut:ClientServerImpl.Stepper.Create /fsm:Scenario.txt /runs:1 ct /r:ClientServer.dll /mp:ClientServer /r:Stepper.dll ^
/iut:ClientServerImpl.Stepper.Create /fsm:Scenario.txt /runs:1
4.2. Xây dựng và thực nghiệm với demo hệ thống client/server 4.2.1. Mô tả bài toán 4.2.1. Mô tả bài toán
Trong luận văn này, tôi chọn bài toán về hệ thống nhúng để kiểm thử với NModel là thiết bị điều khiển từ xa – hệ thống client/server. Bài toàn này đƣợc tham khảo trong tài liệu [4]. Đây là một ứng dụng nhỏ nhƣng tƣơng đối đầy đủ. Mục đích của bài toán là phát triển một hệ thống thiết bị phòng thí nghiệm bao gồm một cảm biến nhiệt độ kết nối với một máy tính nhúng, một mạng, và một máy tính khác đƣợc sử dụng để lƣu trữ và phân tích dữ liệu (hình 4.1). Trên máy tính nhúng (Server) có một chƣơng trình giám sát nhiệt độ đƣợc cài đặt. Trên máy tính khác (Client) có một chƣơng trình khai thác dữ liệu đƣợc cài đặt. Các chƣơng trình giao tiếp với nhau qua mạng bằng cách sử dụng giao thức TCP/IP (hình 4.2), vì vậy client có thể sử dụng internet để kết nối tới một server trong một nhà máy ở xa hoặc trạm thời tiết.
Hình 4.1. Thiết bị điều khiển từ xa – Hệ thống Client/Server
Trƣớc khi kiểm thử và phân tích ứng dụng demo đƣợc mô tả, tôi sẽ giải thích một số vấn đề về cách mà chƣơng trình làm việc.
Protocol
Hai chƣơng trình thực hiện cùng một giao thức, một thỏa thuận về cách làm việc cùng nhau. Một giao thức đƣợc xác định bởi các quy tắc để hình thành những thông điệp và các quy tắc mà ràng buộc theo thứ tự các thông điệp. Trong demo này, "các thông điệp" trong giao thức là các lời gọi phƣơng thức đã đƣợc mã hóa (coded).
Trong giao thức này, máy chủ bắt đầu trƣớc, và đợi một kết nối từ một máy khách. Máy khách kết nối tới máy chủ và gửi một lệnh yêu cầu một phép đo nhiệt độ. Máy chủ phản hồi bằng cách gửi trả lại nhiệt độ. Sau đó máy khách có thể gửi một dòng lệnh khác, hoặc có thể đóng kết nối và thoát. Nếu client đóng, server có thể đợi một client khác để kết nối, hoặc có thể thoát. Server có thể chỉ chứa một kết nối client tại một thời điểm.
Hình 4.2: Giao thức client/server Sockets
Giao thức của demo đƣợc thực hiện bằng cách sử dụng các socket, một giao diện lập trình ứng dụng API cho giao tiếp qua mạng TCP/IP. Socket API là một trong những kỹ thuật cơ bản của Internet và quen thuộc với nhiều nhà phát triển. Khung làm việc .Net cung cấp một thực hiện của API này trong lớp Socket trong không gian tên
System.Net.Sockets.
Thiết lập một kết nối yêu cầu nhiều bƣớc, trong đó mỗi một đối tác gọi các phƣơng thức trong socket API. Trong Server, Socket tạo một socket nghe (a listener socket), Bind liên kết nó với một địa chỉ IP và số cổng, và Listen chuẩn bị cho một kết nối. Accept thực hiện kết nối và tạo một connection socket để sử dụng cho kết nối. Trong Client, Socket tạo một cổng và Connect thực hiện kết nối. Khi kết nối đƣợc thực