FSM của MP kịch bản

Một phần của tài liệu (LUẬN văn THẠC sĩ) nghiên cứu ứng dụng NModel” trong việc phát triển hệ thống nhúng thời gian thực (Trang 59)

 Gõ lệnh >mpv @mpv_composition.txt để hiển thị FSM của MP kịch bản đƣợc biên soạn cùng với MP hợp đồng (FSM có sử dụng điều khiển kịch bản). Kết quả , ta nhận đƣợc thể hiện trong hình 4.5. FSM này đã đƣợc giới hạn tối ƣu về số lƣợng đƣờng chạy so với FSM của MP hợp đồng.

Bƣớc thứ ba, tạo các bộ kiểm thử (test suite) bởi công cụ otg:

 Gõ lệnh >otg @otg_contract.txt để tạo một bộ kiểm thử cho trƣờng hợp sử dụng MP hợp đồng. Tên tệp tin test suite là ContractTest.txt đƣợc lƣu trữ tự động trong cùng thƣ mục của MP. Bộ ca kiểm thử này gồm có 6 ca kiểm thử có nội dung nhƣ sau:

TestSuite( TestCase( ServerSocket(), ServerBind(), ClientSocket(), ServerListen(), ClientConnect(), ServerAccept(), ServerSend(double("99,9")), ServerCloseConnection(), ServerClose(), ClientReceive_Start(), ClientReceive_Finish(double("99,9")), ClientClose() ), TestCase( ClientSocket(), ServerSocket(), ServerBind(), ServerListen(), ClientConnect(), ServerAccept(), ClientSend(), ServerReceive(), ServerSend(double("99,9")), ClientReceive_Start(), ClientReceive_Finish(double("99,9")), ServerCloseConnection(), ServerClose(), ClientClose() ), TestCase( ClientSocket(), ServerSocket(), ServerBind(), ServerListen(), ClientConnect(), ServerAccept(), ServerSend(double("100")), ServerCloseConnection(), ClientReceive_Start(), ClientReceive_Finish(double("100")), ClientClose(), ServerClose() ),

ServerSocket(), ServerBind(), ServerListen(), ClientSocket(), ClientConnect(), ServerAccept(), ClientClose(), ServerCloseConnection(), ServerClose() ), TestCase( ServerSocket(), ClientSocket(), ServerBind(), ServerListen(), ClientConnect(), ServerAccept(), ServerSend(double("100")), ClientReceive_Start(), ClientReceive_Finish(double("100")), ServerSend(double("100")), ServerCloseConnection(), ServerClose(), ClientReceive_Start(), ClientReceive_Finish(double("100")), ClientClose() ), TestCase( ClientSocket(), ServerSocket(), ServerBind(), ServerListen(), ClientConnect(), ServerAccept(), ServerSend(double("99,9")), ServerCloseConnection(), ClientReceive_Start(), ClientReceive_Finish(double("99,9")), ClientClose(), ServerClose() ) )

 Sau khi tạo bộ ca kiểm thử thì dùng lệnh >mpv @mpv_contract_test.txt để xem kết quả của bộ ca kiểm thử dƣới dạng FSM nhƣ trong hình 4.6.

 Gõ lệnh >otg @otg_scenario.txt để tạo ra một bộ ca kiểm thử đƣợc sinh ra từ MP hợp đồng đƣợc biên soạn với MP kịch bản (tên bộ kiểm thử là ScenarioTest.txt). Bộ kiểm thử này gồm có một ca kiểm thử duy nhất có nội dung nhƣ sau:

ServerBind(), ServerListen(), ClientSocket(), ClientConnect(), ServerAccept(), ServerSend(double("100")), ClientReceive_Start(), ClientReceive_Finish(double("100")), ServerSend(double("99,9")), ClientReceive_Start(), ClientReceive_Finish(double("99,9")), ClientSend(), ServerReceive(), ClientClose(), ServerCloseConnection(), ServerClose() ) )

 Sau đó sử dụng lệnh >mpv @mpv_scenario_test.txt để xem kết quả của bộ kiểm thử dƣới dạng FSM nhƣ trong hình 4.7.

