cypress测试本地web应用


Posted in Javascript onJune 01, 2022

cypress测试本地web应用

在之前的cypress介绍里曾提到过,cypress虽然也可以测试部署好的应用,但是它最大的能力还是发挥在测试本地应用上。
本章主要内容就是关于如何测试本地web应用的概述:

  • cypress与后台应用之间的关系。
  • 如何配置cypress使其适合我们的应用
  • 更好的绕过应用的身份验证机制

一、启动本地应用

在前面几章内容中,代码示例都是用的官方文档的网页进行测试的。那个环境相当于一个线上的生产环境,而且是cypress官方的,咱们除了正常访问
啥也做不了。启动本地应用就是启动你自己开发的web应用,比如我本地的测试平台的前端应用。

不过应该还会有小伙伴好奇,为什么就不能直接用线上已经部署好的,而非要用本地的?
这里,我概述一下官方的回答,以供参考:

  • 在日常的本地开发中,cypress是围绕着构建、优化的工具。
  • 数据存根。
  • 最重要的还是你要有控制这个应用的能力,比如,根据需要随时更改调整应用的一些配置之类。

不过,也不是说线上环境和本地环境,你必须二选一才行,也可以都写测试,这也是一个实用场景。比如,大多数的测试可以在本地环境跑,然后留一些
测试可以作为冒烟测试用,可以用到部署好的环境上去。

二、访问本地应用

之前演示用的代码用不上了,现在可以新建一个测试文件home_page_spec.js

describe('The Home Page', () => {
  it('successfully loads', () => {
    cy.visit('http://localhost:8010') // 这里换成你自己本地的url
  })
})

访问成功。

cypress测试本地web应用

三、配置Cypress

在Cypress项目中,其实有个配置文件cypress.json,就在项目根目录下,内容默认为空{}
在这里可以根据需要来添加cypress的各种配置,比如说 测试文件的位置、默认超时时间、环境变量、用哪个报告等等,这里暂时不展开了。

不过现在,可以在这里加一个baseUrl的配置,因为后续访问的路径都是以这个url为基础的。这样就可以给cys.visit()cys .request()这种命令
自动添加baseUrl前缀了。

{
  "baseUrl": "http://localhost:8010"
}

现在访问一个相对路径试下:

describe('The Home Page', () => {
  it('successfully loads', () => {
    cy.visit('/')
  })
})

访问成功。

cypress测试本地web应用

到这里,就可以开始写你本地应用的测试了,至于怎么写,就还是取决不同的项目需求了。

四、Seeding data

这里我理解为初始化数据,比如要测试一个页面的登录,可能就得向数据库里插入一个用户数据,方便使用。在之前用selenium的时候,
通常就在setup 和 teardown里来安排初始化测试数据的准备和清理。

在cypress中,也会有一些支持做这些额外拓展的事情的方法,通常是这3种:

cy.exec(),可以执行系统命令。

cy.task(),可以通过pluginsFile来在node中运行代码。

cy.request(),可以发送http请求。

比如下面这段代码,演示的就是在测试执行之前,要做一系列事情来完成数据的初始化:

describe('The Home Page', () => {
  beforeEach(() => {
    // reset and seed the database prior to every test
    cy.exec('npm run db:reset && npm run db:seed')
    // seed a post in the DB that we control from our tests
    cy.request('POST', '/test/seed/post', {
      title: 'First Post',
      authorId: 1,
      body: '...',
    })
    // seed a user in the DB that we can control from our tests
    cy.request('POST', '/test/seed/user', { name: 'Jane' })
      .its('body')
      .as('currentUser')
  })
  it('successfully loads', () => {
    // this.currentUser will now point to the response
    // body of the cy.request() that we could use
    // to log in or work with in some way
    cy.visit('/')
  })
})

这种用法其实本质上来说没什么错的,但实际上每个测试都要与服务器或者浏览器交互的,这难免会拖慢测试的效率。对于这个问题,cypress
提供了些更快更好的解决方案。

1. Stubbing the server

