如何进行前端自动化测试

  • 如何进行前端自动化测试
  • 使用Puppeteer进行前端自动化测试
    • 使用Puppeteer进行前端自动化测试步骤
    • 使用示例

如何进行前端自动化测试

前端自动化测试是确保前端应用程序在各种情况下都能正常工作的关键。以下是进行前端自动化测试的一般步骤:

  1. 选择适合的测试框架

选择一个适合你项目的前端测试框架是很重要的。一些常见的前端测试框架包括:Jasmine、Mocha、Jest和Cypress等。这些框架都提供了丰富的功能和断言库,可以帮助你编写和运行测试。

  1. 编写测试用例

根据你的需求,编写测试用例来覆盖你的前端代码。测试用例应该涵盖各种场景和边界条件,以确保应用在各种情况下都能正常工作。例如,可以测试用户界面的交互,验证表单输入的有效性,或者检查特定功能是否按预期工作等。

  1. 运行测试

使用所选的测试框架来运行你编写的测试用例。测试框架通常提供了命令行接口或者图形界面来运行测试。你可以选择运行所有的测试用例,或者只运行特定的测试套件或测试文件。

  1. 断言和验证结果

在测试用例中使用断言库来验证测试结果。断言库提供了各种函数和方法,用于比较实际结果与预期结果是否一致。如果断言失败,测试框架会显示详细的错误信息,帮助你快速定位问题。

  1. 集成到持续集成流程

为了实现持续集成和自动化构建,将前端自动化测试集成到你的持续集成流程中是很重要的。这样可以确保在每次代码提交或者构建时都运行测试,并及时发现潜在的问题。

  1. 定期维护和更新测试

随着应用的不断开发和演变,测试用例也需要进行维护和更新。当你添加新功能或修复bug时,确保相应的测试用例也得到更新,以反映应用的最新状态。

总结起来,前端自动化测试的关键是选择适合的测试框架,编写全面的测试用例,运行并验证测试结果,并将其集成到持续集成流程中。这样可以保证你的前端应用在不断变化的环境中始终保持稳定和可靠。

更多详细内容,请微信搜索“前端爱好者戳我 查看

使用Puppeteer进行前端自动化测试

Puppeteer 是一个控制 headless Chrome 的 Node.js API 。它是一个 Node.js 库,通过 DevTools 协议提供了一个高级的 API 来控制 headless Chrome。它还可以配置为使用完整的(非 headless)Chrome。

在浏览器中手动完成的大多数事情都可以通过使用 Puppeteer 完成,下面是一些入门的例子:

  • 生成屏幕截图和 PDF 页面
  • 检索 SPA 并生成预渲染内容(即 “SSR”)
  • 从网站上爬取内容
  • 自动提交表单,UI 测试,键盘输入等
  • 创建一个最新的自动测试环境。使用最新的 JavaScript 和浏览器功能,在最新版本的 Chrome 中直接运行测试
  • 捕获网站的时间线跟踪,以帮助诊断性能问题

使用Puppeteer进行前端自动化测试步骤

使用Puppeteer进行前端自动化测试,需要按照以下步骤进行:

  1. 安装Puppeteer

Puppeteer是基于Node.js的库,因此首先需要在终端中使用npm安装Puppeteer:

npm install puppeteer
  1. 编写测试脚本

在安装了Puppeteer之后,可以在测试脚本中引入它。以下是一个简单的示例:

const puppeteer = require('puppeteer');

(async () => {
  const browser = await puppeteer.launch();
  const page = await browser.newPage();
  await page.goto('https://www.google.com');
  await page.type('input[name="q"]', 'puppeteer');
  await page.click('input[type="submit"]');
  await page.waitForNavigation();
  console.log('Title:', await page.title());
  await browser.close();
})();

上面的代码打开一个浏览器窗口,导航到Google页面,在搜索框中键入“puppeteer”,并点击提交按钮。然后等待页面导航完成,打印页面标题,并关闭浏览器。

  1. 运行测试脚本

