This turned out to be more time consuming than Iād like. I was testing a Node.js program that would log to stdout as prescribed by The 12 Factor Apps - Logs page.
Say you have something like
// index.js
setInterval(() => console.log(Date.now()), 1000);
We want to execute the program under test, allow it to
print to stdout
and then make assertions about the output.
// test.js
import test from 'ava';
const exec = require('child_process').exec;
test('app prints to stdout', t => {
return new Promise((resolve, reject) => {
const server = exec(
'node ./index.js',
{ env: { SERVER_PORT: 4000 }},
(error, stdout, stderr) => {
// not useful as SIGTERM appears as an erroneous exit
// if (error || stderr) {
// reject();
// }
const log = stdout.trim().split('\n');
resolve(log);
}
);
setTimeout(() => { server.kill('SIGTERM'); }, 1000);
}).then((log) => {
t.truthy(log);
});
});
test('app logs fast enough', t => {
return new Promise((resolve, reject) => {
const server = exec(
'node ./index.js',
{ env: { SERVER_PORT: 4001 }},
(error, stdout, stderr) => {
const log = stdout.trim().split('\n');
resolve(log);
}
);
setTimeout(() => { server.kill('SIGTERM'); }, 1000);
}).then((log) => {
t.true(log.length > 3);
});
});
Some tips:
exec
call
in a Promise.exec
ās option.SERVER_PORT
option with different port values for every test to allow your test suite to run tests and server processes in parallel.exec
ās callback is executed after the process terminates. Since we are
testing a long running process we need to explicitly terminate the server by sending it a SIGTERM
signal. Above we do so in a setTimeout
.If you need help solving your business problems with software read how to hire me.