这里就是我理解的mock了,断开与后端服务的依赖。既然我需要跟服务器交互才可以拿到需要的返回数据,如果能绕开交互,直接需要用啥数据就有啥数据,连后端应用都
不需要启了,岂不美哉?关于stub内容很多,后续使用到再继续分解。

2. 解决登录问题

在以往编写测试的过程中,登录一直是一个比较大的问题。你只有登录了,才可以进行后续的测试活动。那么如果我们把登录抽离出去,然后每个测试执行之前都进行一次登录操作,
理论上来讲,也是可行的。

describe('The Login Page', () => {
  beforeEach(() => {
    // reset and seed the database prior to every test
    cy.exec('npm run db:reset && npm run db:seed')
    // seed a user in the DB that we can control from our tests
    // assuming it generates a random password for us
    cy.request('POST', '/test/seed/user', { username: 'jane.lane' })
      .its('body')
      .as('currentUser')
  })
  it('sets auth cookie when logging in via form submission', function () {
    // destructuring assignment of the this.currentUser object
    const { username, password } = this.currentUser
    cy.visit('/login')
    cy.get('input[name=username]').type(username)
    // {enter} causes the form to submit
    cy.get('input[name=password]').type(`${password}{enter}`)
    // we should be redirected to /dashboard
    cy.url().should('include', '/dashboard')
    // our auth cookie should be present
    cy.getCookie('your-session-cookie').should('exist')
    // UI should reflect this user being logged in
    cy.get('h1').should('contain', 'jane.lane')
  })
})

只不过这样整个测试下来就变得非常的慢。所以,cypress呼吁不要在每次测试前使用UI登录。

当然了,你正儿八经写的测试代码里肯定是测试UI的,但是如果这个测试涉及到其他前置的一些数据状态的依赖,那么要避免通过UI去设置。
这里官方还举了个购物车的例子加以说明。

假设要测试购物车的功能。要进行测试的话,得把产品添加到购物车中。那么产品从哪里来? 我是否要使用UI登录到管理后台,然后创建所有的产品,包括它们的描述、类别和图片?
如果这样做了,那是不是所有的产品我都要访问一遍并且加到购物车里呢?

答案显然是否定的,至于怎样做最合适,还得到后续的学习中再分享。

继续回到上面UI登录的问题,因为cypress与selenium不同,在cypress中,可以通过使用cy.request()来跳过使用UI的需要,cy.request()可以自动获取和设置cookie,完成登录态的设置。那么上述的用UI执行登录的代码就可以优化成:

describe('The Dashboard Page', () => {
  beforeEach(() => {
    // reset and seed the database prior to every test
    cy.exec('npm run db:reset && npm run db:seed')
    // seed a user in the DB that we can control from our tests
    // assuming it generates a random password for us
    cy.request('POST', '/test/seed/user', { username: 'jane.lane' })
      .its('body')
      .as('currentUser')
  })
  it('logs in programmatically without using the UI', function () {
    // destructuring assignment of the this.currentUser object
    const { username, password } = this.currentUser
    // programmatically log us in without needing the UI
    cy.request('POST', '/login', {
      username,
      password,
    })
    // now that we're logged in, we can visit
    // any kind of restricted route!
    cy.visit('/dashboard')
    // our auth cookie should be present
    cy.getCookie('your-session-cookie').should('exist')
    // UI should reflect this user being logged in
    cy.get('h1').should('contain', 'jane.lane')
  })
})

在官方看来,这个相比于selenium是一个大优点,其实我觉得也不尽然。这个优化思想是对的,不过在之前使用selenium的时候,虽然它内置的方法不支持这么做,但是可以借助
requests库来迂回解决直接像后端发送请求的问题。

以上就是cypress测试本地web应用的详细内容,更多关于cypress测试web的资料请关注三水点靠木其它相关文章!


Tags in this post...