可以通过以下命令运行测试脚本:

node test.js

这将启动一个新的Chromium浏览器实例,并执行测试脚本。

  1. 进一步学习和使用

以上是一个简单的Puppeteer测试脚本示例,你可以根据具体情况进行修改和扩展。

另外,Puppeteer提供了丰富的API,可以模拟用户操作、截图、网络拦截等,可以去Puppeteer官网学习更多内容:https://pptr.dev/

使用示例

const puppeteer = require('puppeteer');
const Imap = require('imap'),
    inspect = require('util').inspect;
const MailParser = require("mailparser").MailParser
const fs = require('fs');
/*
1、输入符合邮箱规则的邮箱,且不存在在系统中,提示发送邮件成功
2、邮箱为空,点击下一步给出不可为空提示
3、邮箱格式不符合规则,点击下一步相应提示
4、已激活账号,点击下一步相应提示
5、修改邮箱步骤:
    输入邮箱账号,在OAO点击该邮箱链接跳转至对应邮箱(只要能打开该邮箱即可);
    用户在该邮箱点击对应链接直接进行验证;自动跳转到OAO进入“完成”页面;

// 注意事项
测试需要开通qq邮箱的imap服务,登录qq邮箱,在设置中开通。
需要发送短信验证码,记录授权码,填写在密码的位置

*/

const projectConfiguration = require('./projectConfiguration')

// const pathToExtension = require('path').join(__dirname, 'chrome-win\\chrome.exe');
const pathToExtension = require('path').join(__dirname, '../chrome-mac/Chromium.app/Contents/MacOS/Chromium');
const reportFileName = '学生端修改邮箱';

