Skip to content

Commit

Permalink
fix(MochaTestRunner): Exit with a warning if no tests were executed (#…
Browse files Browse the repository at this point in the history
  • Loading branch information
simondel authored and nicojs committed Aug 25, 2017
1 parent ec4ae03 commit ac52860
Show file tree
Hide file tree
Showing 6 changed files with 71 additions and 15 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
"@types/lodash": "^4.14.34",
"@types/log4js": "0.0.32",
"@types/mkdirp": "^0.3.28",
"@types/mocha": "^2.2.34",
"@types/mocha": "^2.2.42",
"@types/mz": "0.0.31",
"@types/progress": "^1.1.28",
"@types/rimraf": "0.0.28",
Expand Down
24 changes: 16 additions & 8 deletions packages/stryker-mocha-runner/src/MochaTestRunner.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,7 @@ import * as log4js from 'log4js';
import { EventEmitter } from 'events';
import { TestRunner, RunResult, RunStatus, RunnerOptions } from 'stryker-api/test_runner';
import { InputFile } from 'stryker-api/core';


// import * as Mocha from 'mocha';
const Mocha = require('mocha');
import * as Mocha from 'mocha';
import StrykerMochaReporter from './StrykerMochaReporter';

const log = log4js.getLogger('MochaTestRunner');
Expand All @@ -25,12 +22,23 @@ export default class MochaTestRunner extends EventEmitter implements TestRunner
return new Promise<RunResult>((resolve, fail) => {
try {
this.purgeFiles();
let mocha = new Mocha({ reporter: StrykerMochaReporter, bail: true });
let mocha = new Mocha({ reporter: StrykerMochaReporter as any, bail: true });
this.files.filter(file => file.included).forEach(f => mocha.addFile(f.path));
try {
let runner: any = mocha.run((failures: number) => {
let result: RunResult = runner.runResult;
resolve(result);
mocha.run((failures: number) => {
const reporter = StrykerMochaReporter.CurrentInstance;
if (reporter) {
let result: RunResult = reporter.runResult;
resolve(result);
} else {
const errorMsg = 'The StrykerMochaReporter was not instantiated properly. Could not retrieve the RunResult.';
log.error(errorMsg);
resolve({
tests: [],
errorMessages: [errorMsg],
status: RunStatus.Error
});
}
});
} catch (error) {
resolve({
Expand Down
6 changes: 4 additions & 2 deletions packages/stryker-mocha-runner/src/StrykerMochaReporter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,15 @@ const log = log4js.getLogger('StrykerMochaReporter');

export default class StrykerMochaReporter {

private runResult: RunResult;
public runResult: RunResult;
private timer = new Timer();
private passedCount = 0;

static CurrentInstance: StrykerMochaReporter | undefined;

constructor(private runner: NodeJS.EventEmitter) {
this.registerEvents();
StrykerMochaReporter.CurrentInstance = this;
}

private registerEvents() {
Expand Down Expand Up @@ -53,7 +56,6 @@ export default class StrykerMochaReporter {

this.runner.on('end', () => {
this.runResult.status = RunStatus.Complete;
(this.runner as any).runResult = this.runResult;
log.debug(`Mocha test run completed: ${this.passedCount}/${this.runResult.tests.length} passed`);
});
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -87,5 +87,28 @@ describe('MochaTestRunner', function () {
}));
});

let file = (filePath: string, mutated: boolean = true, included: boolean = true) => ({ path: path.resolve(filePath), mutated, included });
describe('when no tests are executed', () => {

beforeEach(() => {
const testRunnerOptions = {
files: [
file('./testResources/sampleProject/src/MyMath.js')],
strykerOptions: {},
port: 1234
};
sut = new MochaTestRunner(testRunnerOptions);
});

it('should report no completed tests', () =>
expect(sut.run()).to.eventually.satisfy((runResult: RunResult) => {
expect(countSucceeded(runResult)).to.be.eq(0, 'Succeeded tests did not match');
expect(countFailed(runResult)).to.be.eq(0, 'Failed tests did not match');
runResult.tests.forEach(t => expect(t.timeSpentMs).to.be.greaterThan(-1).and.to.be.lessThan(1000));
expect(runResult.status).to.be.eq(RunStatus.Complete, 'Test result did not match');
expect(runResult.coverage).to.not.be.ok;
return true;
}));
});

let file = (name: string, mutated: boolean = true, included: boolean = true) => ({ path: path.resolve(name), mutated, included });
});
6 changes: 5 additions & 1 deletion packages/stryker/src/Stryker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,11 @@ export default class Stryker {

const inputFiles = await new InputFileResolver(this.config.mutate, this.config.files).resolve();
const { runResult, sandboxCoordinator } = await this.initialTestRun(inputFiles);
if (runResult && inputFiles && sandboxCoordinator) {

if (runResult.tests.length === 0) {
log.warn('No tests were executed. Stryker will exit prematurely. Please check your configuration.');
return [];
} else if (runResult && inputFiles && sandboxCoordinator) {
const mutantResults = await this.generateAndRunMutations(inputFiles, runResult, sandboxCoordinator);
const score = ScoreResultCalculator.calculate(mutantResults);
this.reporter.onScoreCalculated(score);
Expand Down
23 changes: 21 additions & 2 deletions packages/stryker/test/unit/StrykerSpec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,15 +35,15 @@ describe('Stryker', function () {
let testFrameworkOrchestratorMock: Mock<TestFrameworkOrchestrator>;
let configValidatorMock: Mock<ConfigValidator>;
let sandboxCoordinatorMock: Mock<SandboxCoordinator>;
let configReaderMock: Mock<ConfigReader>;
let configReaderMock: Mock<ConfigReader>;
let pluginLoaderMock: Mock<PluginLoader>;
let inputFiles: InputFile[];
let determineExitCodeStub: sinon.SinonStub;
let resolveInitialTestRun: (runResult: RunResult) => void;
let config: any;
let mutants: any[];
let reporter: Reporter;

beforeEach(() => {
sandbox = sinon.sandbox.create();
config = {};
Expand Down Expand Up @@ -288,6 +288,25 @@ describe('Stryker', function () {
});
});
});

describe('with no tests executed', () => {
beforeEach(() => {
resolveInitialTestRun({
status: RunStatus.Complete,
tests: []
});
});

it('should log to have quit early', async () => {
await sut.runMutationTest();
expect(log.warn).to.have.been.calledWith('No tests were executed. Stryker will exit prematurely. Please check your configuration.');
});

it('should not have tested mutations', async () => {
await sut.runMutationTest();
expect(sandboxCoordinatorMock.runMutants).not.to.have.been.called;
});
});
});
});
});
Expand Down

0 comments on commit ac52860

Please sign in to comment.