Recently,
I was responsible for a NodeJS-based application. In this process, I had to
learn about many new things, one of which was testing. At the start, I was not
able to write much code, much less test it. At that time, my testing coverage
rate was 0%. After some time, and especially when I saw that the test coverage
rate for excellent libraries on npm was 100%, I made
a determined effort to learn NodeJS testing. Currently, the application's test
coverage rate is 90%+. This is how I went from 0 to 90. I still have a long way
to go to achieve the remaining 10% and I will discuss this in the future.
Preface
For developers, there is no doubt about the importance of testing. You often hear, "No testing, no release", or "No testing, no reconstruction". In practice, however, there is always some sort of testing problems. For example:
A good test
If you talk to a thousand people, you will hear about at least two thousand testing concepts and methods. This makes it hard to define what is a good tes
t. As my team has taken on more responsibility for testing, we have developed a simple philosophy. It includes the following principles:
The most important measure of a good test is how much code is tested (its coverage). 75% is the minimum standard. This standard is basically feasible for Java, but not suitable for NodeJS. JavaScript is a weakly typed dynamic language, with no compilation stage. This means that many errors can only be discovered when the application is run. Therefore, we need a higher coverage rate. It would be best to have 100%, but at present, my personal standard is 90%+.
Each test case should be able to be executed repeatedly in any environment and the same results should be produced. Only in this way can you really trust your test and use it to find actual bugs. This is also the minimum requirement for integrated testing.
A test case tests only one aspect of the code, such as one branch, and is not highly reliant on certain environments or conditions.
Whether for a single test case or integrated testing, you must ensure that the test can be executed sufficiently quickly.
What to test
The question of what to test is mainly answered based on actual requirements, the business, costs, the language, and other factors. However, there are some commonalities. The Unit Testing Principles This link is in Chinese provide reference principles, but I will not discuss them further here.
How to test
This is a very broad question. In this article, I will only discuss NodeJS testing tools and methods based on my own opinions.
Overview
Frameworks
There are many NodeJS testing frameworks. Currently, the most widely used is Mocha. In this text, I will give a detailed description of Mocha and brief several other frameworks. In this article, all the examples are based on Mocha, unless otherwise specified.
Mocha
A simple, flexible, fun JavaScript test framework for node.js and the browser.
Mocha is a JavaScript testing framework with a wide array of functions. It can run on Node.js or a browser and supports BDD and TDD testing.
Quick Start
Installation
npm install -g mocha
Write a simple test case
var assert = require('chai').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(5));
assert.equal(-1, [1,2,3].indexOf(0));
});
});
});
Run
$ mocha
Output results:
1 test complete (1ms)
Use
Assertions
Mocha allows you to use any assertion library you want, including:
Hooks
Mocha provides hooks, such as before(), after(), beforeEach(), and afterEach(). These are used to set pre-test conditions and clean the test, as shown in the example below:
Dedicated tests or skip testsDedicated tests allow testing only specified test sets or cases. For a dedicated test, you just have to add .only() in front of the test set or case, as shown below:
Skip tests are similar to junit's @Ignore. They are used to skip or ignore a specified test set or case. To do this, just add .skip() in front of the test set or case, as shown below:describe('Array', function(){
describe.skip('#indexOf()', function(){
...
})
})
Editor pluginsBesides using the command line provided by Mocha, you can use editor plugins This link is bad to run test cases. Currently, the following plugins are supported:
Let's use JetBrains as an example. JetBrains provides NodeJS for its IDE kits (IntelliJ IDEA, WebStorm, etc.). It can directly run or debug Mocha test cases. Basic procedure:
Run or debug the test. This plugin allows you to run or debug directories, files, test sets, and test cases. Run the test as shown below:Other
Below, I will list several other NodeJS-based test frameworks or tools. They can be used to test JavaScript code in NodeJS or your browser. I will not discuss them in detail, so to learn more, refer to the official documentation.
Jasmine
A
Behavior Driven Development JavaScript testing framework
Jasmine
is a behavior-driven development framework for testing JavaScript code. It does
not depend on any other JavaScript frameworks. It does not require a DOM. And
it has a clean, obvious syntax so that you can easily write tests.
To learn more, see the official documentation.
Karma Runner
To
bring a productive testing environment to developers
The
main goal for Karma is to bring a productive testing environment to developers.
The environment being one where they don't have to set up loads of
configurations, but rather a place where developers can just write the code and
get instant feedback from their tests.
To
learn more, see the official documentation.
Tools
Mocha provides a basic framework for testing, but in certain scenarios, you may need to use other auxiliary tools as well. Below, I provide a list of common tools.
SuperTest
SuperTest provides high-level abstraction for HTTP testing. This substantially simplifies HTTP-based testing.
The motivation with this module is to provide a high-level abstraction for testing HTTP, while still allowing you to drop down to the lower-level API provided by super-agent.
Installation
$ npm install supertest --save-dev
Usage examplevar request = require('supertest');
describe('GET /user', function() {
it('respond with json', function(done) {
request(app)
.get('/user')
.set('Accept', 'application/json')
.expect('Content-Type', /json/)
.expect(200, done);
});
});
request(app)
.post('/')
.field('name', 'my awesome avatar')
.attach('avatar', 'test/fixtures/homeboy.jpg')
// ..
describe('GET /user', function() {
it('user.name should be an case-insensitive match for "tobi"', function(done) {
request(app)
.get('/user')
.set('Accept', 'application/json')
.expect(function(res) {
res.body.id = 'some fixed id';
res.body.name = res.body.name.toUpperCase();
})
.expect(200, {
id: 'some fixed id',
name: 'TOBI'
}, done);
});
});
To learn more, see the documentation.
Code coverage is a measurement used in software testing. It describes the proportion and extent of the program's source code that is tested. This proportion is the code coverage rate: This indicator has four dimensions:
Istanbul is the most popular JavaScript code coverage tool.
Quick Start
Installation
$ npm install -g istanbul
RunSimplest method:
$ cd /path/to/your/source/root
$ istanbul cover test.js
Output operation results:
..
test/app/util/result.test.js
should static create
should be success
should be static success
should be error
should be static error
299 passing (13s)
[mochawesome] Report saved to /opt/source/node_modules/.mochawesome-reports/index.html
=============================== Coverage summary ===============================
Statements : 92.9% ( 1505/1620 )
Branches : 85.42% ( 410/480 )
Functions : 94.33% ( 133/141 )
Lines : 93.01% ( 1504/1617 )
================================================================================
Done
This
command will also generate a coverage subdirectory, in which the coverage.json file contains the original
coverage data. The file coverage/lcov-report is a coverage report that
you can open in your browser, as shown below:Istanbul
Modes
Two common testing modes are TDD and BDD.
TDD is a core practice and technique used in agile development. It is also a design methodology. The principles of TDD are as follow: Prior to developing function code, write unit test case code. This test code will determine what product code needs to be written. The basic idea behind TDD is that testing can be used to drive the entire development process. However, TDD does not just involve testing work. It also involves needs analysis, design, and quality control quantization. The overall process is as follows:
We will use a small factorial program as an example. First, write the test case, as shown below. Now, when you run it, it will certainly report an error. This is because the program to test has not been written.var assert = require('assert'),
factorial = require('../index');
suite('Test', function (){
suite('#factorial()', function (){
test('equals 1 for sets of zero length', function (){
assert.equal(1, factorial(0));
});
test('equals 1 for sets of length one', function (){
assert.equal(1, factorial(1));
});
test('equals 2 for sets of length two', function (){
assert.equal(2, factorial(2));
});
test('equals 6 for sets of length three', function (){
assert.equal(6, factorial(3));
});
});
});
Start to write the factorial logic, as shown below.
module.exports = function (n) {
if (n < 0) return NaN;
if (n === 0) return 1;
return n * factorial(n - 1);
};
Now,
run the test case and see if the program passes the test. If the program passes
all the tests, this indicates that development is complete. If it does not
passes all the test cases, repair or modify the tested logic until the program
passes the all the tests.BDD (Behavior Driven Development)
BDD is an agile software development technique. It encourages developers, QA staff, non-technical staff, and commercial participants to collaborate in software projects. This process begins from an analysis of user needs and stresses system behaviors. Its most significant characteristic is that written descriptions of behaviors or specifications are used to drive software development. In appearance, behavior and specification descriptions are very similar to tests. However, there are significant differences.
We will continue using the factorial introduced above to demonstrate BDD mode testing:
From the example above, we can see that the biggest difference between the BDD and TDD test cases is wording. The BDD test cases read like normal sentences. Therefore, BDD test cases can be used as tools to facilitate the collaboration of developers, QA staff, non-technical staff, and commercial participants. If developers can more fluently read test cases, they will naturally be able to write better and more comprehensive test cases.TDD vs BDD
In essence and purpose, TDD and BDD are the same. They differ only in implementation and different discussions are arranged in order to improve the overall agile development system. TDD iteratively repeats verification in order to ensure agile development. However, it does not clearly specify how to produce test cases based on the design and ensures the quality of the test cases. BDD, on the other hand, advocates the use of clear and natural language to describe system behaviors. This exactly offsets the accuracy of test cases (system behaviors).
Basically all NodeJS-based libraries and applications choose BDD, though I do not understand exactly why.
Assertions
Currently there are several popular assertion libraries:
Except slight differences in style, these libraries are more or less the same. You can select the library that best suits your preferences or the needs of your application.
We need a conclusion to this article. I will write one below but it needs to be checked with a developer.
By running my NodeJS testing through these testing frame works I was able to get a test coverage of 90%+. For test coverage exceeding 90% please lookout for my future article in the near future.
Cloud Computing, Big Data and VR are Transforming the Real Estate Industry
2,599 posts | 762 followers
FollowAlibaba Clouder - April 12, 2019
Alibaba Clouder - October 12, 2019
Alibaba Clouder - January 27, 2020
Alibaba Clouder - December 30, 2020
Alibaba Clouder - November 1, 2018
Alibaba Clouder - February 14, 2020
2,599 posts | 762 followers
FollowProvides comprehensive quality assurance for the release of your apps.
Learn MorePenetration Test is a service that simulates full-scale, in-depth attacks to test your system security.
Learn MoreMore Posts by Alibaba Clouder