• [Unit Testing] Fundamentals of Testing in Javascript


    In this lesson, we’ll get the most fundamental understanding of what an automated test is in JavaScript. A test is code that throws an error when the actual result of something does not match the expected output. 

    Tests can get more complicated when you’re dealing with code that depends on some state to be set up first (like a component needs to be rendered to the document before you can fire browser events, or there needs to be users in the database). However, it is relatively easy to test pure functions (functions which will always return the same output for a given input and not change the state of the world around them).

    Base file to test against:

    math.js

    const sum = (a, b) => a - b;
    const subtract = (a, b) => a - b;
    
    const sumAsync = (...args) => Promise.resolve(sum(...args));
    const subtractAsync = (...args) => Promise.resolve(subtract(...args));
    
    module.exports = { sum, subtract, sumAsync, subtractAsync };

     index.js

    const { sum, subtract } = require("./math");
    
    let result, expected;
    
    result = sum(3, 7);
    expected = 10;
    if (actual !== expected) {
       throw new Error(`${result} is not equal to ${expected}`);
    }
    
    result = subtract(7, 3);
    expected = 4;
    if (actual !== expected) {
       throw new Error(`${result} is not equal to ${expected}`);
    }

    Let’s add a simple layer of abstraction in our simple test to make writing tests easier. The assertion library will help our test assertions read more like a phrase you might say which will help people understand our intentions better. It will also help us avoid unnecessary duplication.

    const { sum, subtract } = require("./math");
    
    let result, expected;
    
    result = sum(3, 7);
    expected = 10;
    expect(result).toBe(expected);
    
    result = subtract(7, 3);
    expected = 4;
    expect(result).toBe(expected);
    
    function expect(actual) {
      return {
        toBe(expected) {
          if (actual !== expected) {
            throw new Error(`${actual} is not equal to ${expected}`);
          }
        }
      };
    }

    This is also a common way to write a assetion library, expect() function take a actual value and return an object contains 'toBe', 'toEqual'... functions.

    One of the limitations of the way that this test is written is that as soon as one of these assertions experiences an error, the other tests are not run. It can really help developers identify what the problem is if they can see the results of all of the tests.

    Let’s create our own test function to allow us to encapsulate our automated tests, isolate them from other tests in the file, and ensure we run all the tests in the file with more helpful error messages.

    const { sum, subtract } = require("./math");
    
    let result, expected;
    
    test("sum adds numbers", () => {
      result = sum(3, 7);
      expected = 10;
      expect(result).toBe(expected);
    });
    
    test("subtract substracts numbers", () => {
      result = subtract(7, 3);
      expected = 4;
      expect(result).toBe(expected);
    });
    
    function test(title, cb) {
      try {
        cb();
        console.log(`%c ✔︎ ${title}`, "color: green");
      } catch (err) {
        console.error(`✘ ${title}`);
        console.error(err);
      }
    }

    Our testing framework works great for our synchronous test. What if we had some asynchronous functions that we wanted to test? We could make our callback functions async, and then use the await keyword to wait for that to resolve, then we can make our assertion on the result and the expected.

    Let’s make our testing framework support promises so users can use async/await.

    const { sumAsync, subtractAsync } = require("./math");
    
    let result, expected;
    
    test("sum adds numbers", async () => {
      result = await sumAsync(3, 7);
      expected = 10;
      expect(result).toBe(expected);
    });
    
    test("subtract substracts numbers", async () => {
      result = await subtractAsync(7, 3);
      expected = 4;
      expect(result).toBe(expected);
    });
    
    function test(title, cb) {
      try {
        cb();
        console.log(`%c ✔︎ ${title}`, "color: green");
      } catch (err) {
        console.error(`✘ ${title}`);
        console.error(err);
      }
    }
    
    function expect(actual) {
      return {
        toBe(expected) {
          if (actual !== expected) {
            throw new Error(`${actual} is not equal to ${expected}`);
          }
        }
      };
    }

    To fix the problem, we can make our testing lib async / await.

    async function test(title, cb) {
      try {
        await cb();
        console.log(`%c ✔︎ ${title}`, "color: green");
      } catch (err) {
        console.error(`✘ ${title}`);
        console.error(err);
      }
    }

    Not it works normal again.

    These testing utilities that we built are pretty useful. We want to be able to use them throughout our application in every single one of our test files.

    Some testing frameworks provide their helpers as global variables. Let’s implement this functionality to make it easier to use our testing framework and assertion library. We can do this by exposing our test and expect functions on the global object available throughout the application.

    setup-global.js:

    async function test(title, cb) {
      try {
        await cb();
        console.log(`%c ✔︎ ${title}`, "color: green");
      } catch (err) {
        console.error(`✘ ${title}`);
        console.error(err);
      }
    }
    
    function expect(actual) {
      return {
        toBe(expected) {
          if (actual !== expected) {
            throw new Error(`${actual} is not equal to ${expected}`);
          }
        }
      };
    }
    
    global.test = test;
    global.expect = expect;

    Run:

    node --require ./setup-global.js src/index.js

    Up to this point we’ve created all our own utilities. As it turns out, the utilities we’ve created mirror the utilities provided by Jest perfectly! Let’s install Jest and use it to run our test!

    npx jest
  • 相关阅读:
    VUE脚手架,babel转码 常用命令
    ES6那些事半功倍的新特性(一)
    vuex中怎么把‘库’中的状态对象赋值给内部对象(三种方法)
    VUE自定义指令生命周期,VUE生命周期
    判断是数组还是对象的方法
    利用cordova打包H5混合app
    webstorm皮肤外观样式快速设置,CMD的使用方法,webstorm11激活方法
    数组操作方法中的splice()和concat() 以及slice()
    Angularjs跨域
    Node.js的基础知识(一)
  • 原文地址:https://www.cnblogs.com/Answer1215/p/9847563.html
Copyright © 2020-2023  润新知