Skip to content

Commit

Permalink
feat(cli): Add support for commands (#181)
Browse files Browse the repository at this point in the history
* Add support for the `run` command as the only command for now.
* Remove `-c` / `--configFile` options, instead use an argument
  • Loading branch information
nicojs authored Nov 19, 2016
1 parent bc2dbb7 commit fd824de
Show file tree
Hide file tree
Showing 7 changed files with 60 additions and 59 deletions.
6 changes: 4 additions & 2 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -97,11 +97,13 @@
"name": "Run stryker help",
"type": "node",
"request": "launch",
"program": "${workspaceRoot}/src/stryker-cli.js",
"program": "${workspaceRoot}/bin/stryker",
// "preLaunchTask": "build",
"stopOnEntry": false,
"args": [
"--help"
"run",
"--coverageAnalysis",
"sdsd"
],
"cwd": "${workspaceRoot}/.",
"runtimeExecutable": null,
Expand Down
60 changes: 21 additions & 39 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,51 +20,19 @@ npm install stryker stryker-api --save-dev

To test if stryker is working, execute the command:
```
node node_modules/stryker/bin/stryker --help
node_modules/.bin/stryker --version
```

## Usage

Stryker can be used in two ways:

1. Using a config file `node node_modules/stryker/bin/stryker -c stryker.conf.js`
2. Using command line arguments `node node_modules/stryker/bin/stryker –m src/file.js,src/file2.js –f libs/externalLibrary.js,src/file2.js,src/file.js,test/*.js --testFramework 'jasmine' --testRunner 'karma'`

The config file is *not* a simple json file, it should be a common js (a.k.a. npm) module looking like this:
```javascript
module.exports = function(config){
config.set({
// Your config here
});
}
```bash
node_modules/.bin/stryker <command> [options] [stryker.conf.js]
```
You might recognize this way of working from the karma test runner.

If both the config file and command line options are combined, the command line arguments will overrule the options in the config file.

All options are optional except the `files` (or `-f`) and `testRunner` options.

Both the `files` and `mutate` options are a list of globbing expressions. The globbing expressions will be resolved
using [node glob](https://github.com/isaacs/node-glob). This is the same globbing format you might know from
[Grunt](https://github.com/gruntjs/grunt) and [Karma](https://github.com/karma-runner/karma).
The way to provide this list is as an array in the config file, or as a comma seperated list on the command line (without spaces or quotes)

## Supported mutators
The mutators that are supported by Stryker can be found on [our website](http://stryker-mutator.github.io/mutators.html)

## Configuration
Options can be configured either via the command line or via a config file.
The only command supported at the moment is `run`. The last argument is the location to the stryker config file. This is optional, you can also command line options instead.
If both the config file and options are combined, the command line options will overrule the options in the config file.

### Available options
#### Config file
**Command line:** `-c stryker.conf.js` or `--configile stryker.conf.js`
**Config file:** *none, used to set the config file*
**Default value:** *none*
**Description:**
A location to a config file. That file should export a function which accepts a "config" object.
On that object you can configure all options as an alternative for the command line.
If an option is configured on both the command line and in the config file, the command line wins.
An example config:
An example stryker.conf.js file:

```javascript
module.exports = function(config){
Expand All @@ -77,7 +45,21 @@ module.exports = function(config){
plugins: ['stryker-mocha-runner', 'stryker-html-reporter']
});
}
```
```

As you can see, the config file is *not* a simple json file, it should be a common js (a.k.a. npm) module.
You might recognize this way of working from the karma test runner.

Between the config file and your command line options, you should *at least* specify `files` (or `-f`) and the `testRunner` options.

