最近想解決前端開(kāi)發(fā)或測試中的兩個(gè)問(wèn)題:一是界面UI的布局適配,能否在測試的過(guò)程中,通過(guò)命令操作真機打開(kāi)相應頁(yè)面然后截屏,通過(guò)對圖片識別分類(lèi),發(fā)現有問(wèn)題的圖片,然后及時(shí)修復;二是頁(yè)面性能分析,很多時(shí)候頁(yè)面只能在指定的Webview中使用,能否直接通過(guò)命令打開(kāi)指定的頁(yè)面,分析頁(yè)面在真實(shí)APP中的性能,并生成報告。這兩個(gè)問(wèn)題的前提就是通過(guò)命令直接操作手機App,帶著(zhù)問(wèn)題找線(xiàn)索,于是我就結識了Selenium
,下面將結合實(shí)例和大家分享一下。
先看一下官網(wǎng)的解釋?zhuān)?/p>
Selenium automates browsers. That's it! What you do with that power is entirely up to you. Primarily, it is for automating web applications for testing purposes, but is certainly not limited to just that. Boring web-based administration tasks can (and should!) be automated as well.
Selenium has the support of some of the largest browser vendors who have taken (or are taking) steps to make Selenium a native part of their browser. It is also the core technology in countless other browser automation tools, APIs and frameworks.
從上面的話(huà)我們可以知道3個(gè)點(diǎn):
一圖勝千言,Selenium在自動(dòng)化測試中扮演的角色如下圖所示:
我們的訴求是通過(guò)腳本控制本地和手機上的瀏覽器,甚至APP中的Webview,Selenuim正好提供了WebDriver API供我們使用。從上面可以知道Selenium支持多種語(yǔ)言,如python、go、javascript等,對于前端而言,首選當然是javascript。以下是相關(guān)的操作步驟:
該環(huán)節主要是兩步:
在項目中下載selenium-webdriver
npm install selenium-webdriver --save
下載瀏覽器提供的WebDriver,并將該命令文件放置在系統變量PATH下
我使用的是chrome的WebDriver,針對不同的chrome版本,需要下載不同版本的WebDriver,否則程序會(huì )報錯。網(wǎng)上有好心人已經(jīng)整理出了chrome的WebDriver與chrome的版本映射表,可以點(diǎn)擊查看。
selenium-webdriver的說(shuō)明文檔相當的贊,在selenium-webdriver包的目錄下有幾個(gè)文件:chrome.js、edge.js、ie.js、phantom.js等,這些都是selenium-webdriver針對不同的瀏覽器的webdriver的調用做了封裝,打開(kāi)chrome.js,在文件的開(kāi)頭有詳細的文檔說(shuō)明。
chrome.js中提到了3種使用場(chǎng)景:分別是Headless Chrome、Customizing the ChromeDriver Server、Working with Android。而我需要的場(chǎng)景就是Working with Android。
實(shí)例代碼如下:
let chrome = require('selenium-webdriver/chrome');
let {Builder} = require('selenium-webdriver');
let driver = new Builder()
.forBrowser('chrome')
.setChromeOptions(new chrome.Options()
.androidPackage('com.example')
.androidActivity('com.example.Activity'))
.build();
其中需要要點(diǎn)就是指定要操作的瀏覽器類(lèi)型、APP包的名字、android程序的Activity名字。一般webview的內核都是基于webkit的,指定瀏覽器類(lèi)型為chrome即可,APP的包名和Activity名字可以通過(guò)命令工具aapt獲取,關(guān)于aapt的詳細介紹可以參考這篇博客。
通過(guò)以上兩步,就可以通過(guò)node執行相應的js文件,實(shí)現通過(guò)命令來(lái)控制APP了,這里是幾個(gè)我測試的demo,供大家下載。
上面的操作涉及到了兩個(gè)核心,即瀏覽器提供的webdriver和瀏覽器(chrome/chromium)。selenium-webdriver的作用就是利用webdriver將瀏覽器啟動(dòng)起來(lái),并實(shí)現一系列自動(dòng)操作。但究竟webdriver和瀏覽器是怎樣一個(gè)協(xié)同關(guān)系呢,從chrome.js文件的注釋中可以找到一些線(xiàn)索。
By default, every Chrome session will use a single driver service, which is started the first time a Driver instance is created and terminated when this process exits. The default service will inherit its environment from the current process and direct all output to /dev/null. You may obtain a handle to this default service using getDefaultService getDefaultService() and change its configuration with setDefaultService setDefaultService().
從上面可以知道,selenium-webdriver先通過(guò)webdriver啟動(dòng)了一個(gè)driver service,該service又啟動(dòng)chrome,分別起在不同的端口。
通過(guò)查閱資料,可以知道driver service在開(kāi)啟chrome的同時(shí),為chrome安裝了一個(gè)Chrome Automation Extension
擴展程序,該擴展程序的描述是:Exposes extension APIs for automating Chrome
,通過(guò)查看其源碼,可以看到launchApp、getWindowInfo等函數,主要是提供了一些操作chrome的相關(guān)方法。
一圖勝千言,selenium-webdriver的工作原理如下圖所示,該圖來(lái)源于網(wǎng)絡(luò ):
Tips:
上面知道了driver service與chrome之間的關(guān)系,知道默認情況下driver service的生命周期和測試的Chrome session是同步的,意味著(zhù)每次測試都需要開(kāi)啟一個(gè)driver service,如果頻繁的開(kāi)啟和關(guān)閉service,勢必會(huì )造成資源浪費。
針對這個(gè)情況,官方的描述是這樣的:
The ChromeDriver class starts the ChromeDriver server process at creation and terminates it when quit is called. This can waste a significant amount of time for large test suites where a ChromeDriver instance is created per test.
官方針對該情況提出了兩個(gè)解決辦法:
Start the ChromeDriver server separately before running your tests, and connect to it using the Remote WebDriver.
即測試之前先單獨啟動(dòng)driver server,然后使用Remote WebDriver連接上driver server所在的端口。官方提供了一個(gè)python的示例:
import time
from selenium import webdriver
import selenium.webdriver.chrome.service as service
service = service.Service('/path/to/chromedriver')
service.start()
capabilities = {'chrome.binary': '/path/to/custom/chrome'}
driver = webdriver.Remote(service.service_url, capabilities)
driver.get('http://www.google.com/xhtml');
time.sleep(5) # Let the user actually see something!
driver.quit()
Use the ChromeDriverService. This is available for most languages and allows you to start/stop the ChromeDriver server yourself.
可自己創(chuàng )建一個(gè)driver,同時(shí)為這個(gè)driver指定相應的service。這樣不僅可以為driver提供個(gè)性化的服務(wù)(如log日志),還可以控制service的生命周期。
代碼如下:
let chrome = require('selenium-webdriver/chrome');
let service = new chrome.ServiceBuilder()
.loggingTo('/my/log/file.txt')
.enableVerboseLogging()
.build();
let options = new chrome.Options();
// configure browser options ...
let driver = chrome.Driver.createSession(options, service);
前端自動(dòng)化測試的道路是漫長(cháng)的,對selenium的挖掘才剛剛開(kāi)始。本文并沒(méi)有解決引言中提到的兩個(gè)問(wèn)題,selenium-webdriver只是解決了第一步,即通過(guò)命令行來(lái)操作app,后面將繼續學(xué)習,繼續總結分享。
原文轉自:http://www.cnblogs.com/wmhuang/p/8011815.html