当前位置: 首页 > news >正文

个人网站建设公司免费推广广告链接

个人网站建设公司,免费推广广告链接,企业资质查询,苏宁易购电器商城官网背景 近期团队打算做一个小程序自动化测试的工具#xff0c;期望能够做到业务人员操作一遍小程序后#xff0c;自动还原之前的操作路径#xff0c;并且捕获操作过程中发生的异常#xff0c;以此来判断这次发布是否会影响小程序的基础功能。 上述描述看似简单#xff0c;…背景 近期团队打算做一个小程序自动化测试的工具期望能够做到业务人员操作一遍小程序后自动还原之前的操作路径并且捕获操作过程中发生的异常以此来判断这次发布是否会影响小程序的基础功能。 上述描述看似简单但是中间还是有些难点的第一个难点就是如何在业务人员操作小程序的时候记录操作路径第二个难点就是如何将记录的操作路径进行还原。 自动化 SDK 如何将操作路径还原这个问题首选官方提供的 SDK miniprogram-automator。 小程序自动化 SDK 为开发者提供了一套通过外部脚本操控小程序的方案从而实现小程序自动化测试的目的。通过该 SDK你可以做到以下事情 控制小程序跳转到指定页面获取小程序页面数据获取小程序页面元素状态触发小程序元素绑定事件往 AppService 注入代码片段调用 wx 对象上任意接口… 上面的描述都来自官方文档建议阅读后面内容之前可以先看看官方文档当然如果之前用过 puppeteer 也可以快速上手api 基本一致。下面简单介绍下 SDK 的使用方式。 // 引入sdk const automator require(miniprogram-automator)// 启动微信开发者工具 automator.launch({// 微信开发者工具安装路径下的 cli 工具// Windows下为安装路径下的 cli.bat// MacOS下为安装路径下的 clicliPath: path/to/cli,// 项目地址即要运行的小程序的路径projectPath: path/to/project, }).then(async miniProgram { // miniProgram 为 IDE 启动后的实例// 启动小程序里的 index 页面const page await miniProgram.reLaunch(/page/index/index)// 等待 500 msawait page.waitFor(500)// 获取页面元素const element await page.$(.main-btn)// 点击元素await element.tap()// 关闭 IDEawait miniProgram.close() }) 有个地方需要提醒一下使用 SDK 之前需要开启开发者工具的服务端口要不然会启动失败。 捕获用户行为 有了还原操作路径的办法接下来就要解决记录操作路径的难题了。 在小程序中并不能像 web 中通过事件冒泡的方式在 window 中捕获所有的事件好在小程序所以的页面和组件都必须通过 Page 、Component 方法来包装所以我们可以改写这两个方法拦截传入的方法并判断第一个参数是否为 event 对象以此来捕获所有的事件。 // 暂存原生方法 const originPage Page const originComponent Component// 改写 Page Page (params) {const names Object.keys(params)for (const name of names) {// 进行方法拦截if (typeof obj[name] function) {params[name] hookMethod(name, params[name], false)}}originPage(params) } // 改写 Component Component (params) {if (params.methods) {const { methods } paramsconst names Object.keys(methods)for (const name of names) {// 进行方法拦截if (typeof methods[name] function) {methods[name] hookMethod(name, methods[name], true)}}}originComponent(params) }const hookMethod (name, method, isComponent) {return function(...args) {const [evt] args // 取出第一个参数// 判断是否为 event 对象if (evt evt.target evt.type) {// 记录用户行为}return method.apply(this, args)} } 这里的代码只是代理了所有的事件方法并不能用来还原用户的行为要还原用户行为还必须知道该事件类型是否是需要的比如点击、长按、输入。 const evtTypes [tap, // 点击input, // 输入confirm, // 回车longpress // 长按 ] const hookMethod (name, method) {return function(...args) {const [evt] args // 取出第一个参数// 判断是否为 event 对象if (evt evt.target evt.type evtTypes.includes(evt.type) // 判断事件类型) {// 记录用户行为}return method.apply(this, args)} } 确定事件类型之后还需要明确点击的元素到底是哪个但是小程序里面比较坑的地方就是event 对象的 target 属性中并没有元素的类名但是可以获取元素的 dataset。 为了准确的获取元素我们需要在构建中增加一个步骤修改 wxml 文件将所有元素的 class 属性复制一份到 data-className 中。 !-- 构建前 -- view classclose-btn/view view class{{mainClassName}}/view !-- 构建后 -- view classclose-btn data-classNameclose-btn/view view class{{mainClassName}} data-className{{mainClassName}}/view 但是获取到 class 之后又会有另一个坑小程序的自动化测试工具并不能直接获取页面里自定义组件中的元素必须先获取自定义组件。 !-- Page -- toast textloading show{{showToast}} / !-- Component -- view classtoast wx:if{{show}}text classtoast-text{{text}}/textview classtoast-close / /view // 如果直接查找 .toast-close 会得到 null const element await page.$(.toast-close) element.tap() // Error!// 必须先通过自定义组件的 tagName 找到自定义组件 // 再从自定义组件中通过 className 查找对应元素 const element await page.$(toast .toast-close) element.tap() 所以我们在构建操作的时候还需要为元素插入 tagName。 !-- 构建前 -- view classclose-btn / toast textloading show{{showToast}} / !-- 构建后 -- view classclose-btn data-classNameclose-btn data-tagNameview / toast textloading show{{showToast}} data-tagNametoast / 现在我们可以继续愉快的记录用户行为了。 // 记录用户行为的数组 const actions []; // 添加用户行为 const addAction (type, query, value ) {actions.push({time: Date.now(),type,query,value}) }// 代理事件方法 const hookMethod (name, method, isComponent) {return function(...args) {const [evt] args // 取出第一个参数// 判断是否为 event 对象if (evt evt.target evt.type evtTypes.includes(evt.type) // 判断事件类型) {const { type, target, detail } evtconst { id, dataset {} } targetconst { className } datasetconst { value } detail // input事件触发时输入框的值// 记录用户行为let query if (isComponent) {// 如果是组件内的方法需要获取当前组件的 tagNamequery ${this.dataset.tagName} }if (id) {// id 存在则直接通过 id 查找元素query id} else {// id 不存在才通过 className 查找元素query className}addAction(type, query, value)}return method.apply(this, args)} } 到这里已经记录了用户所有的点击、输入、回车相关的操作。但是还有滚动屏幕的操作没有记录我们可以直接代理 Page 的 onPageScroll 方法。 // 记录用户行为的数组 const actions []; // 添加用户行为 const addAction (type, query, value ) {if (type scroll || type input) {// 如果上一次行为也是滚动或输入则重置 value 即可const last this.actions[this.actions.length - 1]if (last last.type type) {last.value valuelast.time Date.now()return}}actions.push({time: Date.now(),type,query,value}) }Page (params) {const names Object.keys(params)for (const name of names) {// 进行方法拦截if (typeof obj[name] function) {params[name] hookMethod(name, params[name], false)}}const { onPageScroll } params// 拦截滚动事件params.onPageScroll function (...args) {const [evt] argsconst { scrollTop } evtaddAction(scroll, , scrollTop)onPageScroll.apply(this, args)}originPage(params) } 这里有个优化点就是滚动操作记录的时候可以判断一下上次操作是否也为滚动操作如果是同一个操作则只需要修改一下滚动距离即可因为两次滚动可以一步到位。同理输入事件也是输入的值也可以一步到位。 还原用户行为 用户操作完毕后可以在控制台输出用户行为的 json 文本把 json 文本复制出来后就可以通过自动化工具运行了。 // 引入sdk const automator require(miniprogram-automator)// 用户操作行为 const actions [{ type: tap, query: goods .title, value: , time: 1596965650000 },{ type: scroll, query: , value: 560, time: 1596965710680 },{ type: tap, query: gotoTop, value: , time: 1596965770000 } ]// 启动微信开发者工具 automator.launch({projectPath: path/to/project, }).then(async miniProgram {let page await miniProgram.reLaunch(/page/index/index)let prevTimefor (const action of actions) {const { type, query, value, time } actionif (prevTime) {// 计算两次操作之间的等待时间await page.waitFor(time - prevTime)}// 重置上次操作时间prevTime time// 获取当前页面实例page await miniProgram.currentPage()switch (type) {case tap:const element await page.$(query)await element.tap()break;case input:const element await page.$(query)await element.input(value)break;case confirm:const element await page.$(query)await element.trigger(confirm, { value });break;case scroll:await miniProgram.pageScrollTo(value)break;}// 每次操作结束后等待 5s防止页面跳转过程中后面的操作找不到页面await page.waitFor(5000)}// 关闭 IDEawait miniProgram.close() }) 这里只是简单的还原了用户的操作行为实际运行过程中还会涉及到网络请求和 localstorage 的 mock这里不再展开讲述。同时我们还可以接入 jest 工具更加方便用例的编写。 总结 看似很难的需求只要用心去发掘总能找到对应的解决办法。另外微信小程序的自动化工具真的有很多坑遇到问题可以先到小程序社区去找找大部分坑都有前人踩过还有一些一时无法解决的问题只能想其他办法来规避。最后祝愿天下无 bug。 公众号粉丝福利 软件测试全套资源免费领取 软件测试面试刷题小程序免费使用 专属于测试人的GPT免费使用
http://www.hkea.cn/news/14581839/

