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

feat(ignore patterns): add "ignorePatterns" config option #2848

Merged
merged 26 commits into from
May 3, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
9ac5e0b
WIP: Ignore patterns
nicojs Apr 21, 2021
83baa65
Merge branch 'epic/v5' into feat/ignore-patterns
nicojs Apr 21, 2021
18a6a64
Also ignore the reports directory
nicojs Apr 21, 2021
dc9f09d
No default for ignore patterns
nicojs Apr 21, 2021
8b5d8b3
Ignore stryker.log file
nicojs Apr 21, 2021
6f778ef
Document "ignorePatterns"
nicojs Apr 21, 2021
90f46e4
Log a warning when both "ignorePatterns" and "files" are set.
nicojs Apr 21, 2021
eb0fcd3
Add cli option `--ignorePatterns`
nicojs Apr 21, 2021
043716f
Remove unused file
nicojs Apr 23, 2021
1c70a30
Add test for whitelisting with ignore patterns
nicojs Apr 23, 2021
28510b0
Ignore with... minimatch?
nicojs Apr 23, 2021
6fc7b2b
Deprecate "files"
nicojs Apr 26, 2021
f518b66
Use windows file resolving on windows
nicojs Apr 26, 2021
9ec65f5
Remove files from e2e test
nicojs Apr 26, 2021
83d86e6
Implement warning when a pattern doesn't amount to anything
nicojs Apr 26, 2021
d6ee659
test(e2e): use stryker json config for grunt
nicojs Apr 26, 2021
5b0c896
Fix bug with minimatch
nicojs Apr 26, 2021
aba6897
Change grunt-stryker to use "ignorePatterns" vs "files"
nicojs Apr 27, 2021
a557501
Document new usage of ignorePatterns
nicojs Apr 27, 2021
3f1138a
Allow ignoring deep dirs
nicojs Apr 27, 2021
02d1171
Document "ignorePatterns" better in json schema
nicojs Apr 27, 2021
644f743
Fix error in test
nicojs Apr 27, 2021
4fac565
Remove unused dependency
nicojs May 2, 2021
fe5eacd
Add remark about removing "files" altogether
nicojs May 2, 2021
2e59d55
docs: improve usage example
nicojs May 2, 2021
eb135fb
Refactor: add `matchesDirectoryPartially` helper
nicojs May 2, 2021
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
22 changes: 13 additions & 9 deletions docs/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -126,21 +126,25 @@ Set the log level that Stryker uses to write to the "stryker.log" file. Possible

### `files` [`string[]`]

Default: result of `git ls-files --others --exclude-standard --cached --exclude .stryker-tmp`<br />
Default: `undefined`<br />
Command line: `[--files|-f] src/**/*.js,a.js,test/**/*.js`<br />
Config file: `"files": ["src/**/*.js", "!src/**/index.js", "test/**/*.js"]`

