Laziness is an important factor in the development of human science and technology. We are leaving the slash-and-burn era precisely because people are constantly increasing their efficiency by inventing tools and streamlines manual processes that allow people to focus on their expertise and leave the rest to machines.

Meanwhile, in the field of front end, we have also gone from the barbarous era to the prosperity and development of today. All kinds of frameworks have blossomed. The front end is no longer confined to static pages, but closer to the development of traditional applications in form, and the complexity of functions has increased exponentially. If I had to re-test the code every time, would I still be able to leave work on time?

Before so we need to develop, will determine the rules of the framework/library, through the rule to write our test cases, so after we develop, run the test case again, let the machine to replace manual to our test code, you can know our framework in various environments and use cases will be no error, but no longer need to verify one by one project.


Of course, I’m not the only one who had this idea. The big boys had this idea for a long time, and that’s where the testing framework came in. As far as I know, Mocha, Jasmine and so on are the popular unit testing frameworks in the front-end field.

Without further ado, let’s take a look at how to get started with testing, and here we use Mocha as an example. The first step is to install Mocha in your project

npm install mocha --save-dev

Create the Test folder in the root directory of your project and create the file index.js. Now you’ll test Array.prototype.IndexOf

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(4))
    })
  })
})

Execute it on the command line

mocha

If you see this result, congratulations, your code has passed the test (funny)

Array
    #indexOf()
      ✓ should return -1 when the value is not present


  1 passing (13ms)

This is a simple example, and many of you may still be confused. Say yes to the testing framework. What the heck did you introduce a assert? This is the predicate module built into NodeJS.

What is assertion?

In programming, an assertion is a first-order logic that is placed in a program (such as a logical assertion that the result is true or false) to indicate and validate the expected result of the program developer — that the assertion should be true when the program runs to the assertion position. If the assertion is not true, the program aborts with an error message. “– Wikipedia

Test framework of duty, just help you to project in all kinds of testing for a program, easy to split test to arrange, and to make it easier to add some description to the human eye in the test, in fact, the input parameters to the function, what result can pass the test, the final output is the need for us to “tell” the test framework. And assertions, which exactly satisfy the semantics of our behavior, are also the most natural.

In general, using the default assertion module is sufficient for many situations, but if you are not comfortable with this syntax, you can also choose to use other assertion libraries in the testing framework, such as should.js, which I won’t go into too much here.

How do I test asynchronous code

You can do done in the callback

var assert = require('assert')

describe('Array', function() {
  describe('#indexOf()', function() {
    it('should return -1 when the value is not present', function(done) {
      setTimeout(function() {
        var value = 1;
        if (value) done(assert.equal(-1, [1, 2, 3].indexOf(4)))
        else done()
      }, 30)
    })
  })
})

promise

it('should xxx', function(done) {
  return new Promise(function(resolve, reject){}).then(done)
})

Support the async await

it('should return -1 when the value is not present', async function(done) {
  let a = await func();
  if (a) done()
  else done(new Error("xxx"))
})

It is important to note that the arrow function is not recommended when using the Mocha API, because you will not be able to get the current context, which has built-in APIs such as timeOut, etc. Please refer to the documentation for details, but I will not expand on this here.


The test environment

It’s time to run the browser!

Yes, up until now, we’ve been executing code in NodeJS. As for how different the browser execution environment is, it’s self-evident that simply running tests on Node is not universal or reliable. We need to run them all in the browser environment.

What? Do you want to open the console to paste code to execute? To save you from endless overtime testing, it’s time to recommend you switch to Karma.

Karma is a test execution management tool that allows you to configure the browser environment that you need to test in, as well as a series of pre-test preparations. It also provides access to report generation of test coverage when needed.

To make it easier for students to configure karma, I use the assertion library should.js instead

npm install should --save-dev

The assertion notation is replaced as follows

/ / assert. Equal ([1, 2, 3]. IndexOf (4), 1) [1, 2, 3] indexOf (4) should. Equal (1)

First we need to install karma

npm install karma-cli -g
npm install karma --save-dev

Go into the project and initialize karma

karma init

You will then receive a barrage of inquiries

Which testing framework do you want to use ?
Press tab to list possible options. Enter to move to the next question.
> mocha

Do you want to use Require.js ?
This will add Require.js plugin.
Press tab to list possible options. Enter to move to the next question.
> no

Do you want to capture any browsers automatically ?
Press tab to list possible options. Enter empty string to move to the next question.
> Chrome
>

