Front-end test Jest (to be continued)

1 Configuration Environment

  1. Node NPM install –save-dev jest needs to be configured in the environment variable
  2. yarn yarn add –dev jest yarn global add jest

2 demo

Jest project files are xx.test.js. When we run a JEST project, Jest will automatically find scripts running with the suffix *.test.js for unit tests.

Machers numerous match judges

  1. ToBe () is used to verify that the values of the base data type are equal
  2. ToEqual () is used to check the value of a reference data type. Due to the nature of the JS object data type itself, reference data type comparison is only a comparison of Pointers, but each value of the object needs to be compared, so this is used toEqual().
  3. Truthiness Indicates the verifier for Boolean judgment
  • ToBeNull matches only null
  • ToBeUndefined matches undefined only
  • ToBeDefined is the opposite of toBeUndefined
  • ToBeTruthy matches any if statement as true
  • ToBeFalsy matches any if statement as false
  1. A digital matcher is used to judge the comparison between numeric values
  • ToBeGreaterThan is greater than the matcher
  • ToBeGreaterThanOrEqual is greater than or equal to the matcher
  • ToBeLessThan is less than the matcher
  • ToBeLessThanOrEqual is less than or equal to the matcher
  • Tobe and toequal are both equivalent and functionally the same for numbers
  1. ToMatch string matchers have the same match as strings
  2. The toContain array filter is used to determine whether an array contains any values
  3. The toThrow error matcher is used to test for a specific throw error, either by determining the text of the error statement (which supports regular matching) or by determining the type of error.

Determination of asynchronous code

Js based on the single-thread asynchronous characteristics, in the code filled with asynchronous programs and various callbacks, so we should pay special attention to the test of asynchronous code. Here are some examples of asynchrony

  1. The callback callbacks
test('the data is peanut butter', () = > {function callback(data) {
    expect(data).toBe('peanut butter'); } fetchData(callback); }); / / this kind of situation has a problem, everyone knows that an ajax request is an event (composed of two transactions sent and return), when sending successful and the return of the event is completed, is a success, jest is considered complete ajax events at this time, so the inspection can be carried in the callback judgment before the end, no validation data data, So this is problematic.Copy the code

Jest provides a method to do to solve this problem, ensuring that the callback is executed to complete the test validation. Call done with a single argument, rather than a function that puts the test on an empty argument. Jest will wait for the done callback to finish the test. let’s show code

test('the data is peanut butter'.done= > {function callback(data) {
    expect(data).toBe('peanut butter');
    done(a); } fetchData(callback); }); ifdone() will never be called, and the test will fail, which is what you want to happen.Copy the code
  1. Promise code We have an easier way to test asynchronously using promises for asynchronous applications. If the Promise returns a reject status, the test automatically fails.
    test('Promise test', ()=>{// assert tests expect. Assertions (1); // Do rememberreturnOtherwise, the test won't get the promise state, and the test will finish before fetchData() completes.return fetchData().then(data=>{
            expect(data).tobe('promise')})})Copy the code

If the expected promise is reject, we can use catch to catch our errors. Be sure to add expect. Assertions to verify that a certain number of assertions are called. Otherwise, a fulfilled Promise will not make the test fail.

test('the fetch fails with an error', () => {
  expect.assertions(1);
  return fetchData().catch(e => expect(e).toMatch('error'));
});
Copy the code
  1. Jest has a special handling of promises, such as high susceptibility and rejects. The promise is processed using a convertor, and the test automatically fails if a reject state is returned. Remember not to lose the return. This is a pity. If you wish a promise to return a reject, then the test fails. This is a pity.
 // let's show code~ // resolves test('the data is peanut butter', () => { expect.assertions(1); return expect(fetchData()).resolves.toBe('peanut butter'); }); // rejects test('the fetch fails with an error', () => { expect.assertions(1); return expect(fetchData()).rejects.toMatch('error'); });Copy the code
  1. Async/Await You can also use Async/Await to process asynchronous tests. Just add the async keyword in front of the test callback function.
// Learn about async and await usage methods and scenarios in advancetest('the data is peanut butter', async () => {// Remember to add assertions to test expect. Assertions (1); const data = await fetchData(); expect(data).toBe('peanut butter');
});

