Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WIP] Remove/deprecate old stryker options #2395

Merged
merged 31 commits into from
Aug 26, 2020
Merged
Show file tree
Hide file tree
Changes from 25 commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion e2e/test/babel-transpiling/stryker.conf.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ module.exports = {
mutate: [
'src/*.js'
],
testFramework: 'mocha',
testRunner: 'mocha',
coverageAnalysis: 'off',
buildCommand: 'npm run build',
Expand Down
1 change: 0 additions & 1 deletion e2e/test/grunt-stryker-test/Gruntfile.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ module.exports = function (grunt) {
]
},
options: {
testFramework: 'jasmine',
testRunner: 'karma',
logLevel: 'info',
concurrency: 2,
Expand Down
1 change: 0 additions & 1 deletion e2e/test/grunt-stryker-test/stryker.conf.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ module.exports = function (config) {
files: ['sampleProject/**']
}
},
testFramework: 'jasmine',
testRunner: 'karma',
logLevel: 'info',
concurrency: 2
Expand Down
2 changes: 0 additions & 2 deletions e2e/test/jasmine-javascript/stryker.conf.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
module.exports = function (config) {
config.set({
mutate: ['lib/**/*.js'],
mutator: 'javascript',
coverageAnalysis: 'perTest',
testFramework: 'jasmine',
testRunner: 'jasmine',
reporters: ['clear-text', 'event-recorder'],
concurrency: 2,
Expand Down
1 change: 0 additions & 1 deletion e2e/test/jest-node/stryker.conf.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
{
"$schema": "../../node_modules/@stryker-mutator/core/schema/stryker-schema.json",
"mutator": "javascript",
"packageManager": "npm",
"testRunner": "jest",
"tempDirName": "stryker-tmp",
Expand Down
2 changes: 0 additions & 2 deletions e2e/test/jest-with-ts/stryker.conf.json
Original file line number Diff line number Diff line change
@@ -1,13 +1,11 @@
{
"$schema": "../../node_modules/@stryker-mutator/core/schema/stryker-schema.json",
"mutator": "typescript",
"mutate": [
"src/data-access/mappers/TableStorageMapper.ts"
],
"packageManager": "npm",
"testRunner": "jest",
"tempDirName": "stryker-tmp",
"transpilers": [],
"concurrency": 2,
"checkers": [
"typescript"
Expand Down
4 changes: 1 addition & 3 deletions e2e/test/karma-jasmine/stryker.conf.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
module.exports = function (config) {
config.set({
mutate: ['src/*.js'],
testFramework: 'jasmine',
testRunner: 'karma',
reporters: ['clear-text', 'html', 'event-recorder'],
concurrency: 2,
Expand All @@ -13,7 +12,6 @@ module.exports = function (config) {
}
}
},
timeoutMS: 60000,
mutator: 'javascript'
timeoutMS: 60000
});
};
2 changes: 0 additions & 2 deletions e2e/test/karma-mocha/stryker.conf.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
module.exports = function (config) {
config.set({
mutate: ['src/*.js'],
mutator: 'javascript',
testFramework: 'mocha',
testRunner: 'karma',
reporters: ['clear-text', 'html', 'event-recorder'],
karma: {
Expand Down
3 changes: 1 addition & 2 deletions e2e/test/vue-cli-javascript-jest/stryker.conf.json
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
{
"$schema": "../../node_modules/@stryker-mutator/core/schema/stryker-schema.json",
"mutator": {
"name": "javascript",
"plugins": []
"plugins": []
},
"mutate": [
"{src,lib}/**/*.+(js|vue)",
Expand Down
36 changes: 5 additions & 31 deletions packages/api/schema/stryker-core.json
Original file line number Diff line number Diff line change
Expand Up @@ -199,11 +199,8 @@
"type": "object",
"additionalProperties": false,
"properties": {
"name": {
"type": "string",
"default": "javascript"
},
"plugins": {
"description": "Override the default babel plugins Stryker uses to parse your JavaScript files. The default list of plugins is extensive and normally doesn't need overriding. Stryker also loads your babel plugins by default (if you have them). If Stryker's default babel plugins conflicts with your plugins, try to override this list with an empty array.",
"anyOf": [
{
"type": "array",
Expand All @@ -227,10 +224,7 @@
},
"default": []
}
},
"required": [
"name"
]
}
},
"warningOptions": {
"title": "WarningOptions",
Expand Down Expand Up @@ -333,17 +327,9 @@
]
},
"mutator": {
"description": "With mutator you configure which mutator plugin you want to use, and optionally, which mutation types to exclude from the test run.",
"oneOf": [
{
"type": "string"
},
{
"$ref": "#/definitions/mutatorDescriptor"
}
],
"default": "javascript",
"errorMessage": "should be an \"object\" describing the mutator or a \"string\". See https://github.com/stryker-mutator/stryker/tree/master/packages/core#mutator."
"description": "Configure how Stryker mutates your code.",
"$ref": "#/definitions/mutatorDescriptor",
"default": {}
},
"packageManager": {
"enum": [
Expand Down Expand Up @@ -393,10 +379,6 @@
"type": "string",
"default": ".stryker-tmp"
},
"testFramework": {
"description": "Configure which test framework you are using. This option is not mandatory, as Stryker is test framework agnostic (it doesn't care what framework you use), However, it is required when coverageAnalysis is set to 'perTest', because Stryker needs to hook into the test framework in order to measure code coverage results per test and filter tests to run.",
"type": "string"
},
"testRunner": {
"description": "With 'testRunner' you specify the test runner that Stryker uses to run your tests. The default value is command. The command runner runs a configurable bash/cmd command and bases the result on the exit code of that program (0 for success, otherwise failed). You can configure this command via the config file using the 'commandRunner: { command: 'npm run mocha' }'. It uses 'npm test' as the command by default.",
"type": "string",
Expand All @@ -417,14 +399,6 @@
"type": "number",
"default": 5000
},
"transpilers": {
"description": "Configure which transpiler plugins should transpile the code before it's executed. This is an array where the transpilers are called in the other of the array. This defaults to an empty array meaning no transpilation will be done.",
"type": "array",
"items": {
"type": "string"
},
"default": []
},
"tsconfigFile": {
"description": "Configure the (root) tsconfig file for typescript projects. This will allow Stryker to rewrite the `extends` and `references` settings in this and related tsconfig files in your sandbox. Defaults to `tsconfig.json`. This setting is also used when you enable the `@stryker-mutator/typescript-checker plugin",
"type": "string",
Expand Down
3 changes: 1 addition & 2 deletions packages/api/src/plugin/Contexts.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { MutatorDescriptor, StrykerOptions } from '../../core';
import { StrykerOptions } from '../../core';
import { Logger, LoggerFactoryMethod } from '../../logging';

import { PluginResolver } from './Plugins';
Expand All @@ -19,5 +19,4 @@ export interface BaseContext {
*/
export interface PluginContext extends BaseContext {
[commonTokens.options]: StrykerOptions;
[commonTokens.mutatorDescriptor]: MutatorDescriptor;
}
1 change: 0 additions & 1 deletion packages/api/src/plugin/tokens.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ export const commonTokens = Object.freeze({
getLogger: stringLiteral('getLogger'),
injector,
logger: stringLiteral('logger'),
mutatorDescriptor: stringLiteral('mutatorDescriptor'),
options: stringLiteral('options'),
pluginResolver: stringLiteral('pluginResolver'),
produceSourceMaps: stringLiteral('produceSourceMaps'),
Expand Down
2 changes: 0 additions & 2 deletions packages/core/src/StrykerCli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -73,10 +73,8 @@ export default class StrykerCli {
'--coverageAnalysis <perTest|all|off>',
`The coverage analysis strategy you want to use. Default value: "${defaultValues.coverageAnalysis}"`
)
.option('--testFramework <name>', 'The name of the test framework you want to use.')
.option('--testRunner <name>', 'The name of the test runner you want to use')
.option('--mutator <name>', 'The name of the mutant generator you want to use')
.option('--transpilers <listOfTranspilers>', 'A comma separated list of transpilers to use.', list)
.option('--reporters <name>', 'A comma separated list of the names of the reporter(s) you want to use', list)
.option('--plugins <listOfPlugins>', 'A list of plugins you want stryker to load (`require`).', list)
.option('--timeoutMS <number>', 'Tweak the absolute timeout used to wait for a test runner to complete', parseInt)
Expand Down
66 changes: 47 additions & 19 deletions packages/core/src/config/OptionsValidator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import os = require('os');
import Ajv = require('ajv');
import { StrykerOptions, strykerCoreSchema, WarningOptions } from '@stryker-mutator/api/core';
import { tokens, commonTokens } from '@stryker-mutator/api/plugin';
import { noopLogger, normalizeWhitespaces, propertyPath, deepFreeze } from '@stryker-mutator/util';
import { noopLogger, propertyPath, deepFreeze } from '@stryker-mutator/util';
import { Logger } from '@stryker-mutator/api/logging';

import { coreTokens } from '../di';
Expand All @@ -23,41 +23,70 @@ export class OptionsValidator {
this.validateFn = ajv.compile(schema);
}

public validate(options: unknown): asserts options is StrykerOptions {
public validate(options: Record<string, unknown>): asserts options is StrykerOptions {
this.removeDeprecatedOptions(options);
this.schemaValidate(options);
this.additionalValidation(options);
}

private removeDeprecatedOptions(rawOptions: Record<string, unknown>) {
if (typeof rawOptions.mutator === 'string') {
this.log.warn(
'DEPRECATED. Use of "mutator" as string is no longer needed. You can remove it from your configuration. Stryker now supports mutating of JavaScript and friend files out of the box.'
);
delete rawOptions.mutator;
}
// @ts-expect-error mutator.name
if (typeof rawOptions.mutator === 'object' && rawOptions.mutator.name) {
this.log.warn(
'DEPRECATED. Use of "mutator.name" is no longer needed. You can remove "mutator.name" from your configuration. Stryker now supports mutating of JavaScript and friend files out of the box.'
);
// @ts-expect-error mutator.name
delete rawOptions.mutator.name;
}
if (Object.keys(rawOptions).includes('testFramework')) {
this.log.warn(
'DEPRECATED. Use of "testFramework" is no longer needed. You can remove it from your configuration. Your test runner plugin now handles its own test framework integration.'
);
delete rawOptions.testFramework;
}
if (Array.isArray(rawOptions.transpilers)) {
const example = rawOptions.transpilers.includes('babel')
? 'babel src --out-dir lib'
: rawOptions.transpilers.includes('typescript')
? 'tsc -b'
: rawOptions.transpilers.includes('webpack')
? 'webpack --config webpack.config.js'
: 'npm run build';
this.log.warn(
`DEPRECATED. Support for "transpilers" is removed. You can now configure your own "${propertyPath<StrykerOptions>(
'buildCommand'
)}". For example, ${example}.`
);
delete rawOptions.transpilers;
}
}

private additionalValidation(options: StrykerOptions) {
const additionalErrors: string[] = [];
if (options.thresholds.high < options.thresholds.low) {
additionalErrors.push('Config option "thresholds.high" should be higher than "thresholds.low".');
}
if (options.transpilers.length > 1 && options.coverageAnalysis !== 'off') {
additionalErrors.push(
normalizeWhitespaces(
`Config option "coverageAnalysis" is invalid. Coverage analysis "${options.coverageAnalysis}"
is not supported for multiple transpilers (configured transpilers: ${options.transpilers.map((t) => `"${t}"`).join(', ')}).
Change it to "off". Please report this to the Stryker team if you whish this feature to be implemented.`
)
);
}
if (options.maxConcurrentTestRunners !== Number.MAX_SAFE_INTEGER) {
this.log.warn('DEPRECATED. Use of "maxConcurrentTestRunners" is deprecated. Please use "concurrency" instead.');
if (!options.concurrency && options.maxConcurrentTestRunners < os.cpus().length - 1) {
options.concurrency = options.maxConcurrentTestRunners;
}
}

additionalErrors.forEach((error) => this.log.error(error));
this.throwErrorIfNeeded(additionalErrors);
}

private schemaValidate(options: unknown): asserts options is StrykerOptions {
if (!this.validateFn(options)) {
const errors = describeErrors(this.validateFn.errors!);
errors.forEach((error) => this.log.error(error));
this.throwErrorIfNeeded(errors);
const describedErrors = describeErrors(this.validateFn.errors!);
describedErrors.forEach((error) => this.log.error(error));
this.throwErrorIfNeeded(describedErrors);
}
}

Expand All @@ -71,14 +100,14 @@ export class OptionsValidator {
}

export function defaultOptions(): StrykerOptions {
const options: unknown = {};
const options: Record<string, unknown> = {};
const validator: OptionsValidator = new OptionsValidator(strykerCoreSchema, noopLogger);
validator.validate(options);
return options;
}

validateOptions.inject = tokens(commonTokens.options, coreTokens.optionsValidator);
export function validateOptions(options: unknown, optionsValidator: OptionsValidator): StrykerOptions {
export function validateOptions(options: Record<string, unknown>, optionsValidator: OptionsValidator): StrykerOptions {
optionsValidator.validate(options);
return deepFreeze(options) as StrykerOptions;
}
Expand All @@ -96,8 +125,7 @@ export function markUnknownOptions(options: StrykerOptions, schema: Record<strin
});
const p = `${propertyPath<StrykerOptions>('warnings')}.${propertyPath<WarningOptions>('unknownOptions')}`;
if (unknownPropertyNames.length) {
log.warn(`
Possible causes:
log.warn(`Possible causes:
* Is it a typo on your end?
* Did you only write this property as a comment? If so, please postfix it with "_comment".
* You might be missing a plugin that is supposed to use it. Stryker loaded plugins from: ${JSON.stringify(options.plugins)}
Expand Down
5 changes: 2 additions & 3 deletions packages/core/src/di/buildChildProcessInjector.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,15 @@ import { StrykerOptions } from '@stryker-mutator/api/core';
import { commonTokens, Injector, PluginContext, tokens } from '@stryker-mutator/api/plugin';
import { createInjector } from 'typed-inject';

import { mutatorDescriptorFactory, pluginResolverFactory } from './factoryMethods';
import { pluginResolverFactory } from './factoryMethods';

import { coreTokens, provideLogger } from '.';

export function buildChildProcessInjector(options: StrykerOptions): Injector<PluginContext> {
return provideLogger(createInjector())
.provideValue(commonTokens.options, options)
.provideFactory(coreTokens.pluginDescriptors, pluginDescriptorsFactory)
.provideFactory(commonTokens.pluginResolver, pluginResolverFactory)
.provideFactory(commonTokens.mutatorDescriptor, mutatorDescriptorFactory);
.provideFactory(commonTokens.pluginResolver, pluginResolverFactory);
}

function pluginDescriptorsFactory(options: StrykerOptions): readonly string[] {
Expand Down
3 changes: 1 addition & 2 deletions packages/core/src/di/buildMainInjector.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import BroadcastReporter from '../reporters/BroadcastReporter';
import { TemporaryDirectory } from '../utils/TemporaryDirectory';
import Timer from '../utils/Timer';

import { mutatorDescriptorFactory, pluginResolverFactory } from './factoryMethods';
import { pluginResolverFactory } from './factoryMethods';

import { coreTokens, PluginCreator } from '.';

Expand All @@ -29,7 +29,6 @@ buildMainInjector.inject = tokens(commonTokens.injector);
export function buildMainInjector(injector: CliOptionsProvider): Injector<MainContext> {
const pluginResolverProvider = createPluginResolverProvider(injector);
return pluginResolverProvider
.provideFactory(commonTokens.mutatorDescriptor, mutatorDescriptorFactory)
.provideFactory(coreTokens.pluginCreatorReporter, PluginCreator.createFactory(PluginKind.Reporter))
.provideFactory(coreTokens.pluginCreatorChecker, PluginCreator.createFactory(PluginKind.Checker))
.provideClass(coreTokens.reporter, BroadcastReporter)
Expand Down
1 change: 0 additions & 1 deletion packages/core/src/di/coreTokens.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ export const timer = 'timer';
export const timeOverheadMS = 'timeOverheadMS';
export const loggingContext = 'loggingContext';
export const mutationTestReportHelper = 'mutationTestReportHelper';
export const transpiler = 'transpiler';
export const sandbox = 'sandbox';
export const sandboxWorkingDirectory = 'sandboxWorkingDirectory'; // TODO: Remove if unused post mutation switching
export const concurrencyTokenProvider = 'concurrencyTokenProvider';
Expand Down
21 changes: 0 additions & 21 deletions packages/core/src/di/factoryMethods.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import { MutatorDescriptor, StrykerOptions } from '@stryker-mutator/api/core';
import { Logger } from '@stryker-mutator/api/logging';
import { commonTokens, Injector, PluginResolver, tokens } from '@stryker-mutator/api/plugin';

Expand All @@ -12,23 +11,3 @@ export function pluginResolverFactory(
return pluginLoader;
}
pluginResolverFactory.inject = tokens(commonTokens.injector);

export function mutatorDescriptorFactory(options: StrykerOptions): MutatorDescriptor {
const defaults: MutatorDescriptor = {
plugins: null,
name: 'javascript',
excludedMutations: [],
};
if (typeof options.mutator === 'string') {
return {
...defaults,
name: options.mutator,
};
}

return {
...defaults,
...options.mutator,
};
}
mutatorDescriptorFactory.inject = tokens(commonTokens.options);
Loading