React modern test

Motivation Test

Test case writing is a risk-driven behavior, whenever Bug reports received, the first to write a unit test to expose the Bug, submit the code in the future, if the test is passed, developers will be able to more ensure confidence for this bug does not occur again.

Motive test is to effectively improve the self-confidence of developers.

Modern front-end test model

There are two models in the front end of the test, 金字塔模型and 奖杯模型.

Pyramid model taken from Martin Fowler apos Blog , a schematic model as follows:

Pyramid bottom-up model is divided into unit testing, integration testing, UI testing, the reason is because the highest costs of the pyramid structure is the lowest cost unit testing, contrast, UI testing. So the largest number of unit test writing, a minimum number of UI tests written. Also note that the more upper-layer testing, confidence to developers to bring their pass rate is greater.

Trophy models are taken from Kent C. Dots presented at The Testing Trophy , the model is more recognized author of modern front-end test model, schematic model is as follows:

Trophy model into bottom-static testing, unit testing, integration testing, E2E test their functions as follows:

  • 静态测试: Tips to report the error when writing code logic stage. (On behalf of the library: eslint, flow, TypeScript)
  • 单元测试: In the trophy model, unit testing duties for some edge cases or a specific algorithm for testing. (On behalf of the library: JEST , Mocha )
  • 集成测试: User behavior simulation for testing of network requests, rely on third parties to obtain environmental behavior data from a database, etc. mock. (On behalf of the library: JEST , REACT-Testing-Library )
  • e2e 测试: Simulate user behavior (including network request to obtain database data, etc.) is tested in a real environment. (On behalf of the library: Cypress )

The more upper test to developers to bring greater self-confidence is, at the same time, the more efficient the lower test test is higher. Trophy model took into account these two factors, we can see the proportion of integration testing is the highest.

Based on user behavior to test

Writing test cases is to increase the self-confidence of the developers of the program, but a lot of time writing test cases brought to the developers feel frustrated doing useful work. Resulting in depressed feeling occurs often because developers to implement the details of specific components were tested, if a user from another angle standing on the conduct of the test can greatly improve test efficiency.

Specific details of the test components will bring the two issues:

  1. Test code 错误否定;
  2. Test code 错误肯定;

With 轮播图组件, for example, in order to see the above-mentioned problems. FIG carousel assembly pseudo-code as follows:

class Carousel extends React.Component {
  state = {
    index: 0
  }

  /* 跳转到指定的页数 */
  jump = (to: number) => {
    this.setState({
      index: to
    })
  }

  render() {
    const { index } = this.state
    return <>
      <Swipe currentPage={index} />
      <button onClick={() => this.jump(index + 1)}>下一页</button>
      <span>`当前位于第${index}页`</span>
    </>
  }
}

The following is based on enzymethe api to write test cases:

import { mount } from 'enzyme'

describe('Carousel Test', () => {
  it('test jump', () => {
    const wrapper = mount(<Carousel>
      <div>第一页</div>
      <div>第二页</div>
      <div>第三页</div>
    </Carousel>)

    expect(wrapper.state('index')).toBe(0)
    wrapper.instance().jump(2)
    expect((wrapper.state('index')).toBe(2)
  })
})

Congratulations, tested by ✅. One day the developers feel that indexthe naming is wrong, its reconstruction will be indexrenamed currentPage, this time code is as follows:

class Carousel extends React.Component {
  state = {
    currentPage: 0
  }

  /* 跳转到指定的页数 */
  jump = (to: number) => {
    this.setState({
      currentPage: to
    })
  }

  render() {
    const { currentPage } = this.state
    return <>
      <Swipe currentPage={currentPage} />
      <button onClick={() => this.jump(currentPage + 1)}>下一页</button>
      <span>`当前位于第${currentPage}页`</span>
    </>
  }
}

Run the test case again, this time in expect(wrapper.state('index')).toBe(0)the wrong place throws ❌, which is called the code a test case 错误否定. Because this code is for consumers there is no problem, but it throws an error test cases, developers have to do at this time 'wasted effort' to adjust the fit test the new code. Test adjusted as follows:

describe('Carousel Test', () => {
  it('test jump', () => {
    ...

-   expect(wrapper.state('index')).toBe(0)
+   expect(wrapper.state('currentPage')).toBe(0)
    wrapper.instance().jump(2)
-   expect((wrapper.state('index')).toBe(2)
+   expect((wrapper.state('currentPage')).toBe(2)
  })
})

Then one day a careless student Xiao Ming made the following changes to the code:

class Carousel extends React.Component {
  state = {
    currentPage: 0
  }

  /* 跳转到指定的页数 */
  jump = (to: number) => {
    this.setState({
      currentPage: to
    })
  }

  render() {
    const { currentPage } = this.state
    return <>
      <Swipe currentPage={currentPage} />
-     <button onClick={() => this.jump(currentPage + 1)}>下一页</button>
+     <button onClick={this.jump(currentPage + 1)}>下一页</button>
      <span>`当前位于第${index}页`</span>
    </>
  }
}

Xiaoming students of the single test run, the test passes ✅, so happy submitted code. The results on the line after the line there is a problem! It's called the code a test case 错误肯定. Because the details of the internal components of the test cases (here jumpfunction), so that Xiao Ming misunderstanding that has been covering the entire scene.

Test cases 错误否定and 错误肯定gave the developers to bring frustration and distress, the reason is to test the specific details of the internal components of actions. The test should be a stable and reliable implementation details from the internal components, the closer the test user behavior to give developers to bring more abundant self-confidence. Compared to Enzyme, REACT-Testing-Library provided api closer to the user's usage behavior, use it to reconstruct the above test cases:

import { render, fireEvent } from '@testing-library/react'

describe('Carousel Test', () => {
  it('test jump', () => {
    const { getByText } = render(<Carousel>
      <div>第一页</div>
      <div>第二页</div>
      <div>第三页</div>
    </Carousel>)

    expect(getByText(/当前位于第一页/)).toBeInTheDocument()
    fireEvent.click(getByText(/下一页/))
    expect(getByText(/当前位于第一页/)).not.toBeInTheDocument()
    expect(getByText(/当前位于第二页/)).toBeInTheDocument()
  })
})

About react-testing-Libraryusage summary will be in the next chapter Jest and react-testing-Library specific description. If you are interested React technology stack, welcome attention personal blog .

Related Links

Guess you like

Origin www.cnblogs.com/MuYunyun/p/11406989.html