First of all, make an advertisement to your friends, the circle and the upcoming circle of big guys all understand, a class and various platforms such as Geek,Kaikeba and other low price resources, package update, in the hands of the first-line development buddy, at the same time for the upcoming candidates have interview guidance technology refers to the service, plus he sa!

First of all, for a long time, unit testing of front-end development has not been a necessary part of the front-end development process, nor is it something that every front-end development engineer pays attention to, nor is it even a part of the software development process that is written in the charter. However, with the complexity of each project, the high reusability of the code, and the high cohesion and low coupling between the front-end code modules, the unit testing process in front-end engineering becomes necessary.

1. What are front-end unit tests

First we need to be clear about what the test is:

In order to detect whether a specific target is in conformity with the standard, the use of special tools or methods for verification, and finally get a specific result.

For the front-end development process, the specific goal is the code we write, and the tools are the test frameworks (libraries), test cases, and so on that we need to use. The result of the inspection office is to show whether the test is passed or give a test report, so as to facilitate troubleshooting and later correction.

Based on the “what” of testing, for the advanced understanding of those new to front-end development, let’s list the “what” of unit testing:

Tests that require database access are not unit tests

Tests that require network access are not unit tests

Tests that require access to the file system are not unit tests

— The art of modifying code

So much for a reference to the explanation of what unit tests are not. Given the limited space, I think the front end developers will have an initial understanding of what the references are.

2. What unit tests mean and why they are needed

2.1 Significance of unit testing

For current front-end engineering, a standard complete project, testing is very necessary. Many times we just complete the project and ignore the testing part of the project. The significance of testing is mainly for the following points:

  1. TDD (Test Driven Development) has proven to be an effective software writing principle that can cover more functional interfaces.
  2. Feedback quickly on your functional output and validate your ideas.
  3. To ensure the security of code refactoring, there is no fixed code, and test cases can give you the peace of mind about changing code structures.
  4. Code that is easy to test is a good design. Before you do a unit test, you must instantiate something. If it has many dependencies, the test should be constructed 7. The manufacturing process will be very time consuming and will affect your testing efficiency. What should we do? To separate dependencies, try to keep a class as simple as possible, such as separating views from functions, so that your code is easy to maintain and understand.

2.2 Why do we need unit tests

  1. The first is a fundamental reason for front-end unit testing: JavaScript is dynamic, there is no type checking, and errors cannot be found during compilation. JavaScript host compatibility issues. For example, how DOM manipulation behaves on different browsers.
  2. Correctness: Testing is a way to verify that your code is correct before you go live.
  3. Automation: Of course you can also test manually and print out the internal information through the console, but this is a one-time thing and the next test will have to be done from scratch, so efficiency cannot be guaranteed. By writing test cases, you can write them once and run them many times.
  4. Explanatory: Test cases are used to test the importance of interfaces, modules, and how to use these apis is covered in the test cases. Reading test cases is a good way for other developers to use these apis, sometimes more clearly than the documentation.
  5. Driving development and guiding design: The prerequisite for code to be tested is the testability of the code itself, so to ensure the testability of the code, we need to pay attention to the DESIGN of the API in the development, TDD test forward plays such a role.
  6. Guarantee refactoring: The Internet industry product iteration speed is very fast, there must be code refactoring process after iteration, then how to ensure the quality of refactoring code? With test cases behind you, refactoring can be bold.

3. How to write unit test cases

3.1 the principle of

  • When you test your code, only the tests are considered, not the internal implementation
  • The data is as close to reality as possible
  • Fully consider the boundary conditions of the data
  • For key, complex, core code, focus testing
  • Use AOP(beforeEach, afterEach) to reduce the amount of test code and avoid useless features
  • The combination of testing and functional development facilitates design and code refactoring

3.2 Two common unit testing methodologies

In unit testing, there are two common methodologies: TDD (Test Driven Development) and BDD (Behavior Driven Development)

For those who have not heard of these two modes of front-end testing before, they can learn about them here.

3.3 I believe that you will have your own personal views on TDD and BDD after reading the book. Here I will first talk about my understanding of TDD and BDD:

TDD (Test-Driven Development) :

