• UIRecorder环境搭建及录制实现


     前天看TesterHome提到UI录制做UI自动化,很感兴趣,前来学习学习。

    参考:https://github.com/alibaba/uirecorder/blob/master/doc/zh-cn/readme.md

    UIRecorder是一款基于WebDriver、Chrome浏览器、NodeJs等方案共同打造的零成本自动化解决方案。

    基于几乎零成本的录制方案,我们让任何一个完全没有自动化经验的人,可以1分钟录制出可读性高,且强大的自动化脚本。

    让所有开发和测试能够最低成本的获得自动化测试的能力,把重复又枯燥的测试工作全部交给计算机,彻底的提高测试效率,解放我们的生产力。

    UIRecorder安装

    1. 安装jdk

    2. 安装node.js,同时安装了npm,需要加上环境变量

    3. 安装cnpm

    npm install -g cnpm --registry=https://registry.npm.taobao.org

    4. 安装uirecorder

    cnpm install uirecorder mocha -g

    安装相关依赖:cnpm install jwebdriver expect.js mocha-generators faker --save-dev 

    5. 下载selenium-standaloneselenium-server-standalone-3.4.0.jar

    6. 启动selenium-server

    7. 下载chromedriver.exe置于chrome安装目录下和python安装目录下

    8. 下载chrome 浏览器59版本以上

    9. 录制脚本

    cmd切换到Duirecorder目录运行:uirecorder start sample/test4.js

    10. 安装Mocha

    cnpm install mochawesome

    11. 生成测试报告

    mocha  sample/test4.js --reporter mochawesome

    注:如果没有第7步,会报错如下:

     1) sample/test4 : chrome "before all" hook:

         Error: the string "The path to the driver executable must be set by the webdriver.chrome.driver system property; for more information, see https://github.com/SeleniumHQ/selenium/wiki/ChromeDriver. The latest version can be downloaded from http://chromedriver.storage.googleapis.com/index.html" was thrown, throw an Error :)

          at <anonymous>

          at process._tickCallback (internal/process/next_tick.js:188:7)

      2) sample/test4 : chrome "after all" hook:

         Error: the string "The path to the driver executable must be set by the webdriver.chrome.driver system property; for more information, see https://github.com/SeleniumHQ/selenium/wiki/ChromeDriver. The latest version can be downloaded from http://chromedriver.storage.googleapis.com/index.html" was thrown, throw an Error :)

          at <anonymous>

    查看录制脚本

    const fs = require('fs');
    const path = require('path');
    const chai = require("chai");   //引用chai这个断言库
    const should = chai.should();
    const JWebDriver = require('jwebdriver');
    chai.use(JWebDriver.chaiSupportChainPromise);  //使用js promise方法的中间件,之后的异步方法可以使用.then()
    const resemble = require('resemblejs-node');
    resemble.outputSettings({
        errorType: 'flatDifferenceIntensity'
    });
    
    const rootPath = getRootPath();
    
    module.exports = function(){
    
        let driver, testVars;
    
        before(function(){
            let self = this;
            driver = self.driver;
            testVars = self.testVars;
        });
    
        it('url: https://h5.ele.me/login/#redirect=https%3A%2F%2Fwww.ele.me%2F', async function(){
            await driver.url(_(`https://h5.ele.me/login/#redirect=https%3A%2F%2Fwww.ele.me%2F`));
        });
    
        it('waitBody: ', async function(){
            await driver.sleep(500).wait('body', 30000).html().then(function(code){
                isPageError(code).should.be.false;     //等价于isPageError(code).chai.should().be.false;
            });
        });
    
        it('click: section:nth-child(1) > input[type="tel"]:nth-child(1), 114, 14, 0', async function(){
            await driver.sleep(300).wait('section:nth-child(1) > input[type="tel"]:nth-child(1)', 30000)
                   .sleep(300).mouseMove(114, 14).click(0);
        });
    
        it('sendKeys: 15074{BACK_SPACE}2421785', async function(){
            await driver.sendKeys('15074{BACK_SPACE}2421785');
        });
    
        it('click: 获取验证码 ( button.CountButton-3e-kd, 36, 4, 0 )', async function(){
            await driver.sleep(300).wait('button.CountButton-3e-kd', 30000)
                   .sleep(300).mouseMove(36, 4).click(0);
        });
    
        it('sendKeys: 974926', async function(){
            await driver.sendKeys('974926');
        });
    
        it('click: 登录 ( button.SubmitButton-2wG4T, 230, 14, 0 )', async function(){
            await driver.sleep(300).wait('button.SubmitButton-2wG4T', 30000)
                   .sleep(300).mouseMove(230, 14).click(0);
        });
    
        it('waitBody: ', async function(){
            await driver.sleep(500).wait('body', 30000).html().then(function(code){
                isPageError(code).should.be.false;
            });
        });
    
        function _(str){
            if(typeof str === 'string'){
                return str.replace(/{{(.+?)}}/g, function(all, key){
                    return testVars[key] || '';
                });
            }
            else{
                return str;
            }
        }
    
    };
    
    if(module.parent && /mocha.js/.test(module.parent.id)){
        runThisSpec();
    }
    
    function runThisSpec(){
        // read config
        let webdriver = process.env['webdriver'] || '';
        let proxy = process.env['wdproxy'] || '';
        let config = require(rootPath + '/config.json');
        let webdriverConfig = Object.assign({},config.webdriver);
        let host = webdriverConfig.host;
        let port = webdriverConfig.port || 4444;
        let match = webdriver.match(/([^:]+)(?::(d+))?/);
        if(match){
            host = match[1] || host;
            port = match[2] || port;
        }
        let testVars = config.vars;
        let browsers = webdriverConfig.browsers;
        browsers = browsers.replace(/^s+|s+$/g, '');
        delete webdriverConfig.host;
        delete webdriverConfig.port;
        delete webdriverConfig.browsers;
    
        // read hosts
        let hostsPath = rootPath + '/hosts';
        let hosts = '';
        if(fs.existsSync(hostsPath)){
            hosts = fs.readFileSync(hostsPath).toString();
        }
        let specName = path.relative(rootPath, __filename).replace(/\/g,'/').replace(/.js$/,'');
    
        browsers.split(/s*,s*/).forEach(function(browserName){
            let caseName = specName + ' : ' + browserName;
    
            let browserInfo = browserName.split(' ');
            browserName = browserInfo[0];
            let browserVersion = browserInfo[1];
    
            describe(caseName, function(){
    
                this.timeout(600000);
                this.slow(1000);
    
                let driver;
                before(function(){
                    let self = this;
                    let driver = new JWebDriver({
                        'host': host,
                        'port': port
                    });
                    let sessionConfig = Object.assign({}, webdriverConfig, {
                        'browserName': browserName,
                        'version': browserVersion,
                        'ie.ensureCleanSession': true,
                        'chromeOptions': {
                            'args': ['--enable-automation']
                        }
                    });
                    if(proxy){
                        sessionConfig.proxy = {
                            'proxyType': 'manual',
                            'httpProxy': proxy,
                            'sslProxy': proxy
                        }
                    }
                    else if(hosts){
                        sessionConfig.hosts = hosts;
                    }
                    self.driver = driver.session(sessionConfig).maximize().config({
                        pageloadTimeout: 30000, // page onload timeout
                        scriptTimeout: 5000, // sync script timeout
                        asyncScriptTimeout: 10000 // async script timeout
                    });
                    self.testVars = testVars;
                    let casePath = path.dirname(caseName);
                    self.screenshotPath = rootPath + '/screenshots/' + casePath;
                    self.diffbasePath = rootPath + '/diffbase/' + casePath;
                    self.caseName = caseName.replace(/.*//g, '').replace(/s*[:.:-s]s*/g, '_');
                    mkdirs(self.screenshotPath);
                    mkdirs(self.diffbasePath);
                    self.stepId = 0;
                    return self.driver;
                });
    
                module.exports();
    
                beforeEach(function(){
                    let self = this;
                    self.stepId ++;
                    if(self.skipAll){
                        self.skip();
                    }
                });
    
                afterEach(async function(){
                    let self = this;
                    let currentTest = self.currentTest;
                    let title = currentTest.title;
                    if(currentTest.state === 'failed' && /^(url|waitBody|switchWindow|switchFrame):/.test(title)){
                        self.skipAll = true;
                    }
                    if(!/^(closeWindow):/.test(title)){
                        let filepath = self.screenshotPath + '/' + self.caseName + '_' + self.stepId;
                        let driver = self.driver;
                        try{
                            // catch error when get alert msg
                            await driver.getScreenshot(filepath + '.png');
                            let url = await driver.url();
                            let html = await driver.source();
                            html = '<!--url: '+url+' -->
    ' + html;
                            fs.writeFileSync(filepath + '.html', html);
                            let cookies = await driver.cookies();
                            fs.writeFileSync(filepath + '.cookie', JSON.stringify(cookies));
                        }
                        catch(e){}
                    }
                });
    
                after(function(){
                    return this.driver.close();
                });
    
            });
        });
    }
    
    function getRootPath(){
        let rootPath = path.resolve(__dirname);
        while(rootPath){
            if(fs.existsSync(rootPath + '/config.json')){
                break;
            }
            rootPath = rootPath.substring(0, rootPath.lastIndexOf(path.sep));
        }
        return rootPath;
    }
    
    function mkdirs(dirname){
        if(fs.existsSync(dirname)){
            return true;
        }else{
            if(mkdirs(path.dirname(dirname))){
                fs.mkdirSync(dirname);
                return true;
            }
        }
    }
    
    function callSpec(name){
        try{
            require(rootPath + '/' + name)();
        }
        catch(e){
            console.log(e)
            process.exit(1);
        }
    }
    
    function isPageError(code){ //code为空或code包含那一串字母,就返回真,其他为假
        return code == '' || / jscontent="errorCode" jstcache="d+"|diagnoseConnectionAndRefresh|dnserror_unavailable_header|id="reportCertificateErrorRetry"|400 Bad Request|403 Forbidden|404 Not Found|500 Internal Server Error|502 Bad Gateway|503 Service Temporarily Unavailable|504 Gateway Time-out/i.test(code);
    }
    
    function catchError(error){
    
    }

    注:录制脚本是基于Mocha框架实现的,请参考http://www.ruanyifeng.com/blog/2015/12/a-mocha-tutorial-of-examples.html

  • 相关阅读:
    实现第三方系统单点登录
    python爬虫
    webot设备motor的api
    webots学习
    python学习算术运算
    python快捷键与命令函数
    python学习构造和析构
    python学习对象相关的bif
    python学习对象:拾遗
    matlab基础知识
  • 原文地址:https://www.cnblogs.com/Ryana/p/9811201.html
Copyright © 2020-2023  润新知