Hình 4.7: FSM của một bộ kiểm thử đƣợc tạo khi MP hợp đồng biên soạn với MP kịch bản

Bƣớc cuối cùng là dùng công cụ ct để kiểm thử:

 Để chạy đƣợc kiểm thử, đầu tiên phải viết một bản khai thác kiểm thử (stepper) để kết nối implementation tới ct (stepper đƣợc trình bày trong phần phụ lục).  Gõ lệnh >build để xây dựng các thƣ viện của chƣơng trình

 Gõ lệnh >ct @ct_contract.txt để thực hiện kiểm thử ngoại tuyến từ MP hợp đồng (không sử dụng điều khiển kịch bản). Kết quả kiểm thử đƣợc thể hiện trong hình 4.8. Kiểm thử này báo thành công và không phát hiện ra lỗi hay khuyết tật.

 Gõ lệnh >ct @ct_scenario.txt để thực hiện kiểm thử ngoại tuyến đƣợc tạo ra từ MP hợp đồng đƣợc biên soạn với MP kịch bản. Kết quả của kiểm thử này báo lỗi đƣợc thể hiện nhƣ trong hình 4.9.

Hình 4.8: Kết quả kiểm thử ngoại tuyến với trƣờng hợp sử dụng MP hợp đồng

Hình 4.9: Kết quả kiểm thử ngoại tuyến với trƣờng hợp sử dụng điều khiển kịch bản (MP hợp đồng đƣợc biên soạn với MP kịch bản)

Nhƣ vậy là kiểm thử ngoại tuyến chƣơng trình client/server đã phát hiện ra lỗi (hình 4.9) khi một bộ kiểm thử có sử dụng điều khiển kịch bản. Thông điệp chỉ ra rằng kiểm thử này lỗi bởi vì giá trị trả về thực tế trong hành động cuối cùng là 99, không giống nhƣ giá trị trả về mong đợi 99.9 đã đƣợc tính bởi MP và đƣợc lƣu trữ trong ca kiểm thử.

Phân tích lỗi: Sau một vài điều tra tôi phát hiện ra khuyết tật là do các đoạn mã không chính xác (không đúng) gây ra các thất bại. Trong mã lệnh (code) của lớp Client đƣợc xây dựng có bộ đệm nhận của client chỉ đƣợc gán với 4 bytes long. Trong khi đó, tôi lại dự định là 40 chứ không phải 4. Đây là một lỗi đánh máy mà không bị bắt (caught) bởi trình biên dịch, bởi sự kiểm tra hoặc kiểm thử đơn vị. Khi server gửi nhiều hơn 4 ký tự, ví dụ nhƣ 100.0 thì client chỉ đọc đƣợc 4 ký tự đầu tiên là 100. Và sau đó các ký tự còn lại trong bộ đệm sẽ đƣợc nhận vào lần tiếp theo khi Client gọi phƣơng thức Receive. Bằng cách này, một mẫu nhiệt độ đơn giản có thể gây cho Client trở nên không đồng bộ với Server, kết quả là việc đọc không đúng sẽ xảy ra với một hoặc nhiều mẫu nhiệt độ tiếp theo.

Từ các kết quả kiểm thử trên tôi có thể so sánh kết quả và đánh giá kiểm thử ngoại tuyến trong hai trƣờng hợp kiểm thử ngoại tuyến không dùng điều khiển kịch bản (tức là chỉ sử dụng MP hợp đồng để sinh các test case tự động) và kiểm thử ngoại tuyến có sử dụng điều khiển kịch bản (kết hợp MP hợp đồng và MP kịch bản) nhƣ sau: trƣờng hợp không dùng điều khiển kịch bản thì có bộ test suite với nhiều test case nên việc kiểm thử không đƣợc kỹ lƣỡng và triệt để, do đó sẽ ít phát hiện ra lỗi hơn, cụ thể trong bài toán này là kiểm thử thành công không phát hiện đƣợc lỗi hay khuyết tật. Còn với trƣờng hợp có sử dụng điều khiển kịch bản thì bộ test suite có số lƣợng test case tối ƣu hơn (ở đây cụ thể là 1 test case) do đó việc kiểm thử sẽ đƣợc kỹ lƣỡng và triệt để hơn, sẽ phát hiện ra lỗi và khuyết tật tốt hơn.