The basic idea is to drive development through testing.

  • The primary purpose of unit testing is not to be able to write all-passing test code with high coverage, but rather to try out the possibilities of functional logic from the perspective of the consumer (caller), thereby facilitating code quality

  • Testing is the means, not the end. The primary purpose of testing is not to prove that the code is correct, but to help detect errors, including low-level ones

  • Test fast. Run fast, write fast

  • Keep the test code simple

  • Failed tests are not ignored. Once the team starts to accept one test build failure, they gradually get used to two, three, four, or more failures. In this case, the test set no longer works

Note that:

  • The core purpose of TDD must not be misunderstood!

  • Testing is not about coverage and accuracy

  • But as an example, telling the developer what code to write

  • Red light (incomplete code, test hanging) -> Green light (write code, tests pass) -> Refactor (optimize code and ensure tests pass)

The process of TDD is:

  1. Demand analysis, thinking implementation. Consider how to “use” the product code, whether it is an instance method or a class method, whether parameters are passed from constructors or method calls, method names, return values, and so on. You are actually doing design, and design is reflected in code. The test is red

  2. Implement code to “green light” tests

  3. Refactor, then repeat the test

  4. In the end, all the requirements are met:

    • Each concept is clearly articulated

    • There is no self-repetition in the code

    • There is nothing superfluous

    • Pass the test

BDD (behaviors – driven development) :

Behavior-driven development (BDD), which focuses on gaining an understanding of the expected software behavior through discussions with stakeholders (in short, customers), focuses on communication

The BDD process is:

  1. Define specific and measurable goals from a business perspective

  2. Find a way to achieve the functions that are most important to the business for the set goals

  3. Then describe the specific actions as a story. Its descriptive methods are based on common words with unerring expressiveness and consistent meaning. For example, expect, should, assert

  4. Find the appropriate language and method to implement the behavior

  5. The tester verifies that the product runs according to the expected behavior. To the greatest extent possible to deliver the product in line with user expectations, to avoid the problem of inconsistent expression

4. Front-end test workflow for Mocha/Karma+Travis

From what unit testing is to the methodology of unit testing. So how do you unit test with a common framework? What is the tool environment for unit testing? What’s a real example of a unit test?

A quick introduction to Mocha, Karma, and Travis.ci should begin

**Mocha: **Mocha is a feature-rich front-end testing framework. A “test framework” is a tool for running tests. It allows you to add tests to your JavaScript applications to ensure the quality of your code. Mocha can run in either a Node.js environment or a browser environment. For more information, go to the official website. Its official introduction is:

Mocha is a feature-rich JavaScript test framework running on Node.js and in the browser, making asynchronous testing simple and fun. Mocha tests run serially, allowing for flexible and accurate reporting, while mapping uncaught exceptions to the correct test cases. Hosted on GitHub.

**Karma: ** A Node.js based JavaScript Test Runner management tool. The tool can be used to test all major Web browsers, is integrated into CI (Continuous Integration) tools, and can be used with other code editors. A powerful feature of the test tool is that it can monitor file changes and then execute the test itself, displaying the test results via console.log. A powerful feature of Karma is that it can monitor the transformation of a set of files and immediately start testing saved files without the user having to leave the text editor. Test results are usually displayed on the command line, not in the code editor. This makes Karma usable with almost any JS editor.

Travis.CI: Provides Continuous Integration (CI) services. It is tied to projects on Github and automatically grabs new code whenever it comes in. Then, provide a running environment, perform tests, complete the build, and deploy to the server.

Continuous integration is the process of automatically running builds and tests as soon as the code changes, and reporting back the results. After ensuring that it meets expectations, “integrate” the new code into the trunk.

The benefit of continuous integration is that you can see the results running every time you make small changes to your code, so you can accumulate small changes over time, rather than merging a large chunk of code at the end of the development cycle.

For Travis.CI, I suggest you go to the personal websites of Ruan dada and Liao Dada. Both teachers speak much more clearly than I can write here.

Assertions library

After the introduction of the basic tool framework, I believe that those who know a little bit about testing know that to do unit tests, you need to write test scripts, and then the test scripts need to use the assertion library.” Assert using that code to test the correctness of this code and to verify and expose errors in this code. “So for front-end unit tests, there are the following libraries of common assertions:

Here’s a code example:

expect(add(1, 1)).to.be.equal(2);

This is an assertion code.

