Test specification

Hello, everyone, MY name is Melio Piggy. Front-end engineering testing is an area I have never touched before, so I only have a simple understanding of it. After reading the team’s test specifications, I feel that there is a lot to learn

  • Unit test (This study is based on Jest. As the cute new me, write a case of Hello world with all kinds of cute new similar to me.)

    • Test as a programmer
    • Unit tests treat code as components. Each component can be individually tested to see if each function in the component returns as expected.
    • Technology stack: JEST
  • E2E testing (to be added later at some time)

    • Test from the user’s perspective
    • E2e or end-to-end or UI testing is a way of testing, I don’t know how you do it internally, to see if an application flows from beginning to end as it was designed. I just open the browser, type the test on the page, and see if it’s what I want. In short, from a user’s perspective, it sees the entire system as a black box, with only the UI exposed to the user
    • Technology stack: Cypress
  • Both are very meaningful.

    • The unit test is an easy way for programmers to test whether their logic returns the correct ones after they have written it.
    • E2e code is to test whether all requirements can be correctly completed, and the final thing is that after code refactoring and JS changes a lot, the test code does not need to be changed when testing requirements, and you do not have to worry about not meeting customer requirements after refactoring.

Let’s start playing Jest briefly

Begin to learn

Set up the environment

Jest — NPX jest –init create a new folder named jest-demo, yarn init -y initialize package.json, yarn add jest-d install jest dependencies, NPX jest –init generate initialization file, this is our simple setup environment. Each of the terms I chose for NPX jest –init looks like this

  • Whether to generate the test command in package.json – select yes, so we see scripts moretestOrder, and then justyarn testIt’s ok. Here’s my understanding. It should be as long as it isxxx.test.jsWill run
  • Is the configuration file to use TS – select no here, use JS to test the waters first
  • Select test environment – we did not select Node, selectbrowser-likeBrowser-like environment
  • Test coverage report – the option is to play with it and see if your test coverage is 100%. Here we can manually set thepackage.jsonTo add test coverage execution commands"test-c": "jest --coverage"
  • The following two configuration options do not understand deeply, first do not mislead people, choose the default, later understand again to supplement

Start coding

Create score.js directly under the root directory, code we write simple, test above 60 (including 60) pass, below 60 fail

function testScore (score) {
    return score >= 60 ? 'pass' : 'Must make an effort'
}

module.exports = {
    testScore,
}
Copy the code

To start writing test cases, create a new file in the root directory of score.test.js

const { testScore } = require('./score')

test('Test 60 points'.() = > {
    expect(testScore(60)).toBe('pass')})Copy the code

The first argument to the test function is a string that describes what we are testing. The second argument is a callback function, and the logic is there. Expect means what we expect. Here we call testScore(60), which is clearly passing, and then we call toBe, which is a matcher, which is equal to ===, and there are various matchers to follow. Let’s first play with the simplest toBe, and then we ask what we expect to get, which is whether it matches the value returned by the logic function we wrote. We say ‘pass’ the test must be ok, and then we can run the unit test YARN test

Awesome, as we expected, we intentionally changed the toBe parameters wrong to take a look

We made an error, but as we expected, the error message was complete, then we changed back to the correct pass at the beginning, and then ran yarn test-C test coverage to see

Oh, my god, don’t understand, baidu for the next

It turns out that our if branch is not fully covered, and there are lines that are not covered, mainly because we don’t have failed tests, so let’s arrange, add failed tests, and then we’ll look at coverage

test('Test 20 points'.() = > {
    expect(testScore(20)).toBe('Must make an effort')})Copy the code

By the way, sometimes our leaders may want to see our test coverage, so it is impossible to directly show our terminal screenshots to them. In fact, Jest helped us generate the folder of Coverage, so you can find the corresponding page and open it. The path is in the index.html file under coverage\lcov-report, which is pretty cool because we’re testing a module now (score.js), so there’s only one line in the table, so as the project’s test file gets bigger and bigger, the test coverage report will also show up