4.2.2.2. Kiểm thử on-the-fly

Kiểm thử on-the-fly không cần phải tạo một bộ kiểm thử trƣớc mà chỉ cần implementation hoặc MP hoặc stepper. Kiểm thử on-the-fly là kiểm thử ngẫu nhiên.

Bƣớc 1: Tạo file ct_contract_random.txt với nội dung sau: /r:Stepper.dll

/iut:ClientServerImpl.Stepper.Create /r:...\Model\ClientServer.dll

/mp:ClientServer /runs:1

Bƣớc 2: Trên dòng lệnh cmd gõ lệnh >ct @ct_contract_random.txt để thực hiện kiểm thử ngẫu nhiên trong trƣờng hợp sử dụng MP hợp đồng. Kết quả kiểm thử này thông báo là gặp thất bại nhƣ trong hình 4.10.

Hình 4.10: Kết quả kiểm thử ngẫu nhiên khi sử dụng MP hợp đồng

Kiểm thử này bị gián đoạn dẫn đến trạng thái chết (mặc dù chọn ngẫu nhiên bất kỳ đƣờng chạy nào). Để kiểm thử đạt kết quả tốt, tệp tin ct đƣợc tạo có sử dụng điều khiển kịch bản ct_scenario_random.txt với nội dung sau:

/r:Stepper.dll /iut:ClientServerImpl.Stepper.Create /r:..\Model\ClientServer.dll /mp:ClientServer /fsm:..\Model\Scenario.txt /runs:1

Tiếp theo, trên chƣơng trình cmd gõ lệnh >ct @ct_scenario_random.txt để thực hiện kiểm thử ngẫu nhiên với trƣờng hợp sử dụng điều khiển kịch bản. Kết quả kiểm thử đƣợc chỉ ra nhƣ trong hình 4.11.

Kiểm thử này thành công bởi vì server đã không gửi 100 cho đến thông điệp cuối cùng. Sau đó, một vài kiểm thử ngẫu nhiên hơn sẽ chạy, ct thực hiện một đƣờng chạy thất bại, làm lộ khuyết tật nhƣ kết quả của đƣờng chạy đƣợc hiển thị trong hình 4.12.

Hình 4.12: Kết quả kiểm thử ngẫu nhiên khi sử dụng điều khiển kịch bản (2)

Tƣơng tự nhƣ phƣơng pháp kiểm thử ngoại tuyến, với trƣờng hợp kiểm thử có sử dụng điều khiển kịch bản của phƣơng pháp trực tuyến (on-the-fly) cũng đạt kết quả kiểm thử tốt hơn so với trƣờng hợp không sử dụng điều khiển kịch bản.

CHƢƠNG 5. KẾT LUẬN VÀ HƢỚNG PHÁT TRIỂN 5.1. Kết luận 5.1. Kết luận

Sau một thời gian nghiên cứu và thực hiện luận văn “Nghiên cứu ứng dụng “NModel” trong việc phát triển hệ thống nhúng thời gian thực”, luận văn của tôi đã đạt đƣợc những kết quả chính cũng nhƣ hƣớng phát triển của luận văn trong thời gian tới nhƣ sau:

Các kết quả chính đạt đƣợc và đóng góp trong luận văn.

- Tìm hiểu và nghiên cứu tài liệu về lý thuyết hệ thống nhúng, lý thuyết về phân tích và kiểm thử dựa trên mô hình: khái niệm chƣơng trình mô hình, khái niệm phân tích dựa trên mô hình, khái niệm kiểm thử dựa trên mô hình, khái niệm máy trạng thái hữu hạn.