(async () => {
    // 引入projectConfiguration配置文件,必须有
    const projectConfiguration = require('./projectConfiguration')
    // 删除目录,为了清空前次的垃圾数据,必须有
   projectConfiguration.deleteFolderRecursive('./screenshot/' + reportFileName)

    projectConfiguration.reportLog('INFO', 'start '+ reportFileName +' Test----------------------------');
    const browser = await puppeteer.launch({
        executablePath: pathToExtension,
        ignoreDefaultArgs: ['--mute-audio', '--disable-extensions'],
        defaultViewport: { width: 1366, height: 768 },
        headless: false
    });

    var newEmail = '1037281161@qq.com';
    // newEmail = '382445027@qq.com';
    
    var pwd = 'zvqhyemdypdybcbj';
    // pwd = 'nwtjimfpxqcabiea';

    var host = 'imap.qq.com';
    var oriContent = "";
    /**
     * imap内容
     */
    let imap = new Imap({
        user: newEmail,
        password: pwd,
        host: host,
        port: 993,
        tls: true,
        tlsOptions: { rejectUnauthorized: false }
    });


    function openInbox(cb) {
        imap.openBox('INBOX', true, cb);
    }
    function getAHref(htmlstr){
        var reg = /<a.+?href=('|")?([^'"]+)('|")?(?:\s+|>)/gim;
        var arr = [];
        while(tem=reg.exec(htmlstr)){
            arr.push(tem[2]);
        }
        return arr;
    }
    imap.once('ready', function () {
        openInbox(function (err, box) {
            if (err) throw err;
            imap.search(['UNSEEN', ['SINCE', new Date().toDateString()], ['FROM', 'notice@bettermorph.com']], (err, results) => {
                if (err || !results) {
                    console.log('you are already up to date');
                    return;
                }
                projectConfiguration.reportLog('INFO', `开始获取最新的邮件内容...`);
                var result = results[results.length - 1];
                var f = imap.fetch(result, { markSeen: true, bodies: '' });
                f.on('message', function (msg, seqno) {
                    console.log('Message #%d', seqno);
                    var mailparser = new MailParser();
                    var prefix = '(#' + seqno + ')';
                    msg.on('body', function (stream, info) {
                        stream.pipe(mailparser);
                        mailparser.on("data", function (mail) {
                            let ar = getAHref(mail.html);
                            console.log(ar);    
                            if(ar.length == 1){
                                goVerifyPage(ar[0]);
                            }                        
                            // fs.writeFile('msg-' + seqno + '-body.html', mail.html, function (err) {
                            //     if (err) throw err;
                            //     console.log(seqno + 'saved!');
                            // });
                        })
                    });
                    msg.once('end', function () {
                        console.log(seqno + 'Finished');
                    });
                });

                f.once('error', function (err) {
                    console.log(err);
                });

                f.once('end', function () {
                    console.log('Connection ended');
                    imap.end();
                    projectConfiguration.reportLog('INFO', `邮件已关闭`);
                });
            });
        });

        imap.once('error', function (err) {
            console.log(err);
        });

        imap.once('end', function () {
            console.log('Connection ended');
        });
    });
    /**
     * imap内容
     */
    async function goVerifyPage(url) {

        projectConfiguration.reportLog('INFO', `打开验证地址:${url}`);
        const np = await browser.newPage();
        try {            
            await np.goto(url);
            // 进入个人空间
            await np.waitFor('button')
            await np.waitFor(500);
            await np.click('.retrieveSteps button[type="button"]');
            // 进入个人空间后,进入个人设置
            await np.waitFor('a[href="#/MySet"]')
            // 点击个人设置
            await np.click('a[href="#/MySet"]');
            await np.waitFor('.email_item .MyAccount');
            var email = await np.evaluate(() => {
                return document.querySelector('.email_item .MyAccount').innerText;
            });
            console.log(email);
            //browser.close();
            projectConfiguration.reportLog('INFO', `更改前页面内容:${oriContent} 更改后页面内容:${email}`);
        } catch (error) {
            
        }
        //browser.close();
        projectConfiguration.reportLog('INFO', 'end 修改邮箱 Test----------------------------');
    }
    
    // 新建目录,为了保存此次的数据,必须有
    projectConfiguration.makeFolderRecursive('./screenshot/' + reportFileName)

    const page = await browser.newPage();
    await projectConfiguration.initPage(page);

    let URL = 'https://www.bettermorph.com/#/studentsLogin';
    projectConfiguration.reportLog('INFO', 'ready 测试地址:' + URL);
    await page.goto(URL);

    await projectConfiguration.login(page, '18713152001', '123456');
    await page.waitFor(1000)
    let userinfo = await page.$('#userInfo');
    if (userinfo) {
        // 点击个人主页
        await page.click('a[href="#/mySpace"]');
        await page.waitFor('a[href="#/MySet"]')
        // 点击个人设置
        await page.click('a[href="#/MySet"]');

        await page.waitFor('.email_item .MyAccount');
        var email = await page.evaluate(() => {
            return document.querySelector('.email_item .MyAccount').innerText;
        });
        oriContent = email;
        
        console.log(email);
        if (email.indexOf('@') < 0) {
            // 代表没有邮箱
            projectConfiguration.reportLog('INFO', '需要绑定邮箱 Test----------------------------');
        } else {
            // 点击修改邮箱
            projectConfiguration.reportLog('INFO', '已经绑定邮箱 Test----------------------------');
        }
        await page.waitFor('a[href="#/StudentRetrieveByMail"]')
        await page.click('a[href="#/StudentRetrieveByMail"]');

        await page.waitFor('input[type="email"]');
        await page.type('input[type="email"]', newEmail, { delay: 10 });
        await page.click('.el-button.stepBtn.el-button--default');

        // 等待有提示去邮箱认证
        await page.waitFor(`a[href="mailto:${newEmail}"]`);

        projectConfiguration.reportLog('INFO', `等待10s登录邮箱${newEmail}----------------------------`);
        await page.waitFor(10000)
        // 登录邮箱,查找notice@bettermorph.com发送的最新邮件
        imap.connect();
        
        fs.rename('./testReport.txt', './' + reportFileName + Date.parse(new Date()) + '.txt', (err) => {
            if (err) throw err;
            console.log('重命名完成');
        });
    }
})();

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/385400.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Vue3+Ant-Design-Vue:报错Cannot read properties of null (reading ‘isCE‘)

