The intended behavior of the bracketed [github], [bower], [discord] service names in the pull request title is to trigger the designated service tests. That way, affected services can be proven working during code review, without needing to run tests on a dev machine, nor running all the slow (and flaky) service tests. Example pull request titles: - [Travis] Fix timeout issues - [Travis Sonar] Support user token authentication - [CRAN CPAN CTAN] Add test coverage The observed behavior is that, whenever bracketed service names are provided, all of the service tests run. This is due to a Mocha limitation, which is that exclusive tests (it.only and describe.only) can only be applied synchronously. In other words, if we try to fetch the PR title and then add exclusive tests in the callback, all the tests will run anyway. This is true even when using _mocha --delay, as we are, and is true whether I use request or node-fetch. Undoubtedly this could be fixed, though it's not worth it. The problem is obscure and therefore low priority for Mocha, which is quite backlogged. And, there is an easy workaround, which is to generate the list of services to test in a separate process. The pull request script test:services:pr is now 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. In addition to sidestepping the Mocha bug, this setup makes it easier to reason about and debug these two steps of the test runner on a dev machine, and since I can't get pipefail to work – and want to be able to run the steps separately – I'm not using Node's built in pre scripts. Overall, separating these concerns this makes the test runner easier to reason about.
93 lines
3.6 KiB
JavaScript
93 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');
|
|
|
|
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);
|