- Cài đặt thành công NModel và .NET framework 3.5.

- Hiểu đƣợc quá trình phân tích và kiểm thử: Viết chƣơng trình mô hình, thực hiện thăm dò và phân tích MP hữu hạn, sinh bộ kiểm thử bằng công cụ otg, tiến hành kiểm thử ngoại tuyến bằng công cụ ct.

- Xây dựng đƣợc các chƣơng trình mô hình làm đầu vào cho công cụ từ bài toán thiết bị điều khiển từ xa – hệ thống Client/Server.

- Xây dựng các tệp tin có định dạng .txt (trong phần phụ lục) để điều khiển công cụ trong việc thực hiện phân tích và kiểm thử với NModel.

- Áp dụng quá trình phân tích và kiểm thử ngoại tuyến để kiểm thử thành công demo client/server với NModel.

5.2. Hƣớng phát triển

Trong luận văn này, tôi đã tìm hiểu và thực hiện đƣợc phân tích và kiểm thử dựa trên mô hình đối với hệ thống đóng có các trạng thái đơn giản. Demo với chƣơng trình nhỏ nhƣng đầy đủ. Tuy nhiên, do gặp khó khăn về mặt thời gian nên luận văn vẫn còn một số hạn chế là bài toán chƣa có điều kiện để cài đặt với hệ thống thực, và bài toán có khả năng chạy trên hệ thống thực nhƣng chƣa đáp ứng đƣợc về mặt thời gian thực. Do đó, trong tƣơng lai, tôi có hƣớng phát triển là: tôi sẽ tiếp tục tìm hiều và nghiên cứu về kiểm thử dựa trên mô hình với NModel trong hệ thống phản ứng có các trạng thái phức tạp, đáp ứng đƣợc về mặt thời gian thực.

TÀI LIỆU THAM KHẢO Tiếng Việt

1. TS. Lƣu Hồng Việt, “Tài liệu tóm tắt bài giảng Hệ thống điều khiển nhúng”, Đại học Bách Khoa Hà Nội.

Tiếng Anh

2. Colin Campbell, Margus Veanes, and Jonathan Jacky (2007, 2008), “NModel Reference”.

3. J. A. Cook J. S. Freudenberg (2008), “Embedded Software Architecture”, EECS 461.

4. Jonathan Jacky, Margus Veanes, Colin Campbell, Wolfram Schulte Cambridge University Press (2008, available December 2007), “Model-based Software Testing and Analysis with C#”, Cambridge University.

5. Juhan Ernits, Margus Veanes, and Johannes Helander (June 2008), “Model-Based Testing of Robots with NModel”.

6. Juhan Ernits, Rivo Roo, Jonathan Jacky, Margus Veanes (2009), “Model-Based Testing of Web Applications Using NModel”.

7. M. Veanes, C. Campbell, W. Grieskamp, L. Nachmanson, W. Schulte, and N. Tillmann (2005), Model-based testing of object-oriented reactive systems with Spec Explorer, Tech. Rep. MSR-TR-2005-59, Microsoft Research. Preliminary version of a book chapter in the forthcoming text book Formal Methods and Testing.

8. M. Broy, B. Jonsson, J.-P. Katoen, M. Leucker, and A. Pretschner (The volume is the outcome of a research seminar that was held in Schloss Dagstuhl in January 2004), editors, Model-Based Testing of Reactive Systems.

Website 9. http://nmodel.codeplex.com/ 10. http://blogs.msdn.com/b/specexplorer/archive/2009/10/27/what-is-model- based-testing.aspx 11. http://nmodelrs.berlios.de/ 12. http://www.kiemthuphanmem.com/blogs/3/24/model-based-testing-l-g-mbt) 13. http://voer.edu.vn/c/he-dieu-hanh-cho-cac-he-thong-nhung-hdh-thoi-gian- thuc/9f009757/07006533#.UzP9xc51mKE 14. http://www.testingvn.com/

PHỤ LỤC

