Guide Development Guide

A better life starts with testing

A programmer who doesn't write automated test cases is not a good test engineer. We encourage all projects to establish complete automated test cases from the very beginning. As the project develops, the initial investment will be returned hundreds of times.

Let's continue the example from the previous section and look at how to write a test case using fibjs.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
const http = require('http'); const path = require('path'); var hello_server = { '/:name(fibjs.*)': (req, name) => { req.response.write('hello, ' + name + '. I love you.'); }, '/:name': (req, name) => { req.response.write('hello, ' + name); } }; var root_server = { '/hello': hello_server, '/bonjour': hello_server, '*': http.fileHandler(path.join(__dirname, 'web')) }; var svr = new http.Server(8080, root_server); svr.start();

an empty test frame

Let’s start with a basic testing framework:

1 2 3 4 5 6 7 8 9 10
var test = require('test'); test.setup(); describe('hello, test', () => { it('a empty test', () => { }); }); test.run();

After saving it as test.js, and executing it on the command line fibjs test.js, you will see the following output, and a basic test framework is written.

1 2 3 4
hello, test √ a empty test √ 1 tests completed (0ms)

Start testing the server

Because we need to test the http server, we need to start the server first. The test case will make a request to the server and then test the request result to determine whether the server meets the requirements:

1 2 3 4 5 6 7 8 9 10 11 12 13 14
var test = require('test'); test.setup(); var http = require('http'); describe('hello, test', () => { it('hello, fibjs', () => { var r = http.get('http://127.0.0.1:8080/hello/fibjs'); assert.equal(r.statusCode, 200); assert.equal(r.data.toString(), 'hello, fibjs. I love you.'); }); }); test.run();

In this code, we determine whether the server logic is normal by verifying whether the result of http.get is the result we expect. Following this example, we can quickly complete a set of tests and optimize the code at the same time:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
var test = require('test'); test.setup(); var http = require('http'); function test_get(url, rep) { var r = http.get('http://127.0.0.1:8080' + url); assert.equal(r.statusCode, 200); assert.equal(r.data.toString(), rep); } describe('hello, test', () => { it('hello, fibjs', () => { test_get('/hello/fibjs', 'hello, fibjs. I love you.'); }); it('hello, fibjs*', () => { test_get('/hello/fibjs-great', 'hello, fibjs-great. I love you.'); }); it('hello, JavaScript', () => { test_get('/hello/JavaScript', 'hello, JavaScript'); }); it('hello, v8', () => { test_get('/hello/v8', 'hello, v8'); }); }); test.run();

Use case group management

Next, let's add the test of bonjour. Although bonjour and hello are the same set of services, because the path has changed, we also need to verify the correctness of the service. This time, in order to better manage the use cases, we performed the test cases Grouping, at the same time, because the test contents of hello and bonjour are the same, we optimized the code again and used the same set of code to test the two sets of services:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
var test = require('test'); test.setup(); var http = require('http'); function test_get(url, rep) { var r = http.get('http://127.0.0.1:8080' + url); assert.equal(r.statusCode, 200); assert.equal(r.data.toString(), rep); } describe('hello, test', () => { function test_hello(hello) { describe(hello + ' test', () => { it('fibjs', () => { test_get('/' + hello + '/fibjs', 'hello, fibjs. I love you.'); }); it('fibjs*', () => { test_get('/' + hello + '/fibjs-great', 'hello, fibjs-great. I love you.'); }); it('JavaScript', () => { test_get('/' + hello + '/JavaScript', 'hello, JavaScript'); }); it('v8', () => { test_get('/' + hello + '/v8', 'hello, v8'); }); }); } test_hello('hello'); test_hello('bonjour'); }); test.run();

By grouping use cases, we can view the test results more clearly, and we can also easily skip and test a group of use cases separately to speed up development and testing. Here are the results from this round of testing:

1 2 3 4 5 6 7 8 9 10 11 12 13
hello, test hello test √ fibjs √ fibjs* √ JavaScript √ v8 bonjour test √ fibjs √ fibjs* √ JavaScript √ v8 √ 8 tests completed (3ms)

According to our server design, we also have a set of static file services. Following the above example, I believe you can quickly write this part of the test cases.

One click test

After the above introduction, we can quickly establish test cases. But in order to use this test script, the server must be started first, which is very inconvenient. We hope that running test.jscan complete the test directly. We can achieve this with the following code:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
var test = require('test'); test.setup(); var http = require('http'); var coroutine = require('coroutine'); coroutine.start(() => { run('./main.js'); }); coroutine.sleep(100); function test_get(url, rep) { var r = http.get('http://127.0.0.1:8080' + url); assert.equal(r.statusCode, 200); assert.equal(r.data.toString(), rep); } describe('hello, test', () => { function test_hello(hello) { describe(hello + ' test', () => { it('fibjs', () => { test_get('/' + hello + '/fibjs', 'hello, fibjs. I love you.'); }); it('fibjs*', () => { test_get('/' + hello + '/fibjs-great', 'hello, fibjs-great. I love you.'); }); it('JavaScript', () => { test_get('/' + hello + '/JavaScript', 'hello, JavaScript'); }); it('v8', () => { test_get('/' + hello + '/v8', 'hello, v8'); }); }); } test_hello('hello'); test_hello('bonjour'); }); process.exit(test.run());

In lines 6 to 10 of this code, we add a startup main.jscode and wait for a while before starting the test.

code coverage check

Good test cases need to consider that the test cases need to cover every branch of the business to ensure that the business is executed correctly. At this time, you can use code coverage check to determine whether the test is complete.

This process is very simple, just add the --cov parameter when testing:

1
fibjs --cov test

After the test is completed, a log file fibjs-xxxx.lcov will be generated in the current directory. At this time, the log needs to be analyzed and a report generated:

1
fibjs --cov-process fibjs-xxxx.lcov out

A set of analysis reports can be generated in the out directory. Enter the directory to check, and you can see the following page: cov You can see that main.jsthe code coverage has reached 100%, which means that the test completely covers the business logic. Click main.jsfurther to see a more detailed report.

👉【Find out the performance killer