E2E Testing, what & how

IES 前端架构 - 基础体验 - 龙逸楠

  • E2E testing 介绍
  • E2E testing 中的一些基本概念介绍
  • 前端 E2E 框架,如何选择
  • 如何编写 E2E 测试

E2E testing 介绍

  • E2E testing 定义
  • E2E testing 示例

E2E testing 定义

End-to-end testing is a technique used to test whether the flow of an application right from start to finish is behaving as expected

在实际场景中,我们通常将测试从功能点的维度拆分。

E2E testing 定义

E2E testing 主要用来测试业务流程的正确性,单个组件内部的逻辑验证主要依靠 unit test。

 

从使用场景来说,E2E testing 是用来捕获那些重大的影响用户可用性的缺陷。而 unit test 主要是用来捕获那些边缘场景下的缺陷。

E2E testing 示例

E2E testing 中的几个重要的概念

Spy

Stub

Mock

Spy

  • test legacy code collaborators that are too difficult or impossible to test with a Mock or Stub
  • verify the collaborator's method is called the correct number of times
  • verify the collaborator's method is called with the correct parameters
  • provide a predetermined response from a collaborator
  • take a predetermined action from a collaborator, like throwing an exception

观察一个函数或者方法,不改变原有方法的行为(参数,实现和返回值)。可以拿到被观察函数/方法被调用的次数,和参数等信息

Spy

Stub

  • provide a predetermined response from a collaborator
  • take a predetermined action from a collaborator, like throwing an exception

控制一个函数/方法的行为。比如第一次调用的时候的返回值,或者接收到某个参数的时候的返回值。

Stub

Mock

  • verify the contract between the code under test and a collaborator
  • verify the the collaborator's method is called the correct number of times
  • verify the collaborator's method is called with the correct parameters

和 Stub 类似,但是 Stub 是在运行时决定在接受到某种输入的时候响应某个输出,而 Mock 是静态的。

Mock

Class MockService {

  getUser() {
    return Promise.resolve({ id: 1, name: 'mock user' })
  }
}

前端 E2E 框架,如何选择

Selenium + nightwatch

Karma + Protractor

Cypress

  • 能力大同小异,都可以 Cover 大部分的业务场景

  • Selenium 依赖 Python 工具链,对前端项目不是很友好

  • Karma 和 Protractor 都是随着 AngularJS 诞生,其生态围绕 AngularJS 发展

对比

选择 Cypress

建议

  • Docker/CI 友好
  • 开箱即用,默认的录屏,截图功能非常好用,可以很方便的 Debug (https://code.byted.org/toutiao-fe/slardar/-/jobs/6446824)
  • npm 生态,对于前端项目本地测试友好

如何编写 E2E 测试

describe('My First Test', () => {
  it('clicking "type" navigates to a new url', () => {
    cy.visit('https://example.cypress.io')

    cy.contains('type').click()

    // Should be on a new URL which includes '/commands/actions'
    cy.url().should('include', '/commands/actions')
  })
})

Mock/Stub App 中影响测试稳定的部分

  • 测试无关但影响功能的 API 请求
  • 非 CDN 的资源
  • 第三方 SDK 的请求

Spy 异步 API 断言 App 执行过程的正确性

  • Ajax/Fetch
  • Timer
  • Router

使用 Element Query API 断言 UI 正确性

  • 在源码中标记 Hero Element
  • UI 上尽量不要让 Hero Element 被遮住
  • 用 Lint 或者其它工具保证 Hero Element 的唯一性和不可变性

Example

https://code.byted.org/appmonitor/maiev

Q & A

deck

By yinan

deck

  • 806