uirecorder 模块化

uirecorder原生代码问题

原生js文件十分臃肿,所有依赖都在一个js中,一个case一个js文件,后期维护十分困难。

模块化

对原生js进行模块化提取出2部分,一部分是以it快为主的主要case流程代码,另一部分是执行it快的依赖及主要方法。

  1. 将原文件中的module.exports提取出来
module.exports = function(){
    let driver, testVars;
    before(function(){
        let self = this;
        driver = self.driver;
        testVars = self.testVars;
    });
    it('url: http://www.baidu.com', async function(){
        await driver.url(_(`http://www.baidu.com`));
    });
    it('waitBody: ', async function(){
        await driver.sleep(500).wait('body', 30000).html().then(function(code){
            isPageError(code).should.be.false;
        });
    });
    it('click: wd ( #kw, 163, 12, 0 )', async function(){
        await driver.sleep(300).wait('#kw', 30000)
               .sleep(300).mouseMove(163, 12).click(0);
    });
    it('click: 学术 ( //a[text()="学术"], 6, 9, 0 )', async function(){
        await driver.sleep(300).wait('//a[text()="学术"]', 30000)
               .sleep(300).mouseMove(6, 9).click(0);
    });
    it('waitBody: ', async function(){
        await driver.sleep(500).wait('body', 30000).html().then(function(code){
            isPageError(code).should.be.false;
        });
    });
    it('click: 贴吧 ( //a[text()="贴吧"], 3, 8, 0 )', async function(){
        await driver.sleep(300).wait('//a[text()="贴吧"]', 30000)
               .sleep(300).mouseMove(3, 8).click(0);
    });
    it('switchWindow: 1', async function(){
        await driver.sleep(500).switchWindow(1);
    });
    it('waitBody: ', async function(){
        await driver.sleep(500).wait('body', 30000).html().then(function(code){
            isPageError(code).should.be.false;
        });
    });
    it('click: kw1 ( #wd1, 69, 18, 0 )', async function(){
        await driver.sleep(300).wait('#wd1', 30000)
               .sleep(300).mouseMove(69, 18).click(0);
    });
    it('sendKeys: mu{BACK_SPACE}{BACK_SPACE}MU{BACK_SPACE}{BACK_SPACE}mushenji', async function(){
        await driver.sendKeys('mu{BACK_SPACE}{BACK_SPACE}MU{BACK_SPACE}{BACK_SPACE}mushenji');
    });
    it('click: 进入贴吧 ( //a[text()="进入贴吧"], 55, 15, 0 )', async function(){
        await driver.sleep(300).wait('//a[text()="进入贴吧"]', 30000)
               .sleep(300).mouseMove(55, 15).click(0);
    });
    it('waitBody: ', async function(){
        await driver.sleep(500).wait('body', 30000).html().then(function(code){
            isPageError(code).should.be.false;
        });
    });
    it('click: mushenji ( a > em, 22, 11, 0 )', async function(){
        await driver.sleep(300).wait('a > em', 30000)
               .sleep(300).mouseMove(22, 11).click(0);
    });
    it('switchWindow: 2', async function(){
        await driver.sleep(500).switchWindow(2);
    });
    it('waitBody: ', async function(){
        await driver.sleep(500).wait('body', 30000).html().then(function(code){
            isPageError(code).should.be.false;
        });
    });
    it('expect: text, a.card_title_fname, equal, 牧神记吧', async function(){
        await driver.sleep(300).wait('a.card_title_fname', 30000)
            .text()
            .should.not.be.a('error')
            .should.equal(_(`牧神记吧`));
    });
    
    function _(str){
        if(typeof str === 'string'){
            return str.replace(/\{\{(.+?)\}\}/g, function(all, key){
                return testVars[key] || '';
            });
        }
        else{
            return str;
        }
    }
};

function isPageError(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);
}
  1. 将剩余的执行module.exports的方法封装到类中
const fs = require('fs');
const path = require('path');
const chai = require("chai");
const should = chai.should();
const JWebDriver = require('jwebdriver');
chai.use(JWebDriver.chaiSupportChainPromise);
const resemble = require('resemblejs-node');
resemble.outputSettings({
    errorType: 'flatDifferenceIntensity'
});

class baseRun {
    constructor() { }
    runThisSpec(func,filename) {
        let rootPath = getRootPath();
        // 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,
                    });
                    if (proxy) {
                        sessionConfig.proxy = {
                            'proxyType': 'manual',
                            'httpProxy': proxy,
                            'sslProxy': proxy
                        }
                    }
                    else if (hosts) {
                        sessionConfig.hosts = hosts;
                    }
                    try {
                        self.driver = driver.session(sessionConfig).windowSize(1024, 768).config({
                            pageloadTimeout: 30000, // page onload timeout
                            scriptTimeout: 5000, // sync script timeout
                            asyncScriptTimeout: 10000 // async script timeout
                        });
                    } catch (e) {
                        console.log(e);
                    }
                    let strs = filename.split('\\');
                    let thisName = strs[strs.length -1];
                    self.testVars = testVars;
                    let casePath = path.dirname(caseName)+'/'+thisName;
                    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;
                });

                func();

                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 + ' -->\n' + html;
                            fs.writeFileSync(filepath + '.html', html);
                            let cookies = await driver.cookies();
                            fs.writeFileSync(filepath + '.cookie', JSON.stringify(cookies));
                            appendToContext(self, filepath + '.png');
                        }
                        catch (e) { }
                    }
                });
                after(function () {
                    return this.driver.close();
                });
            });
        });
    }

    callSpec(name) {
        try {
            require(rootPath + '/' + name)();
        }
        catch (e) {
            console.log(e)
            process.exit(1);
        }
    }
}

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 isPageError(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 appendToContext(mocha, content) {
    try {
        const test = mocha.currentTest || mocha.test;

        if (!test.context) {
            test.context = content;
        } else if (Array.isArray(test.context)) {
            test.context.push(content);
        } else {
            test.context = [test.context];
            test.context.push(content);
        }
    } catch (e) {
        console.log('error', e);
    }
};

function catchError(error) {

}
baseRun.rootPath = getRootPath();
module.exports = baseRun;
  1. 通过给引入class,调用方法传参的方式编写case
const baseRun = require('../commons/base/baseRun.js');

const thisSpec = function() {
    require('./dome1/demo1')();
}
if (module.parent && /mocha\.js/.test(module.parent.id)) {
    const run = new baseRun();
    
    run.runThisSpec(thisSpec,__filename);
}

思考

1、上面的相对路径可以换成绝对路径
2、class的封装太简单
3、可以自设置class来完成自己想要达到的结果
4、这里还有好多东西可以配置成默认设置

有关资料

mocha官方网站 --这个uirecorder依赖的测试框架
一些前辈关羽mocha官方的中文翻译博客
macaca --这个是产生报告的,暂时没有更多了解
uirecorder官方文档,里面有介绍安装、使用等很多介绍。
jwebdriver --类似于webdriver

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值