【Appnium+C#+Winform自動化測試系列】一、獲取本機連接的設備、啟動多個Appnium和獲取本機啟動的Appnium
本系列內容,準備根據所完成的項目為基線,一步一步的把整個設計和實現過程梳理。
先從基本的一些環境問題入手,梳理清楚關於手機設備和Appnium。因為我們在後面的建立Appnium連接時,需要設備名字和啟動的Appnium實例和對應的端口號。
一、獲取手機設備
獲取本機連接的設備,我們可以通過adb命令通過控制臺來實現,在控制臺中輸入命令adb devices可得如下結果:
既然能
夠如此簡單的獲取到連接的設備,接下來也就是對控制臺文字進行處理分析,最後把需要內容獲取出來展示在下拉框裏即可.
對於獲取到的結果,我們只取attached後面部分,可通過字符串的截取實現。去掉空格和換行符後,就變成了一連串的字符,由device間隔開的設備名字了,這樣只需普通的字符處理即可完成。
實際代碼如下,可供參考:
/// <summary>
/// 獲取當前機器連接的終端設備
/// </summary>
/// <returns></returns>
public static string[] InitDevices()
{
System.Diagnostics.Process p = new System.Diagnostics.Process();
p.StartInfo.FileName = "cmd.exe";
p.StartInfo.UseShellExecute = false; //是否使用操作系統shell啟動
p.StartInfo.RedirectStandardOutput = true;//由調用程序獲取輸出信息
p.StartInfo.RedirectStandardError = true;//重定向標準錯誤輸出
p.StartInfo.CreateNoWindow = true;//不顯示程序窗口
p.Start();//啟動程序
//向cmd窗口發送輸入信息
p.StandardInput.WriteLine("adb devices" + "&exit");
p.StandardInput.AutoFlush = true;
//p.StandardInput.WriteLine("exit");
//向標準輸入寫入要執行的命令。這裏使用&是批處理命令的符號,表示前面一個命令不管是否執行成功都執行後面(exit)命令,如果不執行exit命令,後面調用ReadToEnd()方法會假死
//同類的符號還有&&和||前者表示必須前一個命令執行成功才會執行後面的命令,後者表示必須前一個命令執行失敗才會執行後面的命令
//獲取cmd窗口的輸出信息
string output = p.StandardOutput.ReadToEnd();
string[] Devices = output.Replace("\r\n", "").Split(new string[] { "attached" }, StringSplitOptions.RemoveEmptyEntries)[1].Replace("\t", "").Replace(" ", "").Split(new string[] { "device" }, StringSplitOptions.RemoveEmptyEntries);
p.WaitForExit();//等待程序執行完退出進程
p.Close();
return Devices;
}
二、如何啟動多個Appnium
按照平常的使用方法,直接雙擊Appnium程序後點擊啟動即可啟動一個默認端口為4723的Appnium實例。按照這種方法,貌似一臺機器只能運行一個Appnium了。
不過筆者發現,在啟動Appnium時,打印出一段代碼樣的東西:
通過這段代碼,我發現Appnium的啟動貌似是根據主要程序和一些配置來完成實例啟動的。既然這樣,那應該是可以通過修改IP、端口、平臺和版本來控制啟動的Appnium實例了。如果我想啟動多個的話,
應該是可以通過配置端口號來運行多個Appnium了。果然,直接復制命令和配置文件的絕對路徑,在控制臺中執行,然後再觀察對應的node程序,真的出現了!經過後期驗證,這個通過命令實例話的
Appnium是可以運行的。
以此可得,通過對端口作為參數,啟動Appnium實例的函數就這樣實現了:
/// <summary>
/// 啟動Appnium實例
/// </summary>
/// <param name="Port">啟動Appnium端口</param>
public static void BootAppnium(string Port)
{
System.Diagnostics.Process p = new System.Diagnostics.Process();
p.StartInfo.FileName = "cmd.exe";
p.StartInfo.UseShellExecute = false; //是否使用操作系統shell啟動
p.StartInfo.RedirectStandardInput = true;//接受來自調用程序的輸入信息
p.StartInfo.RedirectStandardOutput = true;//由調用程序獲取輸出信息
p.StartInfo.RedirectStandardError = true;//重定向標準錯誤輸出
p.StartInfo.CreateNoWindow = true;//不顯示程序窗口
p.Start();//啟動程序
//向cmd窗口發送輸入信息
string command = @"D:\Appium\node.exe D:\Appium\node_modules\appium\lib\server\main.js --address 127.0.0.1 --port " + Port + " --platform-name Android --platform-version 19 --automation-name Appium --language zh_CN --log-no-color" + "&exit";
p.StandardInput.WriteLine(command);
// p.StandardInput.WriteLine("netstat -aon|findstr \"127.0.0.1:47\"" + "&exit");
p.StandardInput.AutoFlush = true;
p.EnableRaisingEvents = true;
p.Close();
}
三、獲取本機啟動的Appnium
知道了如何啟動多個Appnium後,那獲取本機啟動的Appnium也就易如反掌了。我們可以通過獲取到node.exe程序的PID值,然後根據PID值來獲取對應的端口值了,當然我們在啟動端口的時候,最好是預先
設定好一些範圍,免得出現端口被占用的問題.
首先來獲取node.exe的PID值:
C:\Users\Zeech>tasklist /v |findstr "node"
node.exe 6076 Console 9 78,948 K Unknown ZEECH_LEE\Zeech 0:00:03 暫缺
其中6076即對應的PID值,因為PID值是當前系統唯一的,所以可通過PID值獲取到Appnium啟動的端口號了
C:\Users\Zeech>netstat -ano |findstr "6076"
TCP 127.0.0.1:4723 0.0.0.0:0 LISTENING 6076
代碼如下:
public static string getnodePID()
{
System.Diagnostics.Process p = new System.Diagnostics.Process();
p.StartInfo.FileName = "cmd.exe";
p.StartInfo.UseShellExecute = false; //是否使用操作系統shell啟動
p.StartInfo.RedirectStandardInput = true;//接受來自調用程序的輸入信息
p.StartInfo.RedirectStandardOutput = true;//由調用程序獲取輸出信息
p.StartInfo.RedirectStandardError = true;//重定向標準錯誤輸出
p.StartInfo.CreateNoWindow = true;//不顯示程序窗口
p.Start();//啟動程序
//向cmd窗口發送輸入信息
p.StandardInput.WriteLine("tasklist /v |findstr \"node.exe\"" + "&exit");
// p.StandardInput.WriteLine("netstat -aon|findstr \"127.0.0.1:472\"" + "&exit");
p.StandardInput.AutoFlush = true;
//p.StandardInput.WriteLine("exit");
//向標準輸入寫入要執行的命令。這裏使用&是批處理命令的符號,表示前面一個命令不管是否執行成功都執行後面(exit)命令,如果不執行exit命令,後面調用ReadToEnd()方法會假死
//同類的符號還有&&和||前者表示必須前一個命令執行成功才會執行後面的命令,後者表示必須前一個命令執行失敗才會執行後面的命令
//獲取cmd窗口的輸出信息
string output = p.StandardOutput.ReadToEnd();
p.WaitForExit();//等待程序執行完退出進程
p.Close();
string nodePID = (((output.Replace("\r\n", "").Replace(" ", "").Split(new string[] { "node.exe", "Console" }, StringSplitOptions.RemoveEmptyEntries))))[2].ToString();
return nodePID;
}
/// <summary>
/// 獲取當前機器運行的Appnium
/// </summary>
/// <returns></returns>
public static string [] InitAppnium()
{
System.Diagnostics.Process p = new System.Diagnostics.Process();
p.StartInfo.FileName = "cmd.exe";
p.StartInfo.UseShellExecute = false; //是否使用操作系統shell啟動
p.StartInfo.RedirectStandardInput = true;//接受來自調用程序的輸入信息
p.StartInfo.RedirectStandardOutput = true;//由調用程序獲取輸出信息
p.StartInfo.RedirectStandardError = true;//重定向標準錯誤輸出
p.StartInfo.CreateNoWindow = true;//不顯示程序窗口
p.Start();//啟動程序
//向cmd窗口發送輸入信息
p.StandardInput.WriteLine("netstat -aon|findstr \""+ getnodePID()+"\"" + "&exit");
// p.StandardInput.WriteLine("netstat -aon|findstr \"127.0.0.1:472\"" + "&exit");
p.StandardInput.AutoFlush = true;
//p.StandardInput.WriteLine("exit");
//向標準輸入寫入要執行的命令。這裏使用&是批處理命令的符號,表示前面一個命令不管是否執行成功都執行後面(exit)命令,如果不執行exit命令,後面調用ReadToEnd()方法會假死
//同類的符號還有&&和||前者表示必須前一個命令執行成功才會執行後面的命令,後者表示必須前一個命令執行失敗才會執行後面的命令
//獲取cmd窗口的輸出信息
string output = p.StandardOutput.ReadToEnd();
p.WaitForExit();//等待程序執行完退出進程
p.Close();
string[] Appniuma = (((output.Replace("\r\n", "").Replace(" ", "").Replace("0.0.0.0:0", "||0.0.0.0:0").Split(new string[] { "TCP", "6076" }, StringSplitOptions.RemoveEmptyEntries))));
List<string> Appnium=new List<string>();
for (int i = 0; i < Appniuma.Count(); i++)
{
if (i>1)
{
Appnium.Add(Appniuma[i]);
}
}
return Appnium.ToArray();
}
註意:這種字符串截取的過程可能會出現一些bug.例如,在某些情況下,該PID值恰好是某個端口號的部分,那也會誒篩選出來,最完美的做法是只匹配PID值,這樣處理一下就可以避免這種情況了.
當然,可能在其他的處理過程中同意會出現篩選不精確的情況,需要多次調試分析盡量做到精準.Windows下,可下載一個AWK插件,可以對列進行篩選處理會方便很多.在處理替換時,可能讀者會發
現Replace("0.0.0.0:0", "||0.0.0.0:0"),其實這裏的目的是隔開監聽狀體下的端口號,防止混亂.
四、銷毀Appnium實例
銷毀與創建過程互為逆過程,有了以上知識,處理起來就非常簡單了。只需要kill 實例程序node.exe即可.
直接上代碼:
/// <summary>
/// 銷毀Appnium實例
/// </summary>
public static void ExitAppnium()
{
System.Diagnostics.Process p = new System.Diagnostics.Process();
p.StartInfo.FileName = "cmd.exe";
p.StartInfo.UseShellExecute = false; //是否使用操作系統shell啟動
p.StartInfo.RedirectStandardInput = true;//接受來自調用程序的輸入信息
p.StartInfo.RedirectStandardOutput = true;//由調用程序獲取輸出信息
p.StartInfo.RedirectStandardError = true;//重定向標準錯誤輸出
p.StartInfo.CreateNoWindow = true;//不顯示程序窗口
p.Start();//啟動程序
//向cmd窗口發送輸入信息
p.StandardInput.WriteLine(@"taskkill /f /t /im node.exe" + "&exit");
p.StandardInput.AutoFlush = true;
p.EnableRaisingEvents = true;
p.Close();
}
五、總結
經過以上的梳理,在對環境的操作,需要用到大量的Windows命令。如果想實現一個完整的Windows平臺自動化測試,需要對cmd命令比較熟悉。同時要實現一個功能,最
快速便捷的方法就是去弄懂其原理。任何事情在明白原理的情況下,處理起來都是得心應手,代碼只是一個橋梁而已,相信以上的代碼寫出來後都會覺得非常簡單,可以說
幾乎全是一些字符串的處理。在測試的過程中,往往就需要對獲取的結果進行處理分析,如何精確的獲取到需要的信息將是測試是否成功的關鍵了。
謝謝大家,我已經迫不及待的構思下一篇博文了!
【Appnium+C#+Winform自動化測試系列】一、獲取本機連接的設備、啟動多個Appnium和獲取本機啟動的Appnium