Cypress Courses学习笔记

50 阅读3分钟

作者:蒙奇D

描述:Cypress上提供的4个Courses学习,介绍cypress的使用方式,测试的基本观点,以及Cypress的API、Commands...


Cypress的使用

Cypress桌面程序

//会打开页面
npx cypress open

cypress API

cy.get('button')
cy.request('/users/1').its('body')

cypress 是chain function

task

   cy.task('seed:db',{})
​
    on('task',{
​
     'seed:db':data=>{
​
       return ''
​
    }
​
})

cy.window().then(win=>win.app.$store)

Stubbing Network Response with Fixtures

cy.server()
​
cy.route('GET','/tweets*','fixture:tweets')
​
.as('tweets')
cy.wait().its()

cypress CLI终端

//不会打开浏览器页面
npx cypress run
npx cypress run --record

测试基础(用例for what?)

场景一:给现有的项目加测试用例

将原文翻译成中文是:

如果您尝试测试现有的应用程序,我们建议您首先为应用程序中最 “关键任务” 的部分编写测试。 我们所说的“关键任务”是指应用程序中不会出现故障或损坏的任何部分。 例如,登录/身份验证、购买产品、处理信用卡、注册表单等。我们建议您的第一套测试应该针对应用程序的这些部分,并且它们应该是端到端测试 。

并且使用"User Journeys"方式模拟用户操作步骤,测试完整的场景

场景二:开发新功能

将原文翻译成中文是:

当您实现新功能时,为该功能编写测试的一个有用技巧是首先从最终目标开始。 这个功能具体需要做什么? 它解决什么问题? 一旦理解了这一点,您就可以将该功能分解为小的增量步骤,所有这些都可以转化为测试。

简而言之就是,先从最终目标开始逐步细分

场景三:改bug

将原文翻译成中文是:

强烈建议您围绕应用程序中出现的任何错误编写测试。 一个好的方法是首先围绕故障编写期望正确的测试,此时测试用例执行会失败。 一旦错误被修复,您的测试就会通过,这将验证您的新代码是否已经消除了错误。

这样,您的测试将有助于确保该错误将来永远不会再出现。

voyage%r=zhang.ran130@zte.com.cn,r=chen.bo222@zte.com.cn,r=tao.ran@zte.com.cn,r=yin.peipei@zte.com.cn,r=mo.jianfei@zte.com.cn,r=li.zhongwei160@zte.com.cn,r=ma.xiaoting@zte.com.cn

cypress基础知识

Cypress 是基于Mocha构建

Cypress 原生依赖 Lodash,可以直接使用

异步特性

  • 1.cy.commands不返回任何东西。所以把链式调用用变量拆开不可行的

    // THIS WILL NOT WORK
    const button = cy.get("button")
    ​
    button.click()
    ​
    

    commands are asynchronous and get queued for execution at a later time.

  • 2.then()是cypress自己的命令,不支持async/await
  • get里then返回的btn是个jquery对象,不是domelement,需要cy.wrap(btn是个jquery对象,不是dom element,需要cy.wrap(btn)才能执行交互。比如

    cy.get("button").then(($btn) => {
      const cls = $btn.attr("class")
    ​
      cy.wrap($btn).click().should("not.have.class", cls)
    })
    

waiting&retry

别名:

// Create an alias using the `as()` Cypress Command
cy.get("table").find("tr").as("rows")
// 获取
cy.get("@rows")
​
  • 等待 接口返回
cy.request("POST", "/users").as("signup") // creating the signup alias
cy.wait("@signup") // waiting upon the signup alias

调试

1.cypressUI页面上点击断言步骤,在控制台会打印get的真实的数据

2.在命令终端里 使用cy.screenshot可以记录快照

3.cy.log()可以在UI页面打印日志

4.console.log()可以在UI页面的控制台里打印日志

5.浏览器的开发者工具可以正常使用,正常的浏览器调试

使用JS写测试用例

由于cypress测试用例就是以js代码运行在浏览器上,所以可以使用JS甚至loadsh动态生产测试用例

_.each(feedViews, (feed, feedName) => {
 if('',()=>{
 //something
 })
})
 const comments = ["Thank you!", "Appreciate it."]
​
    comments.forEach((comment, index) => {
      cy.getBySelLike("comment-input").type(`${comment}{enter}`)
      cy.getBySelLike("comments-list").children().eq(index).contains(comment)
    })

cypress 高级概念

测试数据

  • 测试数据脚本
  • Faker模拟数据

持续集成(CI)中使用Cypress

Cypress Cloud

拦截网络请求

拦截

//拦截对/users路由的任何POST请求
cy.intercept("POST", "/users")
//拦截对任何与 /transactions/public *匹配的路由的GET请求
beforeEach(() => {
  cy.intercept("GET", "/transactions/public*").as("publicTransactions")
})
​
​
​

使用fixture覆盖返回体

//拦截并覆盖数据
cy.intercept("GET", "/transactions/public*", {
  // ...
  fixture: "public-transactions.json",
}).as("mockedPublicTransactions")
​

更改响应头

响应中的原始标头将保持不变。这些新标头将附加到原始标头中。

cy.intercept("GET", "/transactions/public*", {
  headers: {
    "X-Powered-By": "Express",
    Date: new Date().toString(),
  },
})

修改响应数据:

我们需要使用.continue()来修改响应数据。

cy.intercept("POST", "/bankaccounts", (req) => {
  const { body } = req
  req.continue((res) => {
    res.body.data.listBankAccount = []
  })
})

检查请求

cy.intercept("POST", apiGraphQL, (req) => {
  const { body } = req
​
  if (
    body.hasOwnProperty("operationName") &&
    body.operationName === "CreateBankAccount"
  ) {
    req.alias = "gqlCreateBankAccountMutation"
  }
})
​

同步等待请求

cy.intercept('POST', '/users').as('signup');
cy.wait('@signup')

API 和集成测试

RWA:真实世界应用程序

发起请求

// cypress/tests/api/api-users.spec.tscontext("GET /users", () => {
  it("gets a list of users", () => {
    cy.request("GET", "/users").then((response) => {
      expect(response.status).to.eq(200)
      expect(response.body.results).length.to.be.greaterThan(1)
    })
  })
})
​