Javascript 相关文章推荐
javascript实现焦点滚动图效果 具体方法
Jun 24 Javascript
制作jquery遮罩层效果导航菜单代码分享
Dec 25 Javascript
js使用eval解析json(js中使用json)
Jan 17 Javascript
js四舍五入数学函数round使用实例
May 09 Javascript
js实现网页标题栏闪烁提示效果实例分析
Nov 20 Javascript
Java框架SSH结合Easyui控件实现省市县三级联动示例解析
Jun 12 Javascript
js Canvas绘制圆形时钟教程
Feb 06 Javascript
vue-router+vuex addRoutes实现路由动态加载及菜单动态加载
Sep 28 Javascript
微信小程序实现聊天对话(文本、图片)功能
Jul 06 Javascript
小程序的上传文件接口的注意要点解析
Sep 17 Javascript
vue 实现模糊检索并根据其他字符的首字母顺序排列
Sep 19 Javascript
vue @click.native 绑定原生点击事件
Apr 22 Vue.js
vue实现登陆页面开发实践
May 30 #Vue.js
Echarts如何重新渲染实例详解
May 30 #Javascript
vue router 动态路由清除方式
May 25 #Vue.js
vue如何清除浏览器历史栈
May 25 #Vue.js
ant design charts 获取后端接口数据展示
May 25 #Javascript
vue3不同环境下实现配置代理
May 25 #Vue.js
Typescript类型系统FLOW静态检查基本规范
You might like
通过ICQ网关发送手机短信的PHP源程序
2006/10/09 PHP
PHP截断标题且兼容utf8和gb2312编码
2013/09/22 PHP
PHP curl 抓取AJAX异步内容示例
2014/09/09 PHP
php实现parent调用父类的构造方法与被覆写的方法
2015/02/11 PHP
Php-Redis安装测试笔记
2015/03/05 PHP
Laravel 实现Controller向blade前台模板赋值的四种方式小结
2019/10/22 PHP
js获取键盘按键响应事件(兼容各浏览器)
2013/05/16 Javascript
javascript实现捕捉键盘上按下的键
2015/05/05 Javascript
javascript实现dom动态创建省市纵向列表菜单的方法
2015/05/14 Javascript
深入分析JSON编码格式提交表单数据
2015/06/25 Javascript
Javascript之Date对象详解
2016/06/07 Javascript
微信小程序 动态的设置图片的高度和宽度详解及实例代码
2017/02/24 Javascript
详解用vue.js和laravel实现微信支付
2017/06/23 Javascript
angular动态删除ng-repaeat添加的dom节点的方法
2017/07/20 Javascript
react-native 完整实现登录功能的示例代码
2017/09/11 Javascript
angular动态表单制作
2018/02/23 Javascript
vue-vuex中使用commit提交mutation来修改state的方法详解
2018/09/16 Javascript
antd design table更改某行数据的样式操作
2020/10/31 Javascript
Python3简单实例计算同花的概率代码
2017/12/06 Python
Python时间戳使用和相互转换详解
2017/12/11 Python
详解opencv中画圆circle函数和椭圆ellipse函数
2019/12/27 Python
Django中modelform组件实例用法总结
2020/02/10 Python
Visual Studio code 配置Python开发环境
2020/09/11 Python
python import 上级目录的导入
2020/11/03 Python
印度尼西亚最大的电商平台:Tokopedia(印尼版淘宝)
2017/12/02 全球购物
我的applet原先好好的, 一放到web server就会有问题,为什么?
2016/05/10 面试题
英语专业应届生求职信范文
2013/11/15 职场文书
员工培训心得体会
2013/12/30 职场文书
文明宿舍获奖感言
2014/02/07 职场文书
市场专员岗位职责
2014/02/14 职场文书
学雷锋先进个人事迹
2014/05/26 职场文书
社区维稳工作方案
2014/06/06 职场文书
幼儿园六一儿童节活动方案
2014/08/26 职场文书
matplotlib之pyplot模块实现添加子图subplot的使用
2021/04/25 Python
python 爬取哔哩哔哩up主信息和投稿视频
2021/06/07 Python
Python中re模块的元字符使用小结
2022/04/07 Python