问题描述 在使用Ant-Design-Vue内置的Table表格组件&#xff0c;实现expand展开行功能时&#xff0c;报错&#xff1a;Uncaught TypeError: Cannot read properties of null (reading ‘isCE‘) 。 报错信息图示&#xff1a; 在GitHub上找到如下描述&#xff0c; 解决方案 网上…

idea:如何连接数据库

1、在idea中打开database: 2、点击 ‘’ ---> Data Source ---> MySQL 3、输入自己的账号和密码其他空白处可以不填&#xff0c;用户和密码可以在自己的mysql数据库中查看 4、最后选择自己需要用的数据库&#xff0c;点击运用ok&#xff0c;等待刷新即可 最后&#xff1a…

利用numpy库进行数据分析

一.这段代码的主要目的是加载美国和英国的YouTube视频数据&#xff0c;并将它们合并在一起。在这个过程中&#xff0c;我们还添加了一个额外的列来表示数据的来源国家&#xff08;美国或英国&#xff09;。 # codingutf-8 import numpy as np# 定义CSV文件的路径 us_file_path…

JavaI/O流 File类(目录)

目录 File类目录操作实例 File类目录操作 Java的File类提供了对文件和目录进行操作的方法。对于目录&#xff0c;File类提供了以下一些方法&#xff1a; 判断目录是否存在&#xff1a;使用exists()方法可以判断目录是否存在。创建目录&#xff1a;使用mkdir()或mkdirs()方法可…

Java奠基】玩转字符串从基础到高级的操作技巧

目录 初识String StringBuilder StringJoiner 字符串原理 综合练习 初识String java.lang.String 类代表字符串&#xff0c;Java程序中的所有字符串文字(例如“abc”)都为此类的对象&#xff0c;例&#xff1a; String name "张三" 当使用双引号直接赋值时&…

Java语法学习反射

Java语法学习反射 大纲 基本介绍class的介绍 具体案例 1. 基本介绍 流程图&#xff08;程序在计算机的阶段&#xff09; 反射的主要的类 这个提高效率不大 2. class的介绍 对于第三点&#xff1a;首先类只会加载一次&#xff0c;得到的class的对象&#xff0c;也只有一…

【北邮鲁鹏老师计算机视觉课程笔记】07 Local feature-Blob detection

【北邮鲁鹏老师计算机视觉课程笔记】07 Local feature-Blob detection 1 实现尺度不变性 不管多近多远&#xff0c;多大多小都能检测出来 找到一个函数&#xff0c;实现尺度的选择特性 2 高斯偏导模版求边缘 做卷积 3 高斯二阶导拉普拉斯 看哪个信号能产生最大响应 高斯…

Linux进程创建,进程终止,进程等待,进程程序替换,简易shell代码

进程创建 fork函数初识 fork函数&#xff1a;从已存在进程中创建一个新进程。新进程为子进程&#xff0c;而原进程为父进程 #include <unistd.h> pid_t fork(void); 返回值&#xff1a;子进程中返回0&#xff0c;父进程返回子进程id&#xff0c;出错返回-1 进程调用 f…

web前端(第一天HTML)

前端是什么&#xff1f; 网页&#xff1f; 将数据以各种方式&#xff08;如&#xff1a;表格、饼图、柱状图等&#xff09;呈现给用户&#xff0c;我们就可以称之为前端。 做前端所需要的工具&#xff1f; notepad 、 editplus 、 notepad 、 vscode 、 webstorm 等&#x…

Linux:搭建docker私有仓库(registry)

当我们内部需要存储镜像时候&#xff0c;官方提供了registry搭建好直接用&#xff0c;废话少说直接操作 1.下载安装docker 在 Linux 上安装 Docker Desktop |Docker 文档https://docs.docker.com/desktop/install/linux-install/安装 Docker 引擎 |Docker 文档https://docs.do…