自定义命令

cypress.command可以支持自定义命令

声明自定义命令:

Cypress.Commands.add("loginByApi", (username, password) => {
  return cy.request("POST", `http://localhost:3000/login`, {
    username,
    password,
  })
})
​

使用自定义命令:

describe("POST /login", () => {
  it("login as user", () => {
    cy.loginByApi("jdoe", "password123").then((response) => {
      expect(response.status).to.eq(200)
    })
  })
})

视口和浏览器测试技巧

在多个浏览器和各种屏幕尺寸中运行所有测试非常重要。目前,Cypress 支持Chrome 系列浏览器(包括基于 Electron 和 Chromium 的 Microsoft Edge)、WebKit(Safari 的浏览器引擎,目前在 Cypress 中处于实验状态)和 Firefox。

指定运行浏览器

1.ci命令里设置参数

--browser

cypress run --browser Firefox

2.UI页面里选择参数

3.测试用例里

//对位于describe()块内的所有测试执行此操作
describe("happy path suite", { browser: "firefox" }, () => {
  it("...")
  it("...")
  it("...")
})
​
//或者// Run the test if Cypress is run via Chrome
it('Show warning outside Chrome', { browser: 'chrome' }, () => {
  // ...
})

测试手机

默认情况下,RWA 中的所有测试都是为桌面编写的。在 中package.json,我们有自定义脚本来启动具有移动维度的 Cypress。

1.ci设置参数--config

"cypress:open:mobile": "cypress open --config viewportWidth=375,viewportHeight=667",
"cypress:run:mobile": "cypress run --config viewportWidth=375,viewportHeight=667",

2.实用函数isMobile()

export const isMobile = () => {
  return (
    Cypress.config("viewportWidth") <
    Cypress.env("mobileViewportWidthBreakpoint")
  )
}
​
​
//环境变量mobileViewportWidthBreakpoint位于cypress.json配置文件中。
{
  // ..."env": {
    "apiUrl": "http://localhost:3001",
    "mobileViewportWidthBreakpoint": 414,
    "coverage": false,
    "codeCoverage": {
      "url": "http://localhost:3001/__coverage__"
    }
  },
  "experimentalStudio": true
}
​

cypress Method

  1. its(属性|下标,options)从数组或者对象里取值

    cy.wrap({ age: 52 }).its("age").should("eq", 52) // true
    
  2. invoke(options?,functionName,args...?) 在JS 数据类型上调用 JS 函数。

    cy.wrap(["Wai Yan", "Yu"]).invoke("slice", 0, 1)
    
  3. request()发起http请求

  4. within()

数据驱动测试

可以自定义模拟数据甚至请求真实的数据来进行测试,这种方式比硬编码数据有以下几个好处:

1.更接近真实用户的交互

2.比硬编码数据维护更简单