With `files`, you can choose which files should be included in your test runner sandbox.
This is normally not needed as it defaults to all files not ignored by git.
Try it out yourself with this command: `git ls-files --others --exclude-standard --cached --exclude .stryker-tmp`.
**DEPRECATED**. Please use [`ignorePatterns`](#ignorepatterns-string) instead.

If you do need to override `files` (for example: when your project does not live in a git repository),
you can override the files here.
### `ignorePatterns` [`string[]`]

When using the command line, the list can only contain a comma separated list of globbing expressions.
When using the config file you can provide an array with `string`s
Default: `[]`<br />
Command line: `--ignorePatterns dist,coverage`<br />
Config file: `"ignorePatterns": ["dist", "coverage"]`<br />

Specify the patterns to all files or directories that are not used to run your tests and thus should _not be copied_ to the sandbox directory for mutation testing. Each patterns in this array should be a [`.gitignore`-style glob pattern](https://git-scm.com/docs/gitignore#_pattern_format).

You can *ignore* files by adding an exclamation mark (`!`) at the start of an expression.
These patterns are **always ignored**: `['node_modules', '.git', '/reports', '/stryker.log', '.stryker-tmp']`. Because Stryker always ignores these, you should rarely have to adjust the `"ignorePatterns"` setting at all. If you want to undo one of these ignore patterns, you can use the `!` prefix, for example: `['!node_modules']`.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do you specify reports and stryker.log with a / at the front, but not for other files/folders?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because I know for a fact that Stryker places them at the root of your project. For example. I would like the src/reports directory that someone might have to be included. Starting with a / means to only match when it exists in the root of the cwd.


If a glob pattern starts with `/`, the pattern is relative to the current working directory. For example, `/foo.js` matches to `foo.js` but not `subdir/foo.js`.

When using the command line, the list can only contain a comma separated list of globbing expressions.

### `inPlace` [`boolean`]

Expand Down
6 changes: 4 additions & 2 deletions e2e/test/grunt-stryker-test/Gruntfile.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,15 @@ module.exports = function (grunt) {
options: {
testRunner: 'karma',
logLevel: 'info',
fileLogLevel: 'warn',
concurrency: 2,
tempDirName: '.stryker-tmp-2'
tempDirName: '.stryker-tmp-2',
karma: { config: { files: [ 'sampleProject/**' ] }}
},
},
withConfigFile: {
options: {
configFile: './stryker.conf.js'
configFile: './stryker.grunt.conf.json'
}
}
}
Expand Down
4 changes: 3 additions & 1 deletion e2e/test/grunt-stryker-test/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
"version": "0.0.0",
"private": true,
"scripts": {
"test": "grunt test"
"pretest": "rimraf reports stryker.log",
"test": "grunt test",
"posttest": "mocha --no-config --require ../../tasks/ts-node-register.js verify/*.ts"
}
}
15 changes: 0 additions & 15 deletions e2e/test/grunt-stryker-test/stryker.conf.js

This file was deleted.

17 changes: 17 additions & 0 deletions e2e/test/grunt-stryker-test/stryker.grunt.conf.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{
"$schema": "../../node_modules/@stryker-mutator/core/schema/stryker-schema.json",
"mutate": [
"sampleProject/src/**"
],
"karma": {
"config": {
"files": [
"sampleProject/**"
]
}
},
"testRunner": "karma",
"logLevel": "info",
"fileLogLevel": "warn",
"concurrency": 2
}
9 changes: 9 additions & 0 deletions e2e/test/grunt-stryker-test/verify/verify.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { expect } from 'chai';
import fs from 'fs';

describe('grunt stryker test', () => {
it('should not log warnings', () => {
const logFileContents = fs.readFileSync('stryker.log', 'utf-8');
expect(logFileContents).empty;
});
});
1 change: 0 additions & 1 deletion e2e/test/use-stryker-programmatically/usingStryker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import Stryker from '@stryker-mutator/core';

