Guide Development Guide

A good life starts with the test

A programmer who does not write automatic test cases is not a good test engineer. We encourage all projects to establish complete automated test cases at the very beginning. With the development of the project, the initial investment will be rewarded hundreds of times.

Let's continue the example from the previous section and take a look at how to use fibjs to write test cases.

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();

Save as test.jslater, in the command line fibjs test.js, you see the following output, a basic test framework was written.

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

Start test server

Because we need to test the http server, we need to start the server first. The test case will send a request to the server, and then test the result of the request 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 judge whether the server logic is normal by verifying whether the result of http.get is the result we expect. According to this example, we can quickly complete a set of tests, and we optimized 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();

Group management of use cases

Let's add bonjour test. 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 content of hello and bonjour are the same, we optimized the code again and tested the two sets of services with the same set of codes:

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 it is also easy to skip and test a group of use cases individually to speed up development and testing. The following are the results of 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. According to the above example, I believe you can quickly write out 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, you must first start the server, this is very easy, we want to run test.jsto complete the test directly. We can use the following code to achieve:

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());

Line 6 to 10 of this code, we added a paragraph startup main.jscode, and wait a little, and then restart the tests.

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, code coverage checking can be used 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 of fibjs-xxxx.lcov will be generated in the current directory. At this time, it is necessary to analyze the log and generate a report:

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

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

👉 [ Find out the performance killer ]