HỆ THỐNG CLIENT/SERVER

Chƣơng trình mô hình contract client/server có tên là ClientServer: using NModel;

using NModel.Attributes; using NModel.Execution; namespace ClientServer {

public enum Socket { None, Created, Bound, Listening, Connecting, Connected, Disconnected, Closed }

public enum Phase { Send, ServerReceive, ClientReceive } public static class ClientServer

{

const double EmptyBuffer = double.MaxValue;

const double Temp2 = 99.9; // Temperature, 2 digits const double Temp3 = 100.0; // Temperature, 3 digits

// Biến trạng thái điều khiển

public static Socket serverSocket = Socket.None; public static Socket clientSocket = Socket.None; public static Phase phase = Phase.Send;

// Trạng thái dữ liệu

public static double clientBuffer = EmptyBuffer;

// Điều kiện trạng thái chấp nhận cho việc kiểm thử

[AcceptingStateCondition]

static bool BothClosed() {

return (serverSocket == Socket.Closed && clientSocket == Socket.Closed); }

// Các điều kiện và hành động cho phép của Server public static bool ServerSocketEnabled()

{

return (serverSocket == Socket.None); }

[Action]

public static void ServerSocket() {

serverSocket = Socket.Created; }

public static bool ServerBindEnabled() {

return (serverSocket == Socket.Created); }

[Action]

public static void ServerBind() {

serverSocket = Socket.Bound; }

public static bool ServerListenEnabled() {

return (serverSocket == Socket.Bound); }

[Action]

public static void ServerListen() {

serverSocket = Socket.Listening; }

public static bool ServerAcceptEnabled() {

}

[Action]

public static void ServerAccept() {

serverSocket = Socket.Connected; clientSocket = Socket.Connected; }

public static bool ServerReceiveEnabled() {

return (serverSocket == Socket.Connected && phase == Phase.ServerReceive); }

// Các hành động Send ở trong MP này không cần tham số

[Action]

public static void ServerReceive() {

phase = Phase.Send; }

public static bool ServerSendEnabled() {

return (serverSocket == Socket.Connected

&& phase == Phase.Send && clientSocket == Socket.Connected); }

// Dùng tham số ở đây, Server có thể gửi các nhiệt độ khác nhau [Action]

public static void ServerSend([Domain("Temperatures")] double datum) {

clientBuffer = datum;

phase = Phase.ClientReceive; }

// Tên miền cho tham số ServerSend là t static Set<double> Temperatures() {

return new Set<double>(Temp2, Temp3); }

public static bool ServerCloseConnectionEnabled() {

return (serverSocket == Socket.Connected); }

[Action]

public static void ServerCloseConnection() {

serverSocket = Socket.Disconnected; }

// Ngăn chặn Client bị treo

public static bool ServerCloseEnabled() {

return (serverSocket != Socket.None

// && serverSocket != Socket.Listening

&& serverSocket != Socket.Connected && serverSocket != Socket.Closed); }

[Action]

public static void ServerClose() {

serverSocket = Socket.Closed; }

// Các điều kiện và hành động được phép của Client public static bool ClientSocketEnabled()

{

return (clientSocket == Socket.None); }

[Action]

clientSocket = Socket.Created; }

public static bool ClientConnectEnabled() {

return (clientSocket == Socket.Created && serverSocket ==

Socket.Listening);

}

[Action]

public static void ClientConnect() {

clientSocket = Socket.Connecting; }

public static bool ClientSendEnabled() {

return (clientSocket == Socket.Connected && phase == Phase.Send); }

// Hành động Send của client ko có tham số

[Action]

public static void ClientSend() {

phase = Phase.ServerReceive; }

public static bool ClientReceiveEnabled() {

return (clientSocket == Socket.Connected && phase == Phase.ClientReceive); }

// Trả về giá trị cần thiết ở đây, server gửi các giá trị khác nhaue

[Action]

public static double ClientReceive() {

double t = clientBuffer; clientBuffer = EmptyBuffer; phase = Phase.Send;

return t; }

