uirecorder 模块化

2023-11-17

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

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

uirecorder 模块化 的相关文章

  • java web项目答辩答辩题总结(书本网上语言答辩+自己的语言答辩)

    答辩每个人的总分为1 5分 每个人主要问3个问题 开发流程 系统架构 项目模块 功能 项目得失重定向与转发 九个隐式对象 get与post的区辨 jsp有静态包含 动态包含 两者的区辨 什么是MVC web系统架构 java web项目答辩
  • Python使用管道、队列、zeromq进行IPC速度对比测试

    管道 import sys from multiprocessing import Process Pipe import time import result msg list for i in range 100 msg list ap
  • 对话框中添加视图方法- CScrollView

    对话框中使用视图方法 今天工作过程中 又遇到了显示图片问题 为此把以前的代码整理一下 通过使用自定义的类继承CScrollView类 是图片或文字等 等能够通过滑块进行自动操作显示 记录查询 步骤 1 建立基本对话框程序 添加一个stati
  • 软件测试包括哪些内容

    以下是一些需要考虑的步骤 1 得到需求 功能设计 内部设计说书和其他必要的文档 2 得到预算和进度要求 3 确定与项目有关的人员和他们的责任 对报告的要求 所需的标准和过程 例如发行过程 变更过程 等等 4 确定应用软件的高风险范围 建立优
  • 各种系统框架图简介(转载)

    原文出处 http space itpub net 6517 viewspace 609654 1 Spring 架构图 Spring 是一个开源 框架 是为了解决企业 应用程序开发复杂性而创建的 框架的主要优势之一就是其分层架构 分层架构
  • android分析monkey的anr

    1 根据anr信息和traces txt判断anr是发生在那个进程中 2 在文件夹logs4android x中搜索 ANR 或者在monkeylog中搜索 anr in 找到发生anr的时间 3 在文件夹logs4android x中搜索
  • MCS-51 汇编指令集(J开头的指令)

    MCS 51系列单片机指令以J开头的指令有8条 分别为 JB bit rel JBC bit rel JC rel JMP A DPTR JNB bit rel JNC rel JNZ rel JZ rel 1 JB bit rel 指令名
  • 接口测试总结

    第一部分 主要从问题出发 引入接口测试的相关内容并与前端测试进行简单对比 总结两者之前的区别与联系 但该部分只交代了怎么做和如何做 并没有解释为什么要做 第二部分 主要介绍为什么要做接口测试 并简单总结接口持续集成和接口质量评估相关内容 第
  • hdu2030 汉字统计

    hdu2030 汉字统计 Time Limit 2000 1000 MS Java Others Memory Limit 65536 32768 K Java Others Total Submission s 4080 Accepted
  • ASP.NET Core 中间件详解及项目实战

    前言 在上篇文章主要介绍了DotNetCore项目状况 本篇文章是我们在开发自己的项目中实际使用的 比较贴合实际应用 算是对中间件的一个深入使用了 不是简单的Hello World 如果你觉得本篇文章对你有用的话 不妨点个 推荐 目录 中间
  • 软件测试 接口测试 入门Jmeter 接口关联 提取器 断言 与fiddler配合使用 使Jmeter录制和创建脚本 操作数据库 持续集成测试

    文章目录 1 接口测试概述 1 1 什么是接口测试 1 2 接口分类 1 3 接口的设计风格分类 1 3 1 Soap架构 1 3 2 Rpc架构 1 3 3 RestFul架构 1 3 4 接口测试工具介绍 1 4 接口测试流程 2 Jm
  • 自学软件测试需要多久?怎么自学软件测试?自学软件测试可以找到工作吗? 绝对干货!

    一 前言 最近经常有很多朋友问我想要入行软件测试 但是都不知道该怎么学 这里详细的给大家说下 对于0基础的朋友 应该怎么去学习软件测试 学习软件测试有2条路可以选 1 找个靠谱的培训机构去培训啦 你就什么都不用想了 跟着培训结构认真的学习就
  • Fortify 代码扫描安装使用教程

    前言 Fortify 能够提供静态和动态应用程序安全测试技术 以及运行时应用程序监控和保护功能 为实现高效安全监测 Fortify具有源代码安全分析 可精准定位漏洞产生的路径 以及具有1分钟1万行的扫描速度 Fortify SCA 支持丰富
  • Selenium2+python自动化10-登录案例

    前言 前面几篇都是讲一些基础的定位方法 没具体的案例 小伙伴看起来比较枯燥 有不少小伙伴给小编提建议以后多出一些具体的案例 本篇就是拿部落论坛作为测试项目 写一个简单的登录测试脚本 在写登录脚本的时候呢 先要保证流程能跑起来 然后才是去想办
  • 组合测试方法PK正交分析方法

    测试过程中 我们经常遇到需要覆盖多个变化参数的测试场景 如我们测试BS配置控制客户端组织资源远程配置一个设备时 进行一个设备通道视频参数设置的各种组合测试 如下图 多数情况下 类似于这种多组合测试时 老员工则是依靠经验去进行有针对性的测试
  • 自动化测试——接口测试

    一 接口分类 1 内部接口 测试被测系统各个子模块之前的接口 或者测试被测系统提供给内部用户系统使用的接口 2 外部接口 被测系统调用外部的接口 系统对外提供的接口 接口测试重点 检查结论参数传递的正确性 输出结果的正确性及对各种异常情况的
  • 重命名文件或目录(renameTo)

    File or directory with old name File file new File oldname File or directory with new name File file2 new File newname R
  • 网管员牢记 10种较为常见的服务器管理错误

    网管员牢记 10种较为常见的服务器管理错误 网络管理阶层的工作就是保证网络的正常工作 从而使得职工们的工作不被打断 可问题在于事物并非总是按照理想状况发展 事实上经常会出现平地起风波的状况 其间有许多原因 这里我们只讨论10种较为常见的网管
  • 008-黑盒测试和白盒测试的优缺点

    黑盒测试和白盒测试的优缺点 黑盒测试的优点有 比较简单 不需要了解程序内部的代码及实现 与软件的内部实现无关 从用户角度出发 能很容易的知道用户会用到哪些功能 会遇到哪些问题 基于软件开发文档 所以也能知道软件实现了文档中的哪些功能 在做软
  • 如何从零开始搭建公司自动化测试框架?

    搭建的自动化测试框架要包括API测试 UI测试 APP测试三类 以上三类其实可以简化为两类 那就是 1 接口自动化测试框架搭建 2 UI自动化测试框架搭建 没问题 安排 且是手把手教你如何搭建以上两类自动化测试框架 回到这篇主题 刷到这个问

随机推荐