What is the location of your source and test files ?
You can use glob patterns, eg. "js/*.js" or "test/**/*Spec.js".
Enter empty string to move to the next question.
> node_modules/should/should.js
> test/*.js

Should any of the files included by the previous patterns be excluded ?
You can use glob patterns, eg. "**/*.swp".
Enter empty string to move to the next question.
> 

Do you want Karma to watch all the files and run the tests on change ?
Press tab to list possible options.
> yes

Once the configuration is complete, there will be a karma.conf.js file in the root of the project. I would love to expand it, but if I keep going, I will probably get to the end of the day, so if you want to learn more about what each configuration item does, check out the karma documentation

// Karma configuration
// Generated on Fri Aug 04 2017 20:53:38 GMT+0800 (CST)

module.exports = function(config) {
  let configuration = {

    // base path that will be used to resolve all patterns (eg. files, exclude)
    basePath: '',


    // frameworks to use
    // available frameworks: https://npmjs.org/browse/keyword/karma-adapter
    frameworks: ['mocha'],


    // list of files / patterns to load in the browser
    files: [
      'node_modules/should/should.js',
      'js/*.js',
      'quz/*.js',
      'test/*.js'
    ],


    // list of files to exclude
    exclude: [
    ],


    // preprocess matching files before serving them to the browser
    // available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor
    preprocessors: {
      'quz/*.js': 'coverage',
      'js/*.js': 'coverage'
    },


    // test results reporter to use
    // possible values: 'dots', 'progress'
    // available reporters: https://npmjs.org/browse/keyword/karma-reporter
    reporters: ['progress', 'coverage', 'coveralls'],
    coverageReporter: {
      type : 'lcov',
      dir : 'coverage/'
    },

    // web server port
    port: 9876,
    plugins: [
      'karma-mocha',
      'karma-chrome-launcher',
      'karma-firefox-launcher',
      'karma-coverage',
      'karma-coveralls'
    ],

    // enable / disable colors in the output (reporters and logs)
    colors: true,


    // level of logging
    // possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG
    logLevel: config.LOG_INFO,


    // enable / disable watching file and executing tests whenever any file changes
    autoWatch: true,


    // start these browsers
    // available browser launchers: https://npmjs.org/browse/keyword/karma-launcher
    browsers: ['ChromeHeadless', 'FirefoxHeadless'],

    customLaunchers: {
      Chrome_travis_ci: {
        base: "ChromeHeadless",
        flags: ["--no-sandbox"]
      },
      FirefoxHeadless: { 
        base: "Firefox", 
        flags: ["-headless"]
      }
    },

    // Continuous Integration mode
    // if true, Karma captures browsers, runs the tests and exits
    singleRun: process.env.TRAVIS,

    // Concurrency level
    // how many browser should be started simultaneous
    concurrency: Infinity
  }
  if (process.env.TRAVIS) {
    configuration.browsers = ["Chrome_travis_ci", 'FirefoxHeadless'];
  }
  config.set(configuration)
}

Now let’s run a run

karma start

Your black window will have a log like this

02 02 2018 18:10:26.181:WARN [arma]: No captured browser, open http://localhost:9876/ 02 02 2018 18:10:26.193:INFO [karma]: Karma v2.0.0 Server Started at http://0.0.0.0:9876/ 02 02 2018 18:10:26.194:INFO [Launcher]: Launcher Launching Browser Chrome with unlimited concurrency 02 2018 18:10:26.199:INFO [Launcher]: Launcher Launcher INFO [Chrome 63.0.3239 (Mac OS X 10.13.2)]: Connected on Socket LV0DMSCNBH5JC2NGAAAA withID 45333497 Chrome 63.0.3239 (Mac OS X 10.13.2): Connected on Socket LV0DMSCNBH5JC2NGAAAA withID 45333497 Chrome 63.0.3239 (Mac OS X 10.13.2): Executed 1 of 1 SUCCESS (0.003 SECs / 0.001SECs)

Your computer will automatically open the browser and stay on the desktop. As soon as Karma notices any changes in your code, it will run the test case again, leaving the testing process behind and focusing on the code. Perfect!

Finished? No! You can be even lazier and plug your current testing process into CI as a pre-deployment link, which is beyond the scope of this article.

Long way, this article is limited to everyone as the beginning of the understanding of the test, in fact, hidden a lot of details, the real environment, in fact, encountered the problem is much more complex than this, but if you understand the principle of testing, I believe that smart you encounter no matter how difficult the problem can also think of a solution.

The sea is boundless, mutual encouragement.