相关文章:

  • 电商网站平台建设方案爱站网长尾关键词挖掘工具下载
  • 重庆网站开发企业页面跳转请记住新域名
  • seo站内优化包括合肥租房网
  • 阿里巴巴国际站怎么做网站模版网站建设开发报告论文
  • 山东临沂网站推广怎么营销自己的产品
  • 贵阳建设工程招聘信息网站国外一个做ppt的网站
  • 河北建设机械协会网站网站建设公司 预算
  • 有做机械工装的网站吗网站代码在哪里看
  • 手机微网站怎么制作的vps centos wordpress
  • 易语言做网站登录东营城乡建设局官网
  • 玉门市住房和城乡建设局网站上海网站建设公司sky
  • 泰和网站制作成全视频免费高清观看在线韩剧
  • 周大福网站建设主要工作网站色彩策划
  • 为自己做的网站申请域名链接转换器
  • 湖南城乡建设部网站wordpress qq主题
  • 网站关键词建设wordpress怎么加js文件路径
  • 网站栏目定位中国储备粮管理集团有限公司
  • 除了淘宝还有哪些购物网站全国最大的外发加工网
  • 西安o2o网站设计公司枣庄网站优化
  • 网站建设专业名词sem是做什么的
  • 北京网站设计服务商桂林漓江风景区介绍
  • 网站建设最新教程门户网站建设汇报
  • 网站被镜像怎么做wordpress建的网站吗
  • 网站流量太高 如何做负载均衡深圳品牌vi设计
  • 瑞安做网站多少钱做网站副业
  • 做网站给韩国卖高仿兰州手机网站制作公司哪家好
  • 石河子市建设局网站辽宁省住房和城乡建设厅网站换了
  • 永久免费高配云服务器济南网站怎么做seo
  • 宁波建设协会网站广州网站建设学习
  • 织梦软件网站模板下载四大免费网站