They want to practice, and I almost adorable new XDM do exercises together to strengthen a wave of practice

After understanding the basic knowledge, a good memory is not as good as bad writing, in a similar, set questions for everyone, and then write a unit test to cover all

  • Create a new module for string-related methods

    • Implements a method that removes all whitespace
    • Implement the string inversion method
    • Implement the compose function, remix the previous method, and derive a new method (removeAllSpaceAndReverse)
  • Test related code

    • Tests whether removing all whitespace is achieved
    • Tests whether the string inversion method is implemented
    • Tests whether the result of removing all whitespace and then reversing the string is the same as the result of reversing the string and then removing all whitespace
    • (Additional questions) Test removeAllSpaceAndReverse

Announced the answer

  • The str.js code is as follows
function removeAllSpace (str) {
    return str.replace(/\s/g.' ')}function reverseStr (str) {
    return str.split(' ').reverse().join(' ')}const compose = (. fns) = > str= > fns.reduce((current, fn) = > fn(current), str)

const removeAllSpaceAndReverse = compose(removeAllSpace, reverseStr)

module.exports = {
    removeAllSpace,
    reverseStr,
    removeAllSpaceAndReverse
}
Copy the code
  • The str.test.js code is as follows
const {
    removeAllSpace,
    reverseStr,
    removeAllSpaceAndReverse
} = require('./str')

test('Test remove all Spaces - A, b, c'.() = > {
    expect(removeAllSpace(' a b c ')).toBe('abc')
})

test('Test string inversion - ABC'.() = > {
    expect(reverseStr('abc')).toBe('cba')
})

test('Tests whether the result of removing all whitespace and then reversing the string is the same as the result of reversing the string and then removing all whitespace'.() = > {
    expect(reverseStr(removeAllSpace(' a b c '))).toBe(removeAllSpace(reverseStr(' a b c ')))
})

test('Test whether the blending function can remove all Spaces and reverse the string -removeAllSpaceAndReverse'.() = > {
    expect(removeAllSpaceAndReverse(' a b c ')).toBe('cba')})Copy the code
  • The following figure shows the terminal

We have two unit tests, score and STR, and six test cases (score has two and STR has four), and all of them are covered

  • Page view coverage

Compose doesn’t understand. Come and see

I don’t know if you’ve seen the source code for Redux, but it has the compose idea in it

export default function compose(. funcs:Function[]) {
  if (funcs.length === 0) {
    // infer the argument type so it is usable in inference down the line
    return <T>(arg: T) = > arg
  }

  if (funcs.length === 1) {
    return funcs[0]}return funcs.reduce((a, b) = > (. args:any) = >a(b(... args))) }Copy the code

So this is actually middleware processing, and it’s very clever, and our example here is pretty much the same, suppose we have a string operation with a, B, and C, and we happen to have a requirement, and all three of these methods are going to work on this string, A (b(c(STR))) or c(b(a(STR))) could both be implemented, but if there were more methods, the code would look very uncomfortable. In this case, we could use the idea of compose, a higher-order function, and return a completely new function

const compose = (. fns) = > str= > fns.reduce((current, fn) = > fn(current), str)
Copy the code

First we accept a mixture of several functions, so the initial… FNS is to take these functions, and then our higher-order function here is to return a function, and this new function is what we’re going to use, take a string, and then write the logic inside, and the unpacking step should be like this

const compose = (. fns) = > (str= >The logic inside)//(STR =>) consider this as a whole, i.e. the return value is a function
Copy the code

Next, we need to operate the function step by step. The return value of the former function is accepted as the result of the next function, using reduce. At this time, we need to test our understanding of reduce. If you don’t pass it by default it’s the first item in the array, which is the first function we pass, so you end up with something like this, and it passes happily

const compose = (. fns) = > str= > fns.reduce((current, fn) = > fn(current), str)
Copy the code

conclusion

Another article, this time the Hello World version of Jest, hope you enjoy it! (Continue to grow stronger, waiting for the big guy to fly)