[C++]17:二叉树进阶

二叉树进阶 一.二叉搜索树&#xff1a;1.二叉搜索树的概念&#xff1a;2.二叉搜索树的实现---循环版本&#xff1a;1.二叉搜索树的基本结构&#xff1a;2.查找&#xff1a;3.插入&#xff1a;4.中序遍历&#xff1a;5.删除&#xff1a; 3.二叉搜索树的实现---递归版本&#xff…

HCIA-HarmonyOS设备开发认证V2.0-3.2.轻量系统内核基础-软件定时器

目录 一、软件定时器基本概念二、软件定时器运行机制三、软件定时器状态四、软件定时器模式五、软件定时器开发流程六、软件定时器使用说明七、软件定时器接口八、代码分析&#xff08;待续...&#xff09;坚持就有收获 一、软件定时器基本概念 软件定时器&#xff0c;是基于系…

java SpringBoot2.7整合Elasticsearch(ES)7 带条件分页查询与不带条件分页查询演示讲解

上文 java SpringBoot2.7整合Elasticsearch(ES)7 进行文档增删查改 我们带着大家 整合了 Elasticsearch 对索引中的文档做了 各方面操作 然后 我们来说说 分页查询 这里 为了方便大家看 我加了五条数据进去 这里 我们仍然需要带个条件 这里 我们用name Mapper 接口 加一个这…

vue3 解决ionic安卓版顶部状态栏空白问题

问题展示&#xff1a; 解决&#xff1a;引入capacitor/status-bar npm install capacitor/status-bar npx cap sync在需要设置状态栏的组件上设置背景跟颜色即可

Vue3快速上手(四)ref之基本类型响应式数据

一、ref之基本类型响应式数据 1.1 基本语法 import { ref } from vuelet x ref(初始值)console.log(xxx --> , x.value);x为一个RefImpl对象&#xff0c;该对象的value属性为实际值&#xff0c;在script里需要操作x.value来改变数据的值&#xff0c;在页面里则可以直接使…

rem基础+媒体查询+Less基础

一&#xff0c;rem基础 二&#xff0c;媒体查询 2.1什么是媒体查询 2.2语法规范 2.3媒体查询rem实现元素动态大小的变化 2.4 引入资源&#xff08;理解&#xff09; 三&#xff0c;Less基础 1 维护css的弊端 2 Less介绍 3 Less变量 变量命名规范 4 Less嵌套 5 Less…

WebSocket原理详解

目录 1.引言 1.1.使用HTTP不断轮询 1.2.长轮询 2.websocket 2.1.概述 2.2.websocket建立过程 2.3.抓包分析 2.4.websocket的消息格式 3.使用场景 4.总结 1.引言 平时我们打开网页&#xff0c;比如购物网站某宝。都是点一下列表商品&#xff0c;跳转一下网页就到了商品…

消息中间件面试篇

消息中间件 RabbitMQ 消息不丢失 可能导致消息丢失的情况&#xff1a; 生产者发送消息丢失消息队列宕机消费者服务宕机&#xff0c;未接收到消息 生产者确认机制 该机制解决了生产者发送消息有可能丢失的问题。 RabbitMQ提供了publisher confirm机制来避免消息发送到MQ过程…

AWD-Test2

1.已知账号密码&#xff0c;可SSH连接进行代码审计。2.登录可万能密码进入&#xff0c;也可注册后登录。3.修改url参数&#xff0c;发现报错。确定为Linux系统4.写入一句话&#xff0c;并提交。&#xff08;也可以文件上传&#xff0c;这里采用简洁的方法&#xff09; <?p…

RPC技术分享

一、微服务与RPC技术分享 1.1 微服务简介 微服务架构是一种软件设计和开发的模式&#xff0c;将应用程序拆分为一组小型、独立的服务。每个服务运行在自己的进程中&#xff0c;并使用轻量级通信机制进行协同工作。微服务架构通过提高灵活性、可维护性和可伸缩性来改进大型系统…