一、概要

前面介绍了Puppeteer+jest+TypeScript做UI自动化,但是这知识基础的,我们实现自动化要考虑的很多,比如PO模式,比如配置文件,比如断言等等。下面就来一一实现我是怎么用puppeteer 做UI自动化的

二、断言

(一)需要依赖的安装包

依赖包 命令
Jest npm install jest --save-dev
@types/jest npm install @types/jest --save-dev
expect-puppeteer npm install expect-puppeteer --save-dev
@types/expect-puppeteer npm install @types/expect-puppeteer --save-dev

我们写过Jest的知道Jest自己就带有断言,但是Jest的断言有时候可能不全满足我们,我们来看看expect-puppeteer的api

链接:expect-puppeteer(api)

(二) 简单介绍下api

  1. 看api的介绍,expect-puppeteer封装了一些可供我们使用的方法,断言比如toMatch(验证页面是否能匹配到值),toMathcElement((验证页面是否能匹配到元素),这两个还是比较好用的,尤其toMathcElement,具体实战再说
  2. 其他api,看跟puppeteer api有点不一样,puppeteer一样有click方法那么expect-puppeteer好处是什么呢?这个时候我们就要看源码了这里建议即使有现成的库,我们也要多看看源码
  3. 查看expect-puppeteer - index.d.ts 发现写了一个ExpectPuppeteer接口,这里里面就有我们所有的api,我们顺便点看任意一个js文件看看,目录(expect-puppeteer - lib - options.js),我们就看看这个文件,看不懂没关系,但是大概我们能猜出,就是控制运行时间的嘛,实际工作中一个case可能会写大量的waitfor()是不是很麻烦,所以,我建议,吧options.js的timeout设置长一点,这样方便更准确的寻找页面元素
  4. api不多做介绍,照着api文档就会了,比较简单
options.js -> 修改timeout为2s
let defaultOptionsValue = {
timeout: 2000
};

三、PO 模式

问:什么是PO模式?

答:概念自行百度,我就不粘贴了,我想稍微写过一点UI自动化的,应该都会多多少少了解一点,通俗的说,我们把元素,方法,测试case 分开写,这样方便我们去管理,逻辑也不叫清晰,具体下面拿实例来说明

四、实例 (以同程网站为实例)

今天我们来写,从首页进入ly.com,点击机票 - 国内机票 - 验证机票默认弹框

(一)我的脚本目录

-----__tests__
-------ui
--------DomesticTictet
-------- cases
-------- basic.test.ts
-------- element
--------Index
-------- action
-------- Navi.action.help.ts
-------- element
-------- Navigation.help.ts
-----env
------ ly.yaml
-----utils
------ config.js
  • 测试用例都在__tests__文件夹中,DomesticTictet,Index 不同模块的文件夹,分别有cases(测试用例存放的文件夹)element(管理页面元素)action(方法)
  • env,管理yaml文件的文件夹,所有的yaml文件放在这里
  • utils 自己写的工具类,config.js读取yaml文件

(二)element类管理

Navigation.help.ts

import { Page } from 'puppeteer';
import expectPuppeteer = require('expect-puppeteer');
export const Nav_Ticket = '#menuNav li:nth-child(3) b';
export const DomesticTicket = '.submenu-nav .flight-submenu1';
home.help.ts
// 标题名
export const titleContent = '.s-title.dflex span'; // 出发城市
export const start_city_input = '.s-box:nth-child(1) input[value]'; // 到达城市
export const arrive_city_input = '.s-box:nth-child(3) input[value]'; // 出发时间
export const start_data_input = 'input[placeholder="出发日期"]'; // 到达时间
export const return_data_input = 'input[placeholder="返回日期"]'; // 搜索按钮
export const domestic_tictet_search = '.s-button'; // 搜索不到航班信息提示
export const flight_no_data_tip = '.flight-no-data span' // 存在航班的元素
export const flight_get_data = '.top-flight-info span b'

(三)action方法编写

Navi.action.help.ts

import { Page } from 'puppeteer';
import expectPuppeteer = require('expect-puppeteer');
const navi_element = require('../element/Navigation.help'); export class Navi_Action {
/**
* 点击国内机票
*/
public async hover_home_ticket(page:Page) {
await page.waitForSelector(navi_element.Nav_Ticket);
await page.hover(navi_element.Nav_Ticket);
await page.waitFor(3000);
await expectPuppeteer(page).toClick(navi_element.DomesticTicket);
await page.waitFor(3000); }
}

(四)yaml配置文件编写

ly.yaml

url:
web: https://www.ly.com/
flighthome: https://www.ly.com/flights/home # puppeteer lanuch配置
puppeteer:
proxy:
viewport:
width: 1920
height: 1080

(五)测试用例编写

basic.test.ts

import { Page } from 'puppeteer';
import { Navi_Action } from '../../Index/action/Navi.action.help';
const config = require('../../../../utils/config');
const Home_Element = require('../element/home.help');
const time = require('silly-datetime'); const ly = config.readConfig('ly'); describe('domestic ticket page content verification', () => {
let page : Page;
beforeEach( async () => {
page = await browser.newPage();
await page.setViewport(ly.puppeteer.viewport);
await page.goto(ly.url.web,{waitUntil:'networkidle2'}); let navi_action = new Navi_Action();
await navi_action.hover_home_ticket(page); },30000)
afterEach ( async () => {
await page.close();
}) test('TEST_001:验证跳转链接' , async() => {
const url = await page.url();
await expect(url).toBe(ly.url.flighthome);
},30000); test('TEST_002:验证标题名' , async() => {
const titleElement = Home_Element.titleContent;
const content = await page.evaluate( (titleElement) => {
return document.querySelector(titleElement).innerHTML;
},titleElement);
await expect(content).toEqual('国内机票');
},30000); test('TEST_003:验证出发默认城市' , async() => {
const content = await page.$eval(Home_Element.start_city_input,el => el.getAttribute('value'));
await expect(content).toEqual('上海');
},30000); test('TEST_004:验证到达默认城市' , async() => {
const content = await page.$eval(Home_Element.arrive_city_input,el => el.getAttribute('value'));
await expect(content).toEqual('北京');
},30000); test('TEST_004:验证时间为当天时间' , async() => {
const current_time = time.format(new Date(),'YYYY-MM-DD');
const start_time_element = Home_Element.start_data_input;
const start_time_content = await page.evaluate( (start_time_element) => {
return document.querySelector(start_time_element).value;
},start_time_element);
await expect(start_time_content).toEqual(current_time);
},30000); test('TEST_005:验证到达默认值' , async() => {
const return_input = await page.$eval(Home_Element.return_data_input,el => el.getAttribute('placeholder'));
await expect(return_input).toEqual('返回日期');
},30000);
})

结果

【基于Puppeteer前端自动化框架】【二】PO模式,断言(如何更简便逻辑的写测试代码)的更多相关文章

  1. 【基于PUPPETEER前端自动化框架】【一】TypeScript+Puppeteer+Jest 整合

    前提:掌握Jest + Puppeteer 1.Jest环境配置 2.Jest-MATCHERS匹配器 3.Jest-全局变量设置 4.Puppeteer安装 5.Puppeteer元素获取 6.Pu ...

  2. UI自动化测试框架:PO模式+数据驱动

    1. PO 设计模式简介 2. 工程结构说明 3. 工程代码实现 page 包 action 包 business_process 包 util 包 conf 包 test_data 目录 log 目 ...

  3. 说说UI自动化中的PO模式

    PO模式,全称PageObject模式,即页面对象模式.将页面定位与业务操作分离. po模式有以下几个优点: 1.易读性好 2.扩展性高 3.复用性强 4.维护性好 5.代码冗余率低 了解了po模式及 ...

  4. 3分钟手把手带你搭建基于selenium的自动化框架

    1 .什么是seleniumSelenium 是一个基于浏览器的自动化工具,它提供了一种跨平台.跨浏览器的端到端的web自动化解决方案.Selenium主要包括三部分:Selenium IDE.Sel ...

  5. Selenium基于Python web自动化基础二 -- 免登录、等待及unittest单元测试框架

    一.免登录在进行测试的过程中难免会遇到登录的情况,给测试工作添加了工作量,本文仅提供一些思路供参考解决方式:手动请求中添加cookies.火狐的profile文件记录信息实现.人工介入.万能验证码.去 ...

  6. 自动化框架的两种断言设计(pytest 版)

    自动化测试断言失败时,根据不同业务场景,可能需要立即终止或继续执行.这里以 Appium + pytest 为例. 一. 断言失败立即终止 用途一:用例的预期结果是其他用例的前提条件时,assert ...

  7. net.sz.framework 框架 轻松搭建服务---让你更专注逻辑功能---初探

    前言 在之前的文章中,讲解过 threadmodel,socket tcp ,socket http,log,astart ,scripts: 都是分片讲解,从今天开始,将带大家,一窥 net.sz. ...

  8. ShutIt:一个基于 Python 的 shell 自动化框架

    ShutIt是一个易于使用的基于shell的自动化框架.它对基于python的expect库(pexpect)进行了包装.你可以把它看作是“没有痛点的expect”.它可以通过pip进行安装. Hel ...

  9. 前端Js框架 UI框架汇总 特性 适用范围 选择

    身为一个资深后端工程师,面对层出不穷的前端框架,总让人眼花缭乱,做一个综合解析贴,从全局着眼,让我们明白各种前端框架的应用范围,为如何选择前端框架,从不同的维度提供一些线索,做为一个长期优化贴,欢迎指 ...

随机推荐

  1. mysql query cache 查询缓存

    查看本博文,并进行验证(验证结果与博文一致): https://blog.csdn.net/carmazhao/article/details/7088530 mysql默认是开启查询缓存的. 设置查 ...

  2. vue 干货

    今天逛博客,发现一个干货, 赶紧记录,内容太多,慢慢消化 vuejs心法和技法 https://www.cnblogs.com/kidsitcn/p/5409994.html

  3. Jetson AGX Xavier ROS下调用USB单目摄像头

    Jetson AGX Xavier安装的ROS是Melodic版本的,所以部署的时候用到的包都是Melodic的. 1. 查看USB摄像头 摄像头连接Xavier设备,调用命令查看. ls /dev/ ...

  4. 推荐系统---深度兴趣网络DIN&DIEN

    深度学习在推荐系统.CTR预估领域已经有了广泛应用,如wide&deep.deepFM模型等,今天介绍一下由阿里算法团队提出的深度兴趣网络DIN和DIEN两种模型 paper DIN:http ...

  5. windows编译openssl(64位)一游

    编译openssl,一套标准流程: (环境:  win10 64位os, vs2019) 需要的工具:perl     nasm   openssl源码包 1  安装perl 2  下载nasm,将n ...

  6. How to: Debug X++ Code Running in .NET Business Connector [AX 2012]

    This topic has not yet been rated - Rate this topic  http://msdn.microsoft.com/EN-US/library/bb19006 ...

  7. 2.5远程仓的库使用-2.7Git别名

    2.5 远程仓库的使用 查看远程仓库 git remote # -v 选项会显示需要读写远程仓库使用的 Git 保存的简写与其对应的 URL 添加远程仓库 git remote add <sho ...

  8. .NET 5 中的隐藏特性

    前言 双十一当天 .NET 5 正式发布带来了很多的新特性和改进,个人觉得非常香,并且花了 10 分钟时间就把自己的 4 个 .NET Core 3.1 的项目升级到了 .NET 5,堪称无痛. 但是 ...

  9. 【linux】helloword原理分析及实战

    目录 前言 linux中hello word原理 hello word 实战 学习参考 前言 hello word 著名演示程序,哈哈 下面在 arm linux 下展示一下hello world,便 ...

  10. 使用KepServerEx进行数据模拟

    KepServerEx是一款在工业控制中比较常见的数据采集服务软件之一,提供了多种类型的驱动,具有比较广泛的适用性.很多厂商和个人都会选择用它来做OPCServer.在项目的实施或测试过程中,我们有时 ...