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 模块化 的相关文章

  • Python使用管道、队列、zeromq进行IPC速度对比测试

    管道 import sys from multiprocessing import Process Pipe import time import result msg list for i in range 100 msg list ap
  • SpringAOP来监控service层中每个方法的执行时间

    使用AOP来说 太方便了 并且特别适合这类场景 代码如下 这里是将要统计的信息写到log文件中 也可以设计成写入表中 package com ecsoft interceptor import org aspectj lang Procee
  • 【软件测试】linux命令-引用符号(反斜杠\、单引号‘‘、双引号““)

    引用符号在解析器中保护特殊元字符和参数扩展 其使用方法有3种 反斜杠 单引号 双引号 单引号和双引号必须匹配使用 均可在解析器中保护特殊元字符和通配符 但是单引号 硬转义 主要用于信息的原样输出 防止任何变量的扩展 双引号 软转义 允许变量
  • 登录界面测试用例设计

    登录界面测试用例设计 一 界面测试点 1 界面的设计风格是否与UI的设计风格统一 2 界面中的文字简洁易懂 3 界面中没有错别字 二 用户名与密码在输入时 要考虑 1 正确的用户名与正确的密码 2 正确的用户名与错误的密码 3 错误的用户名
  • Bicubic Interpolation (双三次插值)

    在Wikipedia http en wikipedia org wiki Bicubic interpolation 上找到了bicubic的描述 不过它只给出了知道导数情况下的公式 后来在CSDN上找到了C语言的算法描述 http to
  • 软件测试包括哪些内容

    以下是一些需要考虑的步骤 1 得到需求 功能设计 内部设计说书和其他必要的文档 2 得到预算和进度要求 3 确定与项目有关的人员和他们的责任 对报告的要求 所需的标准和过程 例如发行过程 变更过程 等等 4 确定应用软件的高风险范围 建立优
  • 白盒测试相关的一些知识

    在白盒测试中 可以使用各种测试方法进行测试 下面这篇文章 可能比较枯燥 如果不乐意读 可以先收藏 如果在你的工作中真遇到白盒测试的话 可以回过头再来看看 还是值得读一读 一般来说 白盒测试时要考虑以下5个问题 1 测试中尽量先用自动化工具来
  • Firefox 或将强制启用 HTTPS 链接

    Mozilla 在最新上线的 Firefox 76 Nightly 版本中引入可选的 HTTPS only 模式 该模式仅允许连接到 HTTPS 站点 如果一切进行顺利的话 Firefox 接下来可能会在稳定版中面向所有用户推出该项功能 H
  • 可连接点对象及示例(二)

    转载请标明是引用于 http blog csdn net chenyujing1234 例子代码 包括客户端与服务端 http www rayfile com zh cn files de82908f 7309 11e1 9db1 0015
  • HTTPRunner学习笔记

    HttpRunner 是一款面向 HTTP S 协议的通用测试框架 只需编写维护一份 YAML JSON 脚本 即可实现自动化测试 性能测试 线上监控 持续集成等多种测试需求 在yaml文件中组织测试用例 在命令行执行 参考 HTTPRun
  • 从零开始写一个Javascript解析器

    最近在研究 AST 之前有一篇文章 面试官 你了解过 Babel 吗 写过 Babel 插件吗 答 没有 卒 为什么要去了解它 因为懂得 AST 真的可以为所欲为 简单点说 使用 Javascript 运行Javascript代码 这篇文章
  • postman中进行SHA1或MD5签名

    大部分接口为了防御重放攻击 往往使用SHA1或者MD5对请求进行签名 例如 我们有如下请求 Request URL http xx xx xx xx nonce 123 timestamp 123 Body xxx xxx signatur
  • 袁红岗的编程感悟

    我自己知道 近几年也一直在用 但就是说不出来 直到最近几天才能够表达 叫作Think in Code 也就是用代码思考 同时也把代码当成自己思想表达的方式 正如哲学家用文字设计 诠释思想 程序员 说话 用的是代码 这就是一个程序员的境 界
  • Python开发环境Wing IDE如何查看调试数据

    Wing IDE具有一个十分有用的特性 就是处理复杂bug的时候可以以各种各样的方式查看调试数据值 这个功能具体是由Watch工具实现的 查看数据值 在PrintAsHTML中发生异常时 右键单击Stack Data工具中的本地数值 这将显
  • Selenium2+python自动化10-登录案例

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

    1 M V C Model View Controller 模式 视图 控制器 这是一种范型 模型对象正是应用系统存在的理由 你设计的对象 包含了数据 逻辑和其他在你的应用领域创建定制的类 视图通常是控件 用来显示和编辑 控制器位于二者中间
  • IntelliJ IDEA中如何使用JUnit4

    背景 最近参与了一个Anroid医疗项目 其中项目底层有很多基础类及通讯类 而且很多涉及复杂的字节操作还有多线程同步及状态机处理 这样的项目做一下TDD还是必要的 尽量项目前期把风险降低一些 现在的问题是本人使用的是IntelliJ开发的A
  • 金融类测试的总结

    金融测试前后端 前端 执行页面级测试用例 验证应用层基本功能 能是否和需求一致 页面风格是否一致 金额 利息 以及对应的状态是否正确等 后端 通过测试页面 录入测试用例 比对结果 为了看数字金额的准确性 也是确认金融底层的正确性以及逻辑性
  • 如何做自动化测试

    这个话题比较大 相信大家也都有自己的想法 我在这里写一些我自己的看法 请大家指教 什么叫做自动化测试工程师 首先 会使用自动化测试工具的测试人员不能够称之为完全的自动化测试人员 这类测试人员被称为 工具小子 Script Kid 这个阶段还
  • 软件测试 app自动化02 Appium常用的元素定位工具 元素的属性 元素定位方法

    文章目录 1 Appium常用的元素定位工具 1 1 uiautomatorviewer 1 2 Appium Inspector 1 3 Weditor 2 元素的属性 3 元素定位方法 小结 1 Appium常用的元素定位工具 1 1

随机推荐