@stryker-mutator/core
Version:
The extendable JavaScript mutation testing framework
86 lines • 4.27 kB
JavaScript
import { createInjector } from 'typed-inject';
import { commonTokens } from '@stryker-mutator/api/plugin';
import { PrepareExecutor, MutantInstrumenterExecutor, DryRunExecutor, MutationTestExecutor, } from './process/index.js';
import { coreTokens } from './di/index.js';
import { retrieveCause, ConfigError } from './errors.js';
import { provideLogging, provideLoggingBackend, } from './logging/index.js';
/**
* The main Stryker class.
* It provides a single `runMutationTest()` function which runs mutation testing:
*/
export class Stryker {
cliOptions;
injectorFactory;
/**
* @constructor
* @param cliOptions The cli options.
* @param injectorFactory The injector factory, for testing purposes only
*/
constructor(cliOptions, injectorFactory = createInjector) {
this.cliOptions = cliOptions;
this.injectorFactory = injectorFactory;
}
async runMutationTest() {
const rootInjector = this.injectorFactory();
try {
const prepareInjector = provideLogging(await provideLoggingBackend(rootInjector, process.stdout)).provideValue(coreTokens.reporterOverride, undefined);
return await Stryker.run(prepareInjector, {
cliOptions: this.cliOptions,
targetMutatePatterns: undefined,
});
}
finally {
await rootInjector.dispose();
}
}
/**
* Does the actual mutation testing.
* Note: this is a public static method, so it can be reused from `StrykerServer`
* @internal
*/
static async run(mutationRunInjector, args) {
try {
// 1. Prepare. Load Stryker configuration, load the input files
const prepareExecutor = mutationRunInjector.injectClass(PrepareExecutor);
const mutantInstrumenterInjector = await prepareExecutor.execute(args);
try {
// 2. Mutate and instrument the files and write to the sandbox.
const mutantInstrumenter = mutantInstrumenterInjector.injectClass(MutantInstrumenterExecutor);
const dryRunExecutorInjector = await mutantInstrumenter.execute();
// 3. Perform a 'dry run' (initial test run). Runs the tests without active mutants and collects coverage.
const dryRunExecutor = dryRunExecutorInjector.injectClass(DryRunExecutor);
const mutationRunExecutorInjector = await dryRunExecutor.execute();
// 4. Actual mutation testing. Will check every mutant and if valid run it in an available test runner.
const mutationRunExecutor = mutationRunExecutorInjector.injectClass(MutationTestExecutor);
const mutantResults = await mutationRunExecutor.execute();
return mutantResults;
}
catch (error) {
if (mutantInstrumenterInjector.resolve(commonTokens.options)
.cleanTempDir !== 'always') {
const log = mutationRunInjector.resolve(commonTokens.getLogger)(Stryker.name);
log.debug('Not removing the temp dir because an error occurred');
mutantInstrumenterInjector.resolve(coreTokens.temporaryDirectory).removeDuringDisposal = false;
}
throw error;
}
}
catch (error) {
const log = mutationRunInjector.resolve(commonTokens.getLogger)(Stryker.name);
const cause = retrieveCause(error);
if (cause instanceof ConfigError) {
log.error(cause.message);
}
else {
log.error('Unexpected error occurred while running Stryker', error);
log.info('This might be a known problem with a solution documented in our troubleshooting guide.');
log.info('You can find it at https://stryker-mutator.io/docs/stryker-js/troubleshooting/');
if (!log.isTraceEnabled()) {
log.info('Still having trouble figuring out what went wrong? Try `npx stryker run --fileLogLevel trace --logLevel debug` to get some more info.');
}
}
throw cause;
}
}
}
//# sourceMappingURL=stryker.js.map