Selenium + Nightwatch 自動化測試環境搭建


    • 首先要安裝 Java 7 或更高 ,(http://www.oracle.com/technetwork/java/javase/downloads/index.html) 並且 java 命令可正常執行才能測試噢~~ 最簡單的判斷方法就是打開自己的終端,輸入 java 並回車,看看是不是有 Java 運行。如果有命令不存在之類的提示,請重新安裝 Java 運行環境 (

    • Node.JS , 而且要確保 npm 命令可用,我想應該其實不用提醒的 ~
      https://nodejs.org/en/download/

開始搭建

1. 創建項目

我們來找個地方新建一個目錄,起名為 "my-test-toolkit",然后在目錄內使用終端運行 npm init -y 生成項目配置文件package.json

 

2. 安裝工具

然后我們將安裝 Selenium 與 Nightwatch。

  • 安裝 selenium-standalone:

    • npm install selenium-standalone --save-dev

  • 安裝 Nightwatch:

    • npm install nightwatch --save-dev

 

 

項目配置

我們先開始配置 Nightwatch,之前提到這是一款 Test Runner 來着,它負責讀取我們的測試腳本,為我們提供 API 來操作瀏覽器,幫我們控制 Selenium。

一. 配置 Nightwatch

  1. 首先,在項目根目錄建立文件 "nightwatch.json",這個文件用來存放 Nightwatch 的配置信息。創建完畢之后,在文件內寫入以下內容:

    {
         "src_folders": ["tests"], "output_folder": "reports", "custom_commands_path": "", "custom_assertions_path": "", "page_objects_path": "", "globals_path": "", "selenium": { "start_process": true, "server_path": "", "log_path": "", "host": "127.0.0.1", "port": 4444, "cli_args": { "webdriver.chrome.driver": "" } }, "test_settings": { "default": { "launch_url": "http://localhost", "selenium_port": 4444, "selenium_host": "localhost", "silent": true, "screenshots": { "enabled": false, "path": "" }, "desiredCapabilities": { "browserName": "firefox", "javascriptEnabled": true, "acceptSslCerts": true } }, "chrome" : { "desiredCapabilities": { "browserName": "chrome", "javascriptEnabled": true, "acceptSslCerts": true } } } } 

    nightwatch.json 的文件名是 不可以 修改的,因為 Nightwatch 每次啟動的時候都是從它讀取配置喔!這里的配置項很多,不過先不管它,我們接着創建文件。如果您希望查看 Nightwatch 的詳細配置,請點 這里

  2. 接着在項目根目錄下創建文件 "nightwatch.conf.js" ,同樣此文件名也是不可以修改的,因為 Nightwatch 每次啟動也會從它這里讀取配置喔~ (´・_・`)
    創建完畢后,打開文件,並寫入如下內容:

    const path = require('path') module.exports = (function (settings) { return settings; })(require('./nightwatch.json')) /* * Nightwatch 會從 nightwatch.json 中讀取配置。 * 不過如果存在 nightwatch.conf.js,將會變為首先從后者中讀取配置。 * nightwatch.conf.js 存在的意義是使用 JavaScript 動態生成配置信息。 * 如果配置信息是不需要代碼修改的,直接使用 nightwatch.json 就可以啦。 */
  3. 再次在項目根目錄建立文件 "startup.js",然后在文件內部寫入:

    require('nightwatch/bin/runner.js')

    這個文件就是我們測試的入口文件,以后我們要執行測試就要運行這個文件,命令為 node ./startup。入口文件的名字是可以按照喜好更改的,只要運行它就好啦。不過每次輸入 node ./startup 太麻煩了,所以我們將這條命令寫入 npm scripts 中 ~~~ 打開 "package.json",在 JSON 對象中建立 "script" 屬性,並寫入內容:

    {
        ...
        "scripts": { "start": "node ./startup.js" }, ... }

以后每次運行測試只要在項目根目錄中執行 npm start 就好了!(・∀・)
Nightwatch 的配置暫時告一段落(其實馬上就會回來………),接下來我們來處理 Selenium.

二. 配置 Selenium

Selenium 是自動化測試環境,它提供了測試服務器、啟動瀏覽器、網頁自動操作等功能,同時暴露 API 給 Nightwatch 供我們使用。

我們接下來將要告訴 Nightwatch 我們的 Selenium 安裝在哪里,啟動瀏覽器的 Driver 程序在哪里,然后建立 Selenium 的安裝腳本與手工啟動腳本,以便不時之需 ~~

Driver 是讓 Selenium 打開系統上已安裝的瀏覽器的程序。

  • 1. 建立 Selenium 的配置信息。
    在項目根目錄下建立文件夾 "build",並在其中創建文件 "selenium-conf.js",並寫入如下信息:

    const process = require('process')
    
    module.exports = {
        // Selenium 的版本配置信息。請在下方鏈接查詢最新版本。升級版本只需修改版本號即可。 // https://selenium-release.storage.googleapis.com/index.html selenium: { version: '2.53.1', baseURL: 'https://selenium-release.storage.googleapis.com' }, // Driver 用來啟動系統中安裝的瀏覽器,Selenium 默認使用 Firefox,如果不需要使用其他瀏覽器,則不需要額外安裝 Driver。 // 在此我們安裝 Chrome 的 driver 以便使用 Chrome 進行測試。 driver: { chrome: { // Chrome 瀏覽器啟動 Driver,請在下方鏈接查詢最新版本。 // https://chromedriver.storage.googleapis.com/index.html version: '2.22', arch: process.arch, baseURL: 'https://chromedriver.storage.googleapis.com' } } } 

    本配置信息包含 Selenium 本體配置與 Driver 配置。我們將在稍后動態載入這些配置。 本文件的目的是為了更好管理 Selenium 的版本。

  • 2. 告訴 Nightwatch,我的 Selenium 與 Driver 在哪里。
    再次打開項目根目錄下的 "nightwatch.conf.js" 文件,並這樣編輯:

    const seleniumConfig = require('./build/selenium-conf') const path = require('path') module.exports = (function (settings) { // 告訴 Nightwatch 我的 Selenium 在哪里。 settings.selenium.server_path = `${path.resolve()}/node_modules/selenium-standalone/.selenium/selenium-server/${seleniumConfig.selenium.version}-server.jar` // 設置 Chrome Driver, 讓 Selenium 有打開 Chrome 瀏覽器的能力。 settings.selenium.cli_args['webdriver.chrome.driver'] = `${path.resolve()}/node_modules/selenium-standalone/.selenium/chromedriver/${seleniumConfig.driver.chrome.version}-${seleniumConfig.driver.chrome.arch}-chromedriver` return settings; })(require('./nightwatch.json'))

我們新加了兩行配置,它們的作用如注釋所示。
同樣的,如果您希望查看更多的配置項,請點擊 這里

  • 3. 建立 Selenium 安裝腳本,一鍵安裝 Selenium。
    還記得上一章我們提過 selenium-standalone 只是用來安裝和管理 Selenium 的工具么?所以現在是時候用它來安裝 Selenium 了。我們將通過調取 selenium-standalone 的內置方法來實現自動安裝。在 "build" 文件夾中建立文件 "selenium-setup.js",並寫入如下信息:

    const selenium = require('selenium-standalone') const seleniumConfig = require('./selenium-conf.js') selenium.install({ version: seleniumConfig.selenium.version, baseURL: seleniumConfig.selenium.baseURL, drivers: seleniumConfig.driver, logger: function (message) { console.log(message) }, progressCb: function (totalLength, progressLength, chunkLength) {} }, function (err) { if (err) throw new Error(`Selenium 安裝錯誤: ${err}`) console.log('Selenium 安裝完成.') })

    同樣為了方便,我們將安裝命令寫入 npm scripts 中:

    {
        ...
        "scripts": { "start": "node ./startup.js", "selenium-setup": "node ./build/selenium-setup.js" }, ... }

    然后在項目根目錄執行 npm run selenium-setup 安裝 Selenium.

    當提示安裝完成后,一切就緒!(・∀・)

Selenium 與其 Driver 會安裝到 "node_modules/selenium-standalone/.selenium" 中。

  • 4. 想要手工啟動 Selenium?
    默認情況下,Selenium 是由 Nightwatch 啟動的,不需要手工干預,不過如果想要手工啟動當然是可以的啦。

    在 build 文件夾中建立文件 "selenium-start.js",並寫入如下信息:

    const selenium = require('selenium-standalone') const seleniumConfig = require('./selenium-conf.js') selenium.start({ drivers: seleniumConfig.driver }, function (err, child) { if (err) throw new Error(`Selenium 啟動失敗: ${err}`) console.log(`Selenium 已手工啟動,進程 PID: ${child.pid}`) console.log('當不再需要運行 Selenium 時可關閉此 PID 進程.') })

    然后同樣添加啟動命令至 npm scripts 中:

    {
        ...
        "scripts": { "start": "node ./startup.js", "selenium-setup": "node ./build/selenium-setup.js", "selenium-start": "node ./build/selenium-start.js" }, ... } 

    以后使用命令 npm run selenium-start 就可以手工啟動 Selenium 了。

搭建完了!

至此,我們的配置與安裝工作已經完成,項目結構應該為:

>
| -- build | | -- selenium-conf.js # Selenium 版本信息配置。 | | -- selenium-setup.js # Selenium 安裝命令腳本。 | | -- selenium-start.js # Selenium 啟動命令腳本。 | | -- nightwatch.conf.js # Nightwatch 動態配置文件。 | -- nightwatch.json # Nightwatch 配置文件。 | -- package.json # 項目信息配置文件。 | -- startup.js # 測試啟動入口文件。

“不過我好像看到 "nightwatch.json" 的配置很復雜,而我們確沒怎么動它?”
嗯~~ 到目前位置確實沒有太多需要改動的,不過還是要注意一個配置項:

  • 請注意 "desiredCapabilities" 下的 "browserName" 項,這是測試時將使用的瀏覽器,您可以修改為 chromeinternet explorerphantomjs,本文在介紹時只安裝了 Chrome 的 Driver,如果您需要使用其他瀏覽器,要安裝相應的 Driver 才可以正常使用。

  • 默認瀏覽器為 Firefox,如果您使用 Firefox 的話,不需要額外進行 Driver 的配置。

  • 所以,如果您需要使用 Chrome 的話請將 "browserName" 修改為 "chrome" 喔!

Driver 的文檔可參考這里
如果您在搭建過程中遇到困難,您可以從 Github 獲取在下已經搭建好的 Start Kit.

開始編寫測試用例

創建目錄存放測試用例

在項目根目錄新建一個名為 "tests" 的目錄,然后這里就用來存放我們即將編寫的測試用例文件。
那么這個文件夾能不能指向到其他地方去呢?當然可以,不過要修改一個小地方。

還記得 " nightwatch.json " 文件么?打開看看,第一項是不是叫 src_folders,然后值為 ["tests"]
我相信您已經懂了,這里就是定義測試用例存放目錄的地方,然后改成自己想要的目錄吧!

您可以在目錄中存放多個測試用例文件,且命名隨意,Nightwatch 將讀取目錄中所有的 JS 文件,如果符合測試用例格式,將會自動執行。

編寫一個簡單的測試用例

在 "tests" 目錄中建立一個測試用例文件 "demo.js",然后我們來寫一個沒什么用的小 demo!

這個 Demo 將打開 Bing,搜索 "what is microsoft",然后保存成截圖后退出。

OK,打開 "demo.js",添加以下內容:

module.exports = { 'Find the answer.': function (client) { // TODO... } }

module.exports 導出一個對象,對象的 Key 即為測試用例名稱,您可以編寫多個測試用例,Nightwatch 將依次執行。

您可以在測試用例中導入其他模塊並直接使用在測試邏輯中,這也是比 Phantom.JS 優秀的地方。

先寫到這里,您可能會對 cilent 感到陌生,所以還是要簡單介紹一下。

client 是代碼運行時 Nightwatch 提供的對象,所有對瀏覽器進行的操作都將使用此對象調取,比如 client.click("CSS Selector")client.getCookie(function () {...}),我們第一章說過的 "可以簡單理解為 Selenium 的控制軟件" 就是通過它體現的喔!

client 的所有 API 詳情見 這里

大致了解這東西的意思之后,就可以接着完善測試邏輯了:

module.exports = {
  'Find the answer.': function (client) { // 定義 Bing 頁面中的節點. const searchInput = '#sb_form_q' const searchBtn = '#sb_form_go' const question = 'what is microsoft' // 啟動瀏覽器並打開 bing.com. client.url('http://bing.com').maximizeWindow() // 確保 "body" 和輸入框可以使用. client.expect.element('body').to.be.present client.expect.element(searchInput).to.be.visible client.pause(2000) // 稍等兩秒. // 輸入 "what is microsoft" 然后搜索. client.setValue(searchInput, question) client.click(searchBtn) client.pause(2000) // 截一張圖然后保存到 "reports/answer.png". client.expect.element('body').to.be.present client.saveScreenshot('reports/answers.png') client.end() } }

來關注一下 expect ,是不是看起來很像自然語言?這些語句就是測試結果的驗證語句,就是我們希望得到的結果。比如client.expect.element('body').to.be.present.before(3000),意思就是 "希望 body 元素能在 3000 毫秒內初始化完畢"。

Nightwatch 支持 BDD-Style 與 Assert 斷言兩種風格,文檔可見 這里

關於 Assert、BDD、TDD 的更多內容請參照其他文章。

是不是確實沒什么用?畢竟是個簡單的 Demo 而已,哈哈。那么添加一個稍微復雜點的測試用例。

編寫另一個簡單的測試用例

這個 demo 將打開 Bilibili 直播 ,然后執行:

  • 打開首頁並等待加載完畢;

  • 檢查登陸按鈕是否存在;

  • 點擊登陸按鈕;

  • 填寫用戶名與密碼;

  • 點擊登陸;

  • 等待頁面加載;

  • 通過 Cookie 檢查是否已登陸;

  • 確保登陸后的用戶導航面板存在;

  • 鼠標移至頭像處打開導航面板;

  • 點擊退出登陸;

  • 等待頁面刷新后檢查 Cookie 是否已退出登陸;

  • 結束測試。

其實就是第一章的那個 Demo 圖干的事情了 (・∀・)這個 demo 不再啰嗦,直接放出代碼:

// Account setting.
const accountConfig = {
  username: 'USERNAME', password: 'PASSWORD', uid: '10000' } module.exports = { 'Bilibili Live Login Test': function (client) { client.url('http://live.bilibili.com').maximizeWindow() // Page Init. client.expect.element('body').to.be.present.before(3000) client.expect.element('.top-nav-login-btn.last').to.be.visible // Login. client.click('.top-nav-login-btn.last') client.waitForElementVisible('#bilibili-quick-login', 2000) client.frame(0) client.pause(2000) client.setValue('#login-username', accountConfig.username) client.setValue('#login-passwd', accountConfig.password) client.click('#login-submit') // Wait and check page has been reloaded. client.frameParent() client.pause(4000) client.expect.element('body').to.be.present.before(3000) // Check cookies to ensure we are signed in. client.getCookies(function (result) { result.value.forEach((value, index, array) => { if (value.name === 'DedeUserID') client.assert.equal(parseInt(value.value, 10), accountConfig.uid) }) }) // Move to User Avatar. client.expect.element('.user-avatar-link').to.be.visible client.moveToElement('.user-avatar-link', 5, 5) client.pause(800) client.expect.element('#top-nav-user-panel').to.be.visible // Logout. client.click('#top-nav-logout-link') client.pause(5000) client.expect.element('body').to.be.present.before(3000) // Check cookies again to ensure we are off. client.getCookies(function (result) { var logout = true result.value.forEach((value, index, array) => { if (value.name === 'LIVE_LOGIN_DATA') logout = false }) client.assert.equal(logout, true) }) client.pause(1000) client.end() } }

您可以新建一個文件,或者在之前的文件中繼續編寫。

運行測試用例

回到項目根目錄,執行 npm start,然后就可以看到瀏覽器自己測試了!
運行效果如下:

測試運行完畢之后,測試結果將打印在終端里,同時會生成到 reports 文件夾中。

您可以在 nightwatch.json 中修改 "output_folder" 來更換報告生成目錄。

需要注意的地方

您可能在使用中會遇到例如 “明明看到節點缺獲取不到”、“鼠標功能好像時好時壞” 等問題,在此給您一些建議:

  • 由於現在很多網站使用諸如 Angular、Vue 等框架構建,其節點可能為組件動態渲染,所以 Selenium 在執行測試時可能獲取的 Dom 樹為舊數據從而導致找不到節點,因此您可以執行等待語句確保節點出現后再進行測試。不過可能不是 100% 成功,這也是這套測試系統的短板之一。

  • 如果您在進行模擬鼠標的測試,您的鼠標指針可能會干擾您的測試,因此建議運行測試后將您的指針移動至屏幕外部,以避免干擾到瀏覽器測試。

  • 測試很可能因為頁面加載時間問題導致測試失敗,不過這也是 E2E 測試的特征所在,您可以修改您的測試邏輯,或致力縮短加載時間。

大功告成!

現在您已經擁有您自己的測試工具並且成功編寫了兩個測試用例!此處您應該為自己鼓掌!
您現在已經可以將 E2E 測試納入您的開發流程之中,在下相信這將對您的開發有不小的幫助。如果您有興趣,您也可以考慮 單元測試的可能性。

如果您沒能成功構建您的項目,您可以從這里獲取代碼。

同時像之前提到的,如果您在使用 Vue 構建您的項目,您可以使用 Vue-cli 來生成已經包含 Selenium 與 Nightwatch 的 Vue 種子項目,您可以在 test/e2e 中編寫您的測試用例。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM