Web自動化之Headless Chrome測試框架整合

41202197514發表於2017-07-11

使用Selenium操作headless chrome 推薦

簡介

WebDriver是一個, 定義了一套檢查和控制使用者代理(比如瀏覽器)的遠端控制介面,各大主流瀏覽器來實現這些介面以便呼叫控制介面來操作瀏覽器。

Selenium是一整套的Web自動化測試解決方案,配合WebDrive規範,實現了對各種使用者代理的適配(比如瀏覽器,PhantomJS等),透過操作瀏覽器的WebDriver介面來實現帶瀏覽器的Web自動化。

使用selenium-webdriver

  • selenium相關的
  • selenium-webdriver的
const webdriver = require('selenium-webdriver'),
    By = webdriver.By;

const driver = new webdriver.Builder()
    .forBrowser('chrome')
    .build();

driver.get('').then((args) => {
    // 獲取百度搜尋按鈕的 文字
    driver.findElement(By.id('su')).then((element) => {
        return element.getAttribute('value')
    }).then((btnName) => {
        console.log(btnName)
    });

    // 獲取百度首頁 title
    driver.getTitle().then((title) => {
        console.log(title);
    });
});

driver.quit(); 

使用browserstack-webdriver

只是獲取driver的方式不一樣,其他呼叫完全一樣

const webdriver = require('browserstack-webdriver'),
    By = webdriver.By;

// Input capabilities
const capabilities = {
    'browserName' : 'firefox',
    'browserstack.user' : BROWSERSTACK_USERNAME,
    'browserstack.key' : BROWSERSTACK_KEY
}

const driver = new webdriver.Builder().
usingServer('').
withCapabilities(capabilities).
build();

driver.get('').then((args) => {
    // 獲取百度搜尋按鈕的 文字
    driver.findElement(By.id('su')).then((element) => {
        return element.getAttribute('value')
    }).then((btnName) => {
        console.log(btnName)
    });

    // 獲取百度首頁 title
    driver.getTitle().then((title) => {
        console.log(title);
    });
});

driver.quit(); 

使用 chromedriver

chromedriver是一個編碼輔助,自動配置環境變數,不需要手動下載和配置環境變數,透過安裝chromedriver同時在程式碼中引入

require('chromedriver') 
更換獲取源的URL(使用如下任意一種就行)
  • 安裝過程新增引數,預設下載地址為

    npm install chromedriver --chromedriver_cdnurl= 
  • 新增如下內容到.npmrc檔案

chromedriver_cdnurl= 
  • 新增環境變數CHROMEDRIVER_CDNURL
CHROMEDRIVER_CDNURL= npm install chromedriver 
更換安裝的chromedriver檔案路徑
  • 安裝過程使用配置引數
npm install chromedriver --chromedriver_filepath=/path/to/chromedriver_mac64.zip 
  • 新增如下內容到.npmrc檔案
chromedriver_filepath=/path/to/chromedriver_mac64.zip 
  • 新增環境變數
CHROMEDRIVER_FILEPATH=/path/to/chromedriver_mac64.zip 

使用mocha + chai

簡介

mocha是一個可以執行在瀏覽器端和NodeJS環境的JavaScript測試框架,區別於類庫,框架定義好了流程,並呼叫你的程式碼。

chai是一個斷言庫,判斷結果是否符合預期。

例項程式碼

const chai = require('chai');

const chromeDriver = require('selenium-webdriver/chrome')

const webdriver = require('selenium-webdriver'),
    By = webdriver.By;

const driver = new webdriver.Builder()
    .forBrowser('chrome')
    .setChromeOptions(new chromeDriver.Options().addArguments(['headless']))
    .build();

describe('首頁載入測試',function(){
    // 獲取百度搜尋按鈕的 文字
    describe('按鈕文字',function(){
        it('按鈕文字必須等於',function(done){
            driver.get('').then(function(){
                driver.findElement(By.id('su')).then((element) => {
                    return element.getAttribute('value')
                }).then((btnName) => {
                    console.log(btnName);
                    chai.expect(btnName).to.equal('百度一下');
                    done();
                });
            });
        })

    });

    // 獲取百度首頁 title
    describe('首頁標題',function(){
        it('首頁標題應該為',function(done){
            driver.get('').then(function(){
                driver.getTitle().then((title) => {
                    console.log(title);
                    chai.expect(title).to.equal('百度一下,你就知道');
                    done();
                });
            });
        });
    });

    after(function(){
        driver.quit();
    })
}); 

使用Karma + mocha + chai

簡介

Karma是一個用JavaScript實現的測試執行器,實現瞭如下內容

  • 對各種常見框架、庫的適配
  • 各種常見程式碼預處理或轉譯
  • 各種執行的測試報告方案
  • 各種瀏覽器或類瀏覽器的適配
  • 各種編輯器的適配,內容變更,立即重新執行
  • 覆蓋率統計

安裝相應的依賴庫

npm i --save-dev karma karma-chrome-launcher karma-mocha karma-chai
npm i --save-dev mocha chai 

生成配置檔案

在工程目錄下執行如下命令

./node_modules/.bin/karma init 

一路按照提示操作即可,生成的配置檔案在工程目錄下karma.conf.js,內容大致如下:

// Karma configuration
// Generated on Mon Jul 10 2017 19:49:48 GMT+0800 (CST)

module.exports = function(config) {
  config.set({
    // base path that will be used to resolve all patterns (eg. files, exclude)
    basePath: '',
    // frameworks to use
    // available frameworks: 
    frameworks: ['mocha'],
    // list of files / patterns to load in the browser
    files: [
    ],
    // list of files to exclude
    exclude: [
    ],
    // preprocess matching files before serving them to the browser
    // available preprocessors: 
    preprocessors: {
    },
    // test results reporter to use
    // possible values: 'dots', 'progress'
    // available reporters: 
    reporters: ['progress'],
    // web server port
    port: 9876,
    // enable / disable colors in the output (reporters and logs)
    colors: true,
    // level of logging
    // possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG
    logLevel: config.LOG_INFO,
    // enable / disable watching file and executing tests whenever any file changes
    autoWatch: true,
    // start these browsers
    // available browser launchers: 
    browsers: ['Chrome'],
    // Continuous Integration mode
    // if true, Karma captures browsers, runs the tests and exits
    singleRun: false,
    // Concurrency level
    // how many browser should be started simultaneous
    concurrency: Infinity
  })
} 
調整配置支援headless chrome

可以到,檢視chrome相關的karma-launcher,有ChromeHeadless和ChromeCanaryHeadless這兩個headless驅動可以選擇。

調整配置支援ES6,新增webpack
npm i webpack karma-webpack babel-core babel-loader babel-preset-es2015 
調整配置增加測試覆蓋度
npm i babel-plugin-istanbul 
最終的到的Karma配置檔案

karma.conf.js

// Karma configuration
// Generated on Mon Jul 10 2017 19:49:48 GMT+0800 (CST)

module.exports = function(config) {
    config.set({
        // base path that will be used to resolve all patterns (eg. files, exclude)
        basePath: '',
        // frameworks to use
        // available frameworks: 
        frameworks: ['mocha','chai'],
        // list of files / patterns to load in the browser
        files: [
            'test/**/*.js'
        ],
        // list of files to exclude
        exclude: [
        ],
        // preprocess matching files before serving them to the browser
        // available preprocessors: 
        preprocessors: {
            'test/**/*.js': ['webpack']
        },
        // test results reporter to use
        // possible values: 'dots', 'progress'
        // available reporters: 
        reporters: ['progress', 'coverage'],
        coverageReporter: {
            type: 'html',
            dir: 'coverage/'
        },
        // web server port
        port: 9876,
        // enable / disable colors in the output (reporters and logs)
        colors: true,
        // level of logging
        // possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG
        logLevel: config.LOG_INFO,
        // enable / disable watching file and executing tests whenever any file changes
        autoWatch: true,
        // start these browsers
        // available browser launchers: 
        browsers: ['ChromeHeadless'],
        // Continuous Integration mode
        // if true, Karma captures browsers, runs the tests and exits
        singleRun: true,
        // Concurrency level
        // how many browser should be started simultaneous
        concurrency: Infinity,
        webpack: {
            module: {
                loaders: [{
                    test: /\.js$/,
                    loader: 'babel-loader',
                    exclude: /node_modules/,
                    query: {
                        presets: ['es2015'],
                        plugins: ['istanbul']
                    }
                }]
            }
        }
    })
} 

編寫程式碼

src/index.js

const isType = (data, type) => {
    return ['[object ', type, ']'].join('') === Object.prototype.toString.call(data)
};

const isFunction = (data) => {
    return isType(data, 'Function')
};

const isArray = (data) => {
    return isType(data, 'Array')
};

module.exports = {
    isType,
    isFunction,
    isArray
} 

編寫測試用例

test/index.js

const typeUtil = require('../src/index')

describe('index.js: ', () => {
  it('isFunction() should work fine.', () => {
    expect(typeUtil.isFunction(function(){})).to.equal(true)
    expect(typeUtil.isFunction(Object.prototype.toString)).to.equal(true)
  });

  it('isArray() should work file.', () => {
      expect(typeUtil.isArray([])).to.equal(true)
      expect(typeUtil.isArray({})).to.equal(false)
  })
}); 

執行測試

  • 在當前目錄下執行./node_modules/.bin/karma start
  • 或者新增如下程式碼到package.json
 "scripts": {
    "test": "karma start"
  } 

然後執行npm run test

檢視結果

  • 命令列能看到執行結果
  • 在工程目錄下的coverage目錄能看到相應的覆蓋率報告

存在的問題

Karma是將測試Case在瀏覽器中執行並檢視結果,當頁面的url 改變的時候,會影響到整個Karma的執行,會有類似Some of your tests did a full page reload!這樣的提示。上面開啟百度首頁檢查按鈕和title的例子在Karma中還沒有找到合適的方式寫出來。

參考資料

  1. Automated testing with Headless Chrome
  2. 使用HeadlessChrome做單頁應用SEO
  3. 基於HeadlessChrome的網頁自動化測試系統-FinalTest
  4. karma 測試框架的前世今生

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/20597700/viewspace-2141926/,如需轉載,請註明出處,否則將追究法律責任。

相關文章