Files
shields/lib/service-test-runner/cli.js
Paul Melnikow ea4b758612 Move service tests alongside code (#1563)
Per discussion in #1543
2018-03-20 18:32:48 -07:00

95 lines
3.6 KiB
JavaScript

// Usage:
//
// Run all services:
// npm run test:services
//
// Run some services:
// npm run test:services -- --only=service1,service2,service3
//
// Alternatively, pass a newline-separated list of services to stdin.
// echo "service1\nservice2\nservice3" | npm run test:services -- --stdin
//
// Service tests are run in CI in two cases: scheduled builds and pull
// requests. The scheduled builds run _all_ the service tests, whereas the
// pull requests run service tests designated in the PR title. In this way,
// affected services can be proven working during code review without needing
// to run all the slow (and likely flaky) service tests.
//
// Example pull request titles:
//
// - [Travis] Fix timeout issues
// - [Travis Sonar] Support user token authentication
// - [CRAN CPAN CTAN] Add test coverage
//
// The pull request script test:services:pr is split into two parts. First the
// :prepare script infers the pull request context, fetches the PR title, and
// writes the list of affected services to a file. Then the :run script reads
// the list of affected services and runs the appropriate tests.
//
// There are three reasons to separate these two steps into separate processes
// and build stages:
//
// 1. Generating the list of services to test is necessarily asynchronous, and
// in Mocha, exclusive tests (`it.only` and `describe.only`) can only be
// applied synchronously. In other words, if you try to add exclusive tests
// in an asynchronous callback, all the tests will run. This is true even
// when using `_mocha --delay`, as we are. Undoubtedly this could be fixed,
// though it's not worth it. The problem is obscure and therefore low
// for Mocha, which is quite backlogged. There is an easy workaround, which
// is to generate the list of services to test in a separate process.
// 2. Executing these two steps of the test runner separately makes the process
// easier to reason about and much easier to debug on a dev machine.
// 3. Getting "pipefail" to work cross platform with an npm script seems tricky.
// Relying on npm scripts is safer. Using "pre" makes it impossible to run
// the second step without the first.
'use strict';
const minimist = require('minimist');
const readAllStdinSync = require('read-all-stdin-sync');
const Runner = require('./runner');
const serverHelpers = require('../../lib/in-process-server-test-helpers');
require('../../lib/unhandled-rejection.spec');
let server;
before('Start running the server', function () {
this.timeout(5000);
server = serverHelpers.start();
});
after('Shut down the server', function () { serverHelpers.stop(server); });
const runner = new Runner();
runner.prepare();
// The server's request cache causes side effects between tests.
runner.beforeEach = () => { serverHelpers.reset(server); };
const args = minimist(process.argv.slice(3));
const stdinOption = args.stdin;
const onlyOption = args.only;
let onlyServices;
if (stdinOption && onlyOption) {
console.error('Do not use --only with --stdin');
} else if (stdinOption) {
const allStdin = readAllStdinSync().trim();
onlyServices = allStdin ? allStdin.split('\n') : [];
} else if (onlyOption) {
onlyServices = onlyOption.split(',');
}
if (typeof onlyServices === 'undefined') {
console.info('Running all service tests.');
} else if (onlyServices.length === 0) {
console.info('No service tests to run. Exiting.');
process.exit(0);
} else {
console.info(`Running tests for ${onlyServices.length} services: ${onlyServices.join(', ')}.\n`);
runner.only(onlyServices);
}
runner.toss();
// Invoke run() asynchronously, because Mocha will not start otherwise.
process.nextTick(run);