The so-called “assertion” is to determine whether the actual execution result of the source code is consistent with the expected result, and to throw an error if not. The implication of the above assertion is that the call to add(1, 1) should result in 2. All test cases (IT blocks) should contain one or more assertions. It is the key to writing test cases. Assertions are implemented by an assertion library, which Mocha does not have, so you must introduce it first.

Examples of code to introduce an assertion library:

var expect = require(‘chai’).expect;

There are many kinds of assertion libraries, and Mocha doesn’t limit which one you can use. It allows you to use any assertion library you want. The assertion library introduced by the above code is CHAI and specifies the Expect assertion style to use it. Here are some common assertion libraries:

  • This is the assertion module in Node.js.
  • should.js
  • expect.js
  • chai.js

This section describes the apis commonly used in Node Assert

  • assert(value[, message])
  • assert.ok(value[, message])
  • assert.equal(actual, expect[, message])
  • assert.notEqual(actual, expected[, message])
  • assert.strictEqual(actual, expect[, message])
  • assert.notStrictEqual(actial, expected[, message])
  • assert.deepEqual(actual, expect[, message])
  • assert.notDeepEqual(actual, expected[, message])
  • assert.deepStrictEqual(actual, expect[, message])
  • assert.notDeepStrictEqual(actual, expected[, message])
  • assert.throws(block[, error][, message])
  • assert.doesNotThrow(block[, error][, message])

assert(value[, message])

Asserts whether the value of value is true, where == is used instead of ===. Message is an optional assertion description.

const assert = require('assert');
assert(true);
Copy the code

assert.ok(value[, message])

Use the same assert(value[, message]) method.

assert.equal(actual, expect[, message])

The expected actual and expect values are equal. The actual and Expect that equal uses to compare are data of the base types (string, number, BoolEarn, null, undefined). The comparison uses == instead of ===.

it('assert.equal', () => { assert.equal(null, false, 'null compare with false'); Assert. Equal (null, true, 'null compare with true'); Assert. Equal (undefined, false, 'undefined compare with false'); Assert. Equal (undefined, true, 'undefined compare with true'); Assert. Equal ('', false, '"" compare with false'); / / normal})Copy the code

notEqual(actual, expected[, message])

Use the same as assert.equal(actual, expect[, message]) except that it inverts the expected result (that is, does not equal).

assert.strictEqual(actual, expect[, message])

Use the same as assert.equal(actual, expect[, message]), but internal comparisons use === instead of ==.

assert.notStrictEqual(actial, expected[, message])

Used in the same way as assert.strictequal (actual, expect[, message]) except that the expected result is inverted (that is, not strictly equal).

it('assert.strictEqual', () => { assert.strictEqual('', false); / / error})Copy the code

assert.deepEqual(actual, expect[, message])

The deepEqual method is used to compare two objects. The process of comparing two objects is to see if the key and value values are the same, using == instead of ===.

it('assert.deepEqual', () => {
  const a = { v: 'value' };
  const b = { v: 'value' };
  assert.deepEqual(a, b);
})
Copy the code

assert.notDeepEqual(actual, expected[, message])

It is used in the same way as assert.deepequal (actual, expect[, message]) except that it inverts the expected result.

assert.deepStrictEqual(actual, expect[, message])

Use the same as assert.deepequal (actual, expect[, message]) but use === instead of == for internal comparisons.

assert.notDeepStrictEqual(actual, expected[, message])

Use the same as assert.deepStrictEqual(actual, expect[, message]).

assert.throws(block[, error][, message])

Error assertion and catch. Assertions specify that a block of code must report an error or throw an error. If the code runs without error, it will assert failure, assert exception.

it('throws', () => {
  var fun = function() {
    xxx
  };
  assert.throws(fun, 'fun error');
})
Copy the code

assert.doesNotThrow(block[, error][, message])

Throws Error assertion is similar to capture, except that it is opposite to the expected result of the throws. An assertion specifies that a code block must run without reporting or throwing an error. If the code runs error will assert failure, assert exception.

it('throws', () => {
  var fun = function() {
    xxx
  };
  assert.doesNotThrow(fun, 'fun error');
})
Copy the code

After the introduction of the corresponding tools, I’ll talk about my personal experience with the use of Mocha, Karma, and Travis.

Mocha

  • Installation of mocha

    npm install mocha -g

Of course, it is also possible to install a partial installation in the project instead of globally