## Supported mutators
The mutators that are supported by Stryker can be found on [our website](http://stryker-mutator.github.io/mutators.html)

## Configuration
All options can be configured either via the command line or via a config file.

Both `files` and `mutate` support globbing expressions using [node glob](https://github.com/isaacs/node-glob). This is the same globbing format you might know from
[Grunt](https://github.com/gruntjs/grunt) and [Karma](https://github.com/karma-runner/karma).

#### Files
**Command line:** `--files node_modules/a-lib/**/*.js,src/**/*.js,a.js,test/**/*.js` or `-f node_modules/a-lib/**/*.js,src/**/*.js,a.js,test/**/*.js`
Expand Down
2 changes: 1 addition & 1 deletion bin/stryker
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

'use strict';

process.title = 'grunt';
process.title = 'stryker';

// Run the TypeScript compiled stryker-cli.js
require('../src/stryker-cli');
2 changes: 1 addition & 1 deletion src/ConfigReader.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ export var CONFIG_SYNTAX_HELP = ' module.exports = function(config) {\n' +
' config.set({\n' +
' // your config\n' +
' });\n' +
' };\n';
' };';

const log = log4js.getLogger('ConfigReader');

Expand Down
44 changes: 31 additions & 13 deletions src/stryker-cli.ts
Original file line number Diff line number Diff line change
@@ -1,33 +1,38 @@
const program = require('commander');
import {CONFIG_SYNTAX_HELP} from './ConfigReader';
import { CONFIG_SYNTAX_HELP } from './ConfigReader';
import Stryker from './Stryker';
import * as log4js from 'log4js';

const log = log4js.getLogger('stryker-cli');
let command: string, strykerConfig: string;

function list(val: string) {
return val.split(',');
}
program
.usage('-f <files> -m <filesToMutate> -c <configFileLocation> [other options]')
.description('Starts the stryker mutation testing process. Required arguments are --files, --testFramework and --testRunner. You can use globbing expressions to target multiple files. See https://github.com/isaacs/node-glob#glob-primer for more information about the globbing syntax.')
.version(require('../package.json').version)
.usage('<command> [options] [stryker.conf.js]')
.description(`Possible commands:
run: Run mutation testing
Optional location to the stryker.conf.js file as last argument. That file should export a function which accepts a "config" object\n${CONFIG_SYNTAX_HELP}`)
.arguments('<command> [stryker.conf.js]')
.action((cmd: string, config: string) => {
command = cmd;
strykerConfig = config;
})
.option('-f, --files <allFiles>', `A comma seperated list of globbing expression used for selecting all files needed to run the tests. For a more detailed way of selecting inputfiles, please use a configFile.
Example: node_modules/a-lib/**/*.js,src/**/*.js,a.js,test/**/*.js`, list)
.option('-m, --mutate <filesToMutate>', `A comma seperated list of globbing expression used for selecting the files that should be mutated.
Example: src/**/*.js,a.js`, list)
.option('-f, --files <allFiles>', `A comma seperated list of globbing expression used for selecting all files needed to run the tests. These include library files, test files and files to mutate, but should NOT include test framework files (for example jasmine). For a more detailed way of selecting inputfiles, please use a configFile.
Example: node_modules/a-lib/**/*.js,src/**/*.js,a.js,test/**/*.js`, list)
.option('--coverageAnalysis <perTest|all|off>', `The coverage analysis strategy you want to use. Default value: "perTest"
* "off": Stryker will not determine the covered code during the initial test run fase. All tests are always tested for each mutant during the mutation testing fase.
* "all": Stryker will determine the covered code of all tests during the initial test run fase. Only mutants that are actually covered by your test suite are tested during the mutation testing fase.
* "perTest": Stryker will determine the covered code per executed test during the initial test run fase. Only mutants that are actually covered by your test suite are tested during the mutation testing fase. Only those tests that cover the mutant are tested per mutant.`)
.option('--coverageAnalysis <perTest|all|off>', `The coverage analysis strategy you want to use. Default value: "perTest"`)
.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('--reporter <name>', 'A comma separated list of the names of the reporter(s) you want to use', list)
.option('--port <n>', 'A free port for the test runner to use (if it needs to). Any additional test runners will be spawned using n+1, n+2, etc', parseInt)
.option('--timeoutMs <number>', 'Tweak the absolute timeout used to wait for a test runner to complete', parseInt)
.option('--timeoutFactor <number>', 'Tweak the standard deviation relative to the normal test run of a mutated test', parseFloat)
.option('--plugins <listOfPlugins>', 'A list of plugins you want stryker to load (`require`).', list)
.option('-c, --configFile <configFileLocation>', 'A location to a config file. That file should export a function which accepts a "config" object\n' +
CONFIG_SYNTAX_HELP)
.option('--logLevel <level>', 'Set the log4js loglevel. Possible values: fatal, error, warn, info, debug, trace, all and off. Default is "info"')
.parse(process.argv);

Expand All @@ -37,12 +42,25 @@ log4js.setGlobalLogLevel(program['logLevel'] || 'info');
delete program.options;
delete program.rawArgs;
delete program.args;
delete program.Command;
delete program.Option;
delete program.commands;
for (let i in program) {
if (i.charAt(0) === '_') {
delete program[i];
}
}

new Stryker(program).runMutationTest()
.catch(err => log.error(`an error occurred`, err));
if (strykerConfig) {
program.configFile = strykerConfig;
}

const commands: { [cmd: string]: () => void } = {
run: () => new Stryker(program).runMutationTest().catch(err => log.error(`an error occurred`, err))
};

if (Object.keys(commands).indexOf(command) >= 0) {
commands[command]();
} else {
log.error('Unknown command: "%s", supported commands: [%s], or use `stryker --help`.', command, Object.keys(commands));
}
3 changes: 1 addition & 2 deletions test/integration/config-reader/ConfigReaderSpec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -90,8 +90,7 @@ describe('ConfigReader', () => {
config.set({
// your config
});
};
`);
};`);
});

it('should exit with 1', () => {
Expand Down
2 changes: 1 addition & 1 deletion testResources/module/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
"main": "index.js",
"scripts": {
"tsc": "tsc",
"stryker:config": "stryker --configFile stryker.conf.js"
"stryker:config": "stryker run stryker.conf.js"
},
"author": "",
"license": "ISC",
Expand Down

0 comments on commit fd824de

Please sign in to comment.