public static bool ClientCloseEnabled() {

return (clientSocket == Socket.Connected && phase == Phase.Send);

}

[Action] public static void ClientClose()

{

clientSocket = Socket.Closed; }

}

public static class Factory

{

public static ModelProgram Create() {

return new LibraryModelProgram(typeof(Factory).Assembly,"ClientServer"); }

}

Xây dựng test harness: using System;

using NModel.Conformance; using NModel.Terms;

namespace ClientServerImpl {

public class Stepper: IStepper

const string host = "127.0.0.1"; // localhost

Server s = new Server();

Client c = new Client();

public CompoundTerm DoAction(CompoundTerm action) {

switch (action.Name) {

case("Tests"): return null; // hành động đầu tiên trong chuỗi kiểm thử. case("ServerSocket"):

s.Socket(); return null; case("ServerBind"):

s.Bind(host,port); return null; case("ServerListen"):

s.Listen(); return null; case("ServerAccept"):

s.Accept(); return null; case("ServerReceive"):

s.Receive(); return null; case("ServerSend"):

// s.Send gửi một số double, không phải string!

s.Send((double)((Literal) action.Arguments[0]).Value); return null;

case("ServerCloseConnection"): s.CloseConnection(); return null; case("ServerClose"):

s.Close(); return null; case("ClientSocket"):

c.Socket(); return null; case("ClientConnect"):

c.Connect(host,port); return null; case("ClientSend"):

c.Send("T"); return null; case("ClientReceive_Start"):

// c.Receive trả về một số double, không phải string return CompoundTerm.Create("ClientReceive_Finish", c.Receive());

case("ClientClose"): c.Close(); return null;

default: throw new Exception("Unexpected action " + action); }

}

public void Reset() {

s = new Server(); c = new Client(); }

public static IStepper Create() {

return new Stepper(); }

}

Xây dựng các tệp tin dạng .txt cho công cụ mpv, otg, và ct: Tệp tin mpv_contract.txt:

/r:ClientServer.dll /mp:ClientServer /livenessCheckIsOn+

Tệp tin mpv_scenario.txt:

/fsm:Scenario.txt Tệp tin mpv_composition.txt: #Kết hợp MP hợp đồng với MP kịch bản /r:ClientServer.dll /mp:ClientServer /fsm:Scenario.txt /combineActions+ Tệp tin otg_contract.txt: # Referenced assembly /r:ClientServer.dll /mp:ClientServer /file:ContractTest.txt Tệp tin otg_scenario.txt:

# Tạo bộ kiểm thử MP hợp đồng kết hợp với MP kịch bản /r:ClientServer.dll

/mp:ClientServer /fsm:Scenario.txt /file:ScenarioTest.txt

Tệp tin ct_contract.txt:

# Thực hiện kiểm thử với bộ kiểm thử đƣợc tạo từ MP hợp đồng /r:Stepper.dll

/iut:ClientServerImpl.Stepper.Create /testSuite:..\Model\ContractTest.txt

Tệp tin ct_scenario.txt:

# Kiểm thử với bộ kiểm thử có kết hợp MP hợp đồng với MP kịch bản /r:Stepper.dll /iut:ClientServerImpl.Stepper.Create /testSuite:..\Model\ScenarioTest.txt Tệp tin ct_contract_random.txt: /r:Stepper.dll /iut:ClientServerImpl.Stepper.Create /r:..\Model\ClientServer.dll /mp:ClientServer /runs:1 Tệp tin ct_scenario_random.txt:

# Kiểm thử ngẫu nhiên với sự kết hợp của MP hợp đồng và MP kịch bản /r:Stepper.dll

/iut:ClientServerImpl.Stepper.Create /r:..\Model\ClientServer.dll

Một phần của tài liệu (LUẬN văn THẠC sĩ) nghiên cứu ứng dụng NModel” trong việc phát triển hệ thống nhúng thời gian thực (Trang 59)

Tải bản đầy đủ (PDF)

(74 trang)