npm install mocha --save
Copy the code
  • Create a test file, test.js

    var assert = require(‘assert’)

    describe(‘Array’, function() { describe(‘#indexOf()’, function() { it(‘should return -1 when the value is not present’, function() { assert.equal(-1, [1, 2, 3].indexOf(-1)) }) }) })

This file is simply an indexOf() method that tests the Array. The assertion library I’m using here is the API in the Assert module provided by Node. Here it is asserted that -1 is equal to the value returned by the array [1, 2, 3] performing indexOf(-1), and that no error will be reported if the test passes, and an error will be reported if there is an error.

Let’s run the file mocha test.js using the global installation of Mocha. Here is the result

Basic test case instances

const assert = require('assert'); Describe (' 1 + 2 = 1 ', function() {describe(' 1 + 2 = 1 ', function() {// describe(' 1 + 2 = 1 ', function() { Assert.equal (result, 3); }); });Copy the code

A Mocha test case consists of the following parts:

  1. Describe Defined Test Suite
  2. Test Case defined by IT
  3. The test code
  4. Assert that part

Note: Each test file can have multiple test suites and test cases. Mocha runs not only in the Node environment, but also in the browser environment; It is also possible to install Mocha globally using NPM I mocha -g and then run the test case from the command line.

Here’s a little more detail on how to write the test script

Mocha’s role is to run test scripts, which you must first learn to write. A “test script” is a script used to test the source code. Here is the code for the addition module add.js.

// add.js
function add(x, y) {
  return x + y;
}

module.exports = add;
Copy the code

To test that the addition module is correct, write a test script. Typically, a test script has the same name as the source script to be tested, but with a suffix of.test.js (for tests) or.spec.js (for specifications). For example, the test script name for add.js is add.test.js.

// add.test.js var add = require('./add.js'); var expect = require('chai').expect; Describe ('1 + 1 ', function() {it('1 + 1 should equal 2', function() {expect(add(1, 1)).to.be.equal(2); }); });Copy the code

The above code, the test script, can be executed independently. The test script should include one or more Describe blocks, and each Describe block should include one or more IT blocks.

A describe block is called a test suite and represents a set of related tests. It is a function with the first argument being the name of the test suite (” test of the addition function “) and the second argument being an actual function that is executed.

An IT block, called a test case, represents a single test and is the smallest unit of testing. It is also a function, with the first argument being the name of the test case (“1 plus 1 should equal 2”) and the second argument being an actual function that is executed.

Expect’s assertions have the advantage of being close to natural language, and here are some examples.

// Expect (4 + 5).to.be. Equal (9); expect(4 + 5).to.be.not.equal(10); expect(foo).to.be.deep.equal({ bar: 'baz' }); // If Boolean = true expect('everthing').to.be.ok; expect(false).to.not.be.ok; // typeof expect('test').to.be.a('string'); expect({ foo: 'bar' }).to.be.an('object'); expect(foo).to.be.an.instanceof(Foo); // include expect([1, 2, 3]).to.include(2); expect('foobar').to.contain('foo'); expect({ foo: 'bar', hello: 'universe' }).to.include.keys('foo'); // empty expect([]).to.be.empty; expect('').to.be.empty; expect({}).to.be.empty; // match expect('foobar').to.match(/^foo/);Copy the code

Basically, Expect’s assertions are written the same way. The header is an Expect method, and the tail is an assertion method, such as equal, a/an, OK, match, and so on. A to or to.be connection is used between the two. If the Expect assertion is not true, an error is thrown. In fact, as long as no error is thrown, the test case passes.

It ('1 + 1 = 2', function() {});Copy the code

The above test case, which has no code inside, still passes because no error is thrown.

Karma

Based on some commonly used modules for karma testing

Module is installed

NPM install karma-cli -g NPM install karma mocha karma-mocha --save-dev NPM install karma-firefox- Launcher --save-dev NPM install karma-chrome- Launcher --save-devCopy the code

configuration

The main focus here is on the configuration of karma. Conf.js. If you want to use karma and mocha, use NPM install karma-cli -g to install karma-cli globally. Configuration details

Two fields to note:

  • SingleRun: If true, the browser will automatically exit and close the browser window after running the test. The value of singleRun can be dynamically assigned to more runtime environments, by adding the NODE_ENV variable to the boot command.

  • Browsers: browser configuration (which can be configured with multiple browsers). If the browser cannot be started, configure the browser. If the browser fails to start, you may need to set it to the –no-sandbox mode.

    { “browsers”: [“Chrome”, “ChromeHeadless”, “ChromeHeadlessNoSandbox”], “customLaunchers”: { “ChromeHeadlessNoSandbox”: { “base”: “ChromeHeadless”, “flags”: [“–no-sandbox”] } } }

or

{
  "browsers": ["Chrome_travis_ci"],
  "customLaunchers": {
    "Chrome_travis_ci": {
      "base": "Chrome",
      "flags": ["--no-sandbox"]
    }
  }
}
Copy the code

Github project to access Travis.CI for integration automation test steps

  • Create and complete a testable project on Github. Completion here refers to the need to complete basic project functionality, as well as test case code.

  • Configure travis-CI to recognize the read configuration file, so that travis-CI will know some of the configuration during the test when it comes in.

  • Github and Travis – Ci are sites, in other words, if two things can get through. You need to be logged in to Travis – Ci and authorized to access your Github project and set up your project.

  • After completion, you can run the written test code according to your own needs, and you can set up regular tasks to run the test.

Project creation, improvement of project functionality, and test code.

  • Project requirement: Implement a summation method
  • Test: PassmochaTo test the completed summation method.

The following is the project structure. After the project is created, install the mocha module via NPM I mocha -d. Then run NPM test locally to see if it passes. If the test passes, we can move on to the next step.

Create the travis-CI test profile

Create the travis-ci configuration file.travis.yml with the file contents. More information about the configuration file can be found on the Travis website

Language: node_js node_js: - "node" - "8.9.4"Copy the code

So far, the process of project development and test code writing is basically completed, and the next step is to access Travis – CI testing.

Access to the Travis – ci

Use GitHub to log in to the official website of Travis – Ci at www.travis-ci.org/

Find the project you just created on GitHub that needs to be tested and start testing

View the testing process to detect problems in a timely manner.

Check whether the test status passes the test. If the test status does not pass the test, rectify the fault in time and modify the fault repeatedly. If the test passes, you can add a passed flag to the project document.

conclusion

At the beginning of this year, I had an interview for a company. The company is a start-up company whose boss is Mr. Lin Shiding, former chief architect of Baidu. The company is called Aiyun School, which mainly provides data services for basic education and has its own platform and products. One of the most impressive questions the interviewer asked me that day was: What was the framework and workflow you used for unit testing when you were doing the front end? I was so confused, honestly, that I didn’t even know what a unit test was in the front end. What to test? What tools do you use? Speechless, I said I hadn’t used it before and hadn’t done any front-end testing. At that time, the interviewer’s face was obviously a little disappointed, but eventually the company hired me. The reason I said this experience is to convey that front-end development is no longer the early days of cutting graphics, special effects and visual performance. The front end of the development engineer is more of you now as a product of the entire project development team (is also a matter of fact) theoretically from the user a recent post, should not only limited to realize the function of the pure traditional front-end, more need to understand the needs of customers on the basis of the plan as a whole based coupling, good front-end and back-end and front-end function accurately. Job experience, according to their own interview here today when IT comes to the front of the unit test content, personally think that in certain companies project, may not be necessary, but as one of the fastest growing IT field, front-end engineers to master the front unit test time can be to demand more and more hard in the future, rather than always stay in dispensable understanding category, Because it’s all about trends in front end development.

At the same time, however, in my personal opinion, at least for the time being, I’m sticking with the development process as a supplement to the main test. Unit test guided development process, such as TDD, is not currently recommended. Personally, I think this is a very innovative methodology, and it is not impossible at present. In my opinion, the scope of feasibility is not wide enough, and the requirements for feasibility are very strict. So relative to the TDD, test the leading development, for the preparation of advanced front-end developer, personal suggestion, more understand some will use the new trends and technologies is necessary, but as a technical person should learn in new, cutting-edge technology at the same time, do not lose yourself blindly pursue new technology, more important is to hone the present mainstream skills. Compared with the development process dominated by unit tests in the future, it is better to improve the basic development process in the current time node, such as making your JS code more focused on the realization of modularity and functionalization. At the same time, unit tests will be more efficient, and the role of current unit tests in front-end engineering will be really played.