本篇承接上篇Windows phone 應用開發[9]-單元測試,當在Unit TEst 確定了測試用例的方案.在單個模塊單元測試通過開始走模塊之間集成時.其實很多測試工作就可以開發人員手中開始向測試人員轉移.類似針對單個模塊,測試團隊可以根據已經確定測試用例批量執行.得到實際結果與期望結果進行比較.而這個過程測試執行者無需了解代碼如何執行.也就是俗稱黑盒測試.
而對於單個模塊的回歸測試而言.為了提高效率引入自動化測試的概念.可惜的是目前並沒有任何可用於Windows phone Application應用程序的自動化測試工具.曾在Silverlight中使用過自動化測試工具-Ranorex,花費點時間嘗試通過Ranorex在WP 上執行自動化測試.發現存在很多應用程序與測試工具之間很多不可控的問題.
那么對於單個模塊回歸測試而言.需要哪些過程可以自動化?分析如下:
自動化流程:
[1]:模擬器控制-啟動或關閉Windows phone 模擬器.
[2]: 自動在模擬器上安裝並執行測試用例應用程序.
[3]: 收集測試結果
[4]: 卸載測試用應用程序前恢復模擬器
首先來看看應用程序安裝執行過程.目前只能通過Application Development Tool部署真機上:
now,如果我們把這個過程自動化處理.問題就出現了如何在不使用Application Development Tool情況把XAP安裝包安裝到模擬器或真機上? 同樣針對模擬器控制.如何能夠在代碼自動控制並運行XAP安裝包?
針對這個問題.Windows phone 類庫中提供一個Microsoft.SmartDevice.Connectivity.DLL用來實現與模擬器或設備進行交互.現在針對原有解決方案添加一個命名為DeveiceAutomationTest_Desktop的Console類型應用程序用來做回歸測試自動化的控制台.解決方案結構如下:
要實現對模擬器交互控制 需要在控制台應用程序添加對Microsoft.SmartDevice.Connectivity.DLL引用,引用地址C:\Program Files (x86)\Common Files\microsoft shared\Phone Tools\CoreCon\10.0\Bin:
添加引用后,實現對應設備控制的操作.連接並安裝初始化XAP到模擬器中,添加一個設備控制類DeviceManager類,首先要根絕設備類型模擬器或真機獲取設備的控制設備的Device對象:
1: /// <summary>
2: /// Get Current Support Platform Device Object
3: /// </summary>
4: /// <param name="localId">Region Local Id</param>
5: /// <returns>Device Object</returns>
6: public static Device GetSupportPlatformDeviceObj(int localId,bool isDevice)
7: {
8: //Note By chenkai:
9: //1033 is the LCID for English, United States and 1031 is the LCID for German, Germany.
10: //Please Check List of Locale ID (LCID) Values as Assigned by Microsoft.
11: //http://msdn.microsoft.com/zh-cn/goglobal/bb964664.aspx
12: //Now Use English is 1031
13:
14: if (localId == 0)
15: localId = 1031;
16: Device currentDeviceObj = null;
17: DatastoreManager datastoreManagerObj = new DatastoreManager(localId);
18: Platform wp7Platform = datastoreManagerObj.GetPlatforms().Single(p => p.Name == "Windows Phone 7");
19: if (wp7Platform != null)
20: {
21: if (isDevice)
22: currentDeviceObj = wp7Platform.GetDevices().Single(x => x.Name == "Windows Phone Device");
23: else
24: currentDeviceObj = wp7Platform.GetDevices().Single(x => x.Name == "Windows Phone Emulator");
25: }
26: return currentDeviceObj;
27: }
localid是在初始化靜態 DatastoreManager 對象時是一個區域設置標識符 (LCID),這是一個標識語言、國家和/或地區的整數. 當然這里采用1031德國地區.針對這個區域Localid的設置請參考官方給出的List of Locale ID (LCID) Values as Assigned by Microsoft 列表.
獲取數據控制Device對象后.可以連接設備並把XAP包安裝並初始化到設備中:
1: /// <summary>
2: /// Connection Emulator Device
3: /// </summary>
4: /// <param name="deviceObj">Device Object</param>
5: /// <param name="applicationGuid">Application Guid</param>
6: /// <param name="iconFilePath">IconFile Path</param>
7: /// <param name="xapFileName">XapFile Name</param>
8: /// <returns>return is Connection Device</returns>
9: public static void ConnectionDeviceInstallApp(Device deviceObj,Guid applicationGuid,string iconFilePath,string xapFileName)
10: {
11: if (!string.IsNullOrEmpty(applicationGuid.ToString()))
12: {
13: try
14: {
15: deviceObj.Connect();
16: ApplicationManager.InstallApplicationAndLaunch(deviceObj, applicationGuid, iconFilePath, xapFileName);
17: }
18: finally
19: {
20: deviceObj.Disconnect();
21: }
22: }
23: }
這個方法中需要提供Device設備操作對象.以及XAP安裝包和對應應用程序圖標的文件路徑. 其實這里並不一定非得采用控制台的方式.也可以做一個Winform以可見UI的方式.至於Guid則是測試項目WP7AutomationTest_Demo.Test-WMAppmainfest.xml文件中的ProductId相對應:
1: <App xmlns="" ProductID="{b81d87a6-3afd-4f21-9a60-3c5ae0921fd2}" Title="WP7AutomationTest_Demo.Test"/>
該方法中執行了兩個操作.鏈接設備.安裝XAP包到設備中.安裝XAP操作通過ApplicationManager類中InstallApplicationAndLaunch方法 .定義如下:
1: public static void InstallApplicationAndLaunch(Device deviceObj, Guid applicationGuid, string iconFileName, string xapFileName)
2: {
3: if (!string.IsNullOrEmpty(applicationGuid.ToString()))
4: {
5: //Install and Luanch
6: UnstallApplicationAndClear(deviceObj, applicationGuid);
7: deviceObj.InstallApplication(applicationGuid, applicationGuid, "AutomationAPP", iconFileName, xapFileName);
8: RemoteApplication currentApplication = deviceObj.GetApplication(applicationGuid);
9: if (currentApplication != null)
10: currentApplication.Launch();
11: }
12: }
通過Device對象初始化XAP 並Lauch,.在執行安裝XAP之前 如果正在運行則立即中斷.如果已經安裝該應用程序則需刪除卸載:
1: public static void UnstallApplicationAndClear(Device deviceObj, Guid applicationGuid)
2: {
3: if(!string.IsNullOrEmpty(applicationGuid.ToString()))
4: {
5: if (deviceObj.IsApplicationInstalled(applicationGuid))
6: {
7: RemoteApplication remoteApplication = deviceObj.GetApplication(applicationGuid);
8: if (remoteApplication != null)
9: {
10: //Remove Application
11: remoteApplication.TerminateRunningInstances();
12: remoteApplication.Uninstall();
13: }
14: }
15: }
16: }
well.如此封裝號對設備的初始化的控制.開始執行ProgramMain 方法:
1: static void Main(string[] args)
2: {
3: //Base ApplicationInfo
4: string xapfile = @"..\..\..\WP7AutomationTest_Demo.Test\Bin\Debug\WP7AutomationTest_Demo.Test.xap";
5: string iconfile = @"..\..\..\WP7AutomationTest_Demo.Test\Bin\Debug\WApplicationIcon.png";
6: ApplicationBaseInfo currentBaseInfo = new ApplicationBaseInfo(xapfile, iconfile, new Guid("b81d87a6-3afd-4f21-9a60-3c5ae0921fd2"));
7:
8: //DeviceManager Object
9: Device deviceObj = DeviceManager.GetSupportPlatformDeviceObj(1031,false);
10: using (ServiceHost currentHost = new ServiceHost(typeof(TestResultReportService)))
11: {
12: currentHost.Open();
13: Console.WriteLine("Current Service is Open...");
14: Console.WriteLine("Connecting to Windows phone Emluator Device...");
15:
16: try
17: {
18: //Device Connection
19: deviceObj.Connect();
20: Console.WriteLine("Windows phone Emluator Device Connected...");
21: ApplicationManager.InstallApplicationAndLaunch(deviceObj, currentBaseInfo.ApplicationGuid, currentBaseInfo.IconFilePath, currentBaseInfo.XapFilePath);
22: Console.WriteLine("Wait For Run TestCase Compated...");
23:
24: lastendTestRunEvent.WaitOne(12000);
25:
26: Console.WriteLine("Test Case is Run Complate...");
27: ApplicationManager.UnstallApplicationAndClear(deviceObj, currentBaseInfo.ApplicationGuid);
28: Console.WriteLine("Application is UnStall and Clear...");
29: }
30: finally
31: {
32: deviceObj.Disconnect();
33: }
34:
35: //currentHost.Close();
36: }
Main方法執行的流程.首先部署XAP停止正在應用程序.並從設備中移除.然后連接設備 部署XAP包. 執行TEstCase測試用例.獲取測試用例反饋結果.卸載當前應用程序並清空數據狀態.回復測試運行前.測試效果:
正常運行時如果模擬器沒有運行會自動打開模擬器 安裝XAP包運行測試用例.當控制台獲取測試結果后.卸載當前當前測試用例.一個完整回歸測試流程就建立成功了.而發現可以把整個執行流程全部自動化代碼控制.當然可以把回歸測試在執行多條數據時多次自動化執行.整個執行流程控制台操作如下:
在main方法同時建立一個WCF服務.該服務的主要目的是在單元測試用例測試完成后通知控制台停止調用. 另外一個目的是把SUTF框架的測試結果傳遞給控制台.存在一個測試結果文件中保存在本地並輸出到控制台中:
1: public class TestResultReportService : ITestResultReportService
2: {
3: public void SaveTestResultFile(string filename, string filecontent)
4: {
5: var outputfile = Path.Combine(@"..\..\..\DeveiceAutomationTest_Desktop\Bin\Debug\", filename);
6: if (File.Exists(outputfile))
7: {
8: File.Delete(outputfile);
9: }
10: File.WriteAllText(outputfile, filecontent);
11: Console.WriteLine(filecontent);
12: }
13:
14: public void GetFinalTestResult(bool failure, int failures, int totalScenarios, string message)
15: {
16: Console.WriteLine(message);
17: Program.EndTestRun();
18: }
19: }
而針對測試用例應用程序WP7AutomationTest_Demo.Test需要額外引用該服務.重新建立一個TestBaseReportService類用來重寫TestReportingProvider實體類中方法實現.測試結果通過服務以消息的形式傳遞給控制台.保存在文件中: 首先添加引用:
1: using Microsoft.Silverlight.Testing;
2: using Microsoft.Silverlight.Testing.Harness;
3: using Microsoft.Silverlight.Testing.Service;
4: using Microsoft.VisualStudio.TestTools.UnitTesting;
重寫方法:
1: public class TestBaseReportService:TestReportingProvider
2: {
3: //ServiceClient
4: UnitTestService.TestResultReportServiceClient reportClient = new UnitTestService.TestResultReportServiceClient();
5: public TestBaseReportService(TestServiceProvider serviceProvider) : base(serviceProvider) { }
6:
7: public override void ReportFinalResult(Action<ServiceResult> callback, bool failure, int failures, int totalScenarios, string message)
8: {
9: this.IncrementBusyServiceCounter();
10: reportClient.SaveTestResultFileCompleted += (se, x) =>
11: {
12: this.DecrementBusyServiceCounter();
13: };
14: reportClient.GetFinalTestResultAsync(failure, failures, totalScenarios, message);
15: base.ReportFinalResult(callback, failure, failures, totalScenarios, message);
16: }
17:
18: public override void WriteLog(Action<ServiceResult> callback, string logName, string content)
19: {
20: this.IncrementBusyServiceCounter();
21: reportClient.SaveTestResultFileCompleted += (s, e) =>
22: {
23: this.DecrementBusyServiceCounter();
24: };
25: reportClient.SaveTestResultFileAsync(logName, content);
26: base.WriteLog(callback, logName, content);
27: }
28: }
ok。定義重寫服務之后還需要Silverlight Unit TESt FrameWork框架進行測試結果的關聯.這很關鍵.SUTF框架將通過該服務來提交報告. 在mainpage定義輸出的頁面添加如下Code:
1: var reportSetting = UnitTestSystem.CreateDefaultSettings();
2: if (reportSetting!=null)
3: {
4: reportSetting.TestService.RegisterService(TestServiceFeature.TestReporting, new TestBaseReportService(reportSetting.TestService));
5: }
一整個回歸測試自動化流程建立完畢",編譯通過執行:
well.可以看到把整個回歸測試整個流程完全自動化用Code處理了. 而控制台應用就類似自動化時可以復用處理的腳本一樣.可以復用.依然能夠看到控制台中存在幾個需要及時制定的變量類似.XAP 包路徑等.也可以封裝可見的UI指定.當我們修改審核玩測試用例后.就可以通過該控制台應用程序.定期執行自動化回歸的測試.生成測試報告.很有效保證代碼集成時質量.本篇只是提供自動化解決一種方案.
源碼如下: