最近想解決前端開發或測試中的兩個問題:一是界面UI的佈局適配,可否在測試的過程當中,經過命令操做真機打開相應頁面而後截屏,經過對圖片識別分類,發現有問題的圖片,而後及時修復;二是頁面性能分析,不少時候頁面只能在指定的Webview中使用,可否直接經過命令打開指定的頁面,分析頁面在真實APP中的性能,並生成報告。這兩個問題的前提就是經過命令直接操做手機App,帶着問題找線索,因而我就結識了Selenium
,下面將結合實例和你們分享一下。javascript
先看一下官網的解釋:html
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.前端
從上面的話咱們能夠知道3個點:java
一圖勝千言,Selenium在自動化測試中扮演的角色以下圖所示:
node
咱們的訴求是經過腳本控制本地和手機上的瀏覽器,甚至APP中的Webview,Selenuim正好提供了WebDriver API供咱們使用。從上面能夠知道Selenium支持多種語言,如python、go、javascript等,對於前端而言,首選固然是javascript。如下是相關的操做步驟:python
該環節主要是兩步:android
npm install selenium-webdriver --save
selenium-webdriver的說明文檔至關的贊,在selenium-webdriver包的目錄下有幾個文件:chrome.js、edge.js、ie.js、phantom.js等,這些都是selenium-webdriver針對不一樣的瀏覽器的webdriver的調用作了封裝,打開chrome.js,在文件的開頭有詳細的文檔說明。
chrome.js中提到了3種使用場景:分別是Headless Chrome、Customizing the ChromeDriver Server、Working with Android。而我須要的場景就是Working with Android。
實例代碼以下:git
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();
其中須要要點就是指定要操做的瀏覽器類型、APP包的名字、android程序的Activity名字。通常webview的內核都是基於webkit的,指定瀏覽器類型爲chrome便可,APP的包名和Activity名字能夠經過命令工具aapt獲取,關於aapt的詳細介紹能夠參考這篇博客。
經過以上兩步,就能夠經過node執行相應的js文件,實現經過命令來控制APP了,這裏是幾個我測試的demo,供你們下載。github
上面的操做涉及到了兩個核心,即瀏覽器提供的webdriver和瀏覽器(chrome/chromium)。selenium-webdriver的做用就是利用webdriver將瀏覽器啓動起來,並實現一系列自動操做。但究竟webdriver和瀏覽器是怎樣一個協同關係呢,從chrome.js文件的註釋中能夠找到一些線索。web
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先經過webdriver啓動了一個driver service,該service又啓動chrome,分別起在不一樣的端口。
經過查閱資料,能夠知道driver service在開啓chrome的同時,爲chrome安裝了一個Chrome Automation Extension
擴展程序,該擴展程序的描述是:Exposes extension APIs for automating Chrome
,經過查看其源碼,能夠看到launchApp、getWindowInfo等函數,主要是提供了一些操做chrome的相關方法。
一圖勝千言,selenium-webdriver的工做原理以下圖所示,該圖來源於網絡:
Tips:
上面知道了driver service與chrome之間的關係,知道默認狀況下driver service的生命週期和測試的Chrome session是同步的,意味着每次測試都須要開啓一個driver service,若是頻繁的開啓和關閉service,勢必會形成資源浪費。
針對這個狀況,官方的描述是這樣的:
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.
官方針對該狀況提出了兩個解決辦法:
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()
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);
前端自動化測試的道路是漫長的,對selenium的挖掘纔剛剛開始。本文並無解決引言中提到的兩個問題,selenium-webdriver只是解決了第一步,即經過命令行來操做app,後面將繼續學習,繼續總結分享。