test('the fetch fails with an error', async () => { expect.assertions(1); // Remember to add the assertion test try {await fetchData(); } catch (e) { expect(e).toMatch('error'); }});Copy the code

Convergent use is also possible: /.rejects and Async/Await

// Because await itself returns a promise. So we can continue testing our code based on the returned promise.test('the data is peanut butter', async () => {
  expect.assertions(1);
  await expect(fetchData()).resolves.toBe('peanut butter');
});

test('the fetch fails with an error', async () => {
  expect.assertions(1);
  await expect(fetchData()).rejects.toMatch('error');
});
Copy the code

#Jest traversal and Setup and Teardown for some repetitive test Settings, we can use beforeEach and afterEach. Suppose we need to repeat some test setup on an interactive data set. Suppose initializeCityDatabase() is called before the test and clearCityDatabase() is called after the test. We can then use beforeEach and afterEach. let’s show code~

beforeEach and afterEach

    beforeEach(() => {
      initializeCityDatabase();
    });
    
    afterEach(() => {
      clearCityDatabase();
    });
    
    test('city database has Vienna', () => {
      expect(isCity('Vienna')).toBeTruthy();
    });
    
    test('city database has San Juan', () => {
      expect(isCity('San Juan')).toBeTruthy();
    });
Copy the code

BeforeEach and afterEach handle asynchronous code, which can also use done and Promise, if initializeCityDatabase() returns a promise. let’s show code

    beforeEach(()=>{
        return initializeCityDatabase(); // returnA promise})Copy the code

beforeAll and afterAll

Scoping

We can modularize our tests by creating a scope using Jest’s Describe function and the IDEA of JS functional programming. Specific scenarios are used to model the scope of our foreach through describe. let’s show code

// Here beforeEach applies to alltest
beforeEach(() => {
  return initializeCityDatabase();
});

test('city database has Vienna', () => {
  expect(isCity('Vienna')).toBeTruthy();
});

test('city database has San Juan', () => {
  expect(isCity('San Juan')).toBeTruthy();
});

describe('matching cities to foods', () => {// here beforeEach applies only to tests in describe beforeEach(() => {return initializeFoodDatabase();
  });

  test('Vienna <3 sausage', () => {
    expect(isValidCityFoodPair('Vienna'.'Wiener Schnitzel')).toBe(true);
  });

  test('San Juan <3 plantains', () => {
    expect(isValidCityFoodPair('San Juan'.'Mofongo')).toBe(true);
  });
});
Copy the code

With so much beforeEach/afterEach and beforeAll/afterAll, combine descibe to see our execution order. I believe you will remember js after reading (task queue and scope).

    beforeAll(() => console.log('1 - beforeAll'));
    afterAll(() => console.log('1 - afterAll'));
    beforeEach(() => console.log('1 - beforeEach'));
    afterEach(() => console.log('1 - afterEach'));
    test(' ', () => console.log('1 - test'));
    describe('Scoped / Nested block', () => {
      beforeAll(() => console.log('2 - beforeAll'));
      afterAll(() => console.log('2 - afterAll'));
      beforeEach(() => console.log('2 - beforeEach'));
      afterEach(() => console.log('2 - afterEach'));
      test(' ', () => console.log('2 - test'));
    });
    
    // 1 - beforeAll
    // 1 - beforeEach
    // 1 - test
    // 1 - afterEach
    // 2 - beforeAll
    // 1 - beforeEach
    // 2 - beforeEach
    // 2 - test// 2-aftereach // 1-aftereach // 2-afterall // 1-afterall As the result view order, global will be applied to describe internal. Notice the order of execution, beforeALL and afterAll are executed only once, global beforeEach applies to describetestAlso note that after in the after scope executes before global after. BeforeAll is executed before beforeEach, while afterAll is executed after afterEach.Copy the code

If you want to run just one of the many tests, you can simply add.only to the test statement and skip the other tests

// Only this onetestRun the test. Only ('this will be the only test that runs', () => {
  expect(true).toBe(false); }); / / thistestWill be skippedtest('this test will not run', () => {
  expect('A').toBe('A');
});
Copy the code