new Stryker({
coverageAnalysis: 'off',
files: [],
mutate: [],
testRunner: 'mocha'
}).runMutationTest().then(() => console.log('done'));
17 changes: 9 additions & 8 deletions packages/api/schema/stryker-core.json
Original file line number Diff line number Diff line change
Expand Up @@ -253,7 +253,7 @@
"type": "number"
},
"maxTestRunnerReuse": {
"description": "Restart each forked threads after <n> runs. Not recommended unless you are experiencing memory leaks that you are unable to resolve. (default: 0)",
"description": "Restart each forked worker after <n> runs. Not recommended unless you are experiencing memory leaks that you are unable to resolve. (default: 0)",
"type": "number",
"default": 0
},
Expand Down Expand Up @@ -282,18 +282,19 @@
"$ref": "#/definitions/eventRecorderOptions",
"default": {}
},
"ignorePatterns": {
"description": "Specify the patterns to all files or directories that are not used to run your tests and thus should *not be copied* to the sandbox directory for mutation testing. Each patterns in this array should be a [`.gitignore`-style glob pattern](https://git-scm.com/docs/gitignore#_pattern_format).\n\nThese patterns are **always ignored**: `['node_modules', '.git', '/reports', '/stryker.log', '.stryker-tmp']`. Because Stryker always ignores these, you should rarely have to adjust the `\"ignorePatterns\"` setting at all. If you want to undo one of these ignore patterns, you can use the `!` prefix, for example: `['!node_modules']`.\n\nIf a glob pattern starts with `/`, the pattern is relative to the current working directory. For example, `/foo.js` matches to `foo.js` but not `subdir/foo.js`.\n\nWhen using the command line, the list can only contain a comma separated list of globbing expressions.",
"type": "array",
"items": {
"type": "string"
},
"default": []
},
"fileLogLevel": {
"description": "Set the log level that Stryker uses to write to the \"stryker.log\" file",
"$ref": "#/definitions/logLevel",
"default": "off"
},
"files": {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't this still be in the schema, but deprecated?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As explained during the community meeting, I don't want people to use it. The rewrite to ignorePatterns is being done before the options are validated. This is in line with other deprecated options.

"description": "With `files` you can choose which files should be included in your test runner sandbox.\nThis is normally not needed as it defaults to all files not ignored by git.\nTry it out yourself with this command: `git ls-files --others --exclude-standard --cached --exclude .stryker-tmp`.\n\nIf you do need to override `files` (for example: when your project does not live in a git repository),\nyou can override the files here.\n\nWhen using the command line, the list can only contain a comma separated list of globbing expressions.\nWhen using the config file you can provide an array with `string`s",
"type": "array",
"items": {
"type": "string"
}
},
"inPlace": {
"type": "boolean",
"description": "Determines whether or not Stryker should mutate your files in place. Note: mutating your files in place is generally not needed for mutation testing, unless you have a dependency in your project that is really dependent on the file locations (like \"app-root-path\" for example).\n\nWhen `true`, Stryker will override your files, but it will keep a copy of the originals in the temp directory (using `tempDirName`) and it will place the originals back after it is done.\n\nWhen `false` (default) Stryker will work in the copy of your code inside the temp directory.",
Expand Down
21 changes: 20 additions & 1 deletion packages/core/src/config/options-validator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import { coreTokens } from '../di';
import { ConfigError } from '../errors';
import { isWarningEnabled } from '../utils/object-utils';
import { CommandTestRunner } from '../test-runner/command-test-runner';
import { MUTATION_RANGE_REGEX } from '../input';
import { IGNORE_PATTERN_CHARACTER, MUTATION_RANGE_REGEX } from '../input';

import { describeErrors } from './validation-errors';

Expand Down Expand Up @@ -70,6 +70,25 @@ export class OptionsValidator {
);
delete rawOptions.transpilers;
}
if (Array.isArray(rawOptions.files)) {
const ignorePatternsName = propertyPath<StrykerOptions>('ignorePatterns');
const isString = (uncertain: unknown): uncertain is string => typeof uncertain === 'string';
const files = rawOptions.files.filter(isString);
const newIgnorePatterns: string[] = [
'**',
...files.map((filePattern) =>
filePattern.startsWith(IGNORE_PATTERN_CHARACTER) ? filePattern.substr(1) : `${IGNORE_PATTERN_CHARACTER}${filePattern}`
),
];
delete rawOptions.files;
this.log.warn(
`DEPRECATED. Use of "files" is deprecated, please use "${ignorePatternsName}" instead (or remove "files" altogether will probably work as well). For now, rewriting them as ${JSON.stringify(
newIgnorePatterns
)}. See https://stryker-mutator.io/docs/stryker-js/configuration/#ignorepatterns-string`
);
const existingIgnorePatterns = Array.isArray(rawOptions[ignorePatternsName]) ? (rawOptions[ignorePatternsName] as unknown[]) : [];
rawOptions[ignorePatternsName] = [...newIgnorePatterns, ...existingIgnorePatterns];
}
}

private additionalValidation(options: StrykerOptions) {
Expand Down
9 changes: 3 additions & 6 deletions packages/core/src/input/input-file-collection.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
import os from 'os';

import { File, MutationRange } from '@stryker-mutator/api/core';
import { Logger } from '@stryker-mutator/api/logging';
import { normalizeWhitespaces } from '@stryker-mutator/util';
Expand All @@ -15,12 +13,11 @@ export class InputFileCollection {
this.mutationRanges = mutationRangeToInstrument;
}

public logFiles(log: Logger): void {
public logFiles(log: Logger, ignoreRules: readonly string[]): void {
if (!this.files.length) {
log.warn(
`No files selected. Please make sure you either${os.EOL}` +
` (1) Run Stryker inside a Git repository; or${os.EOL}` +
' (2) Specify the `files` property in your Stryker configuration (`--files via command line`).'
normalizeWhitespaces(`No files found in directory ${process.cwd()} using ignore rules: ${JSON.stringify(ignoreRules)}.
Make sure you run Stryker from the root directory of your project with the correct "ignorePatterns".`)
);
} else {
if (this.filesToMutate.length) {
Expand Down