How do I run only certain tests in karma? - karma-runner

I have karma config set up correctly, config file, running in the background, just great. As soon as I change and save a file, it reruns the tests.... all 750 of the unit tests. I want to be able to run just a few. Short of manually hacking the config file or commenting out hundreds of tests across many files, is there any easy way to do it?
E.g. when running command line server tests using say mocha, I just use regexp: mocha -g 'only tests that I want'. Makes it much easier to debug and quickly check.

So now I feel foolish. mocha supports a very narrow version of regexp matching.
This runs all tests
describe('all tests',function(){
describe('first tests',function(){
});
describe('second tests',function(){
});
});
This runs just 'first tests'
describe('all tests',function(){
describe.only('first tests',function(){
});
describe('second tests',function(){
});
});
You can also do it.only()
I should have noticed that. Sigh.

You can do that at karma startup time unfortunately, not at runtime.
If you want to change it dynamically you have to put some more effort.
Say you want to focus on a specific set/suite of tests from the beginning, on the karma-mocha plugin page there's this snippet of code to do what you want:
module.exports = function(config) {
config.set({
// karma configuration here
...
// this is a mocha configuration object
client: {
// The pattern string will be passed to mocha
args: ['--grep', '<pattern>'],
...
}
});
};
In order to make the <pattern> parametric you have to wrap the configuration file in a Configurator that will listen CLI and customize the karma configuration for you.
Have a look to this SO answer to know how to setup a very simple Configurator.

I have same question and this is my workround by a little change on karma.conf.js.
In fact, take an argument from command line and modify the pattern in "files".
I use minimist to parse the argument list.
In config file:
/* Begin */
var minimist = require('minimist');
var argv = minimist(process.argv);
var testBase="test/unit";
var testExt=".spec.js";
var unitTestPattern = testBase+'/**/*'+testExt;
if ("test" in argv){
unitTestPattern = testBase+"/"+argv["test"]+testExt;
}
/* End */
module.exports = function(config){
config.set({
//....
files : [
//....
unitTestPattern, //place here
// 'test/unit/**/*.spec.js', //replace this
//....
],
//....
});
};
run in command prompt:
karma start test/karma.conf.js --single-run --test #TEST_CASE_FILE#

a nice extension that can help here is karma-jasmine-html-reporter-livereload
https://www.npmjs.com/package/karma-jasmine-html-reporter-livereload
or karma-jasmine-html-reporter https://www.npmjs.com/package/karma-jasmine-html-reporter?__hstc=72727564.86845f057bb4d741f59d578059e30644.1443860954685.1453095135802.1453138187458.37&__hssc=72727564.1.1453138187458&__hsfp=2285154675
It creates a debug page in which you can run each test individually. very useful for large projects!

1) In your karma.conf.js get the params from the terminal:
var files = (process.env.npm_config_single_file) ? process.env.npm_config_single_file : 'test/test_index.js';
2) In order to run a single test you will need to set an option object with all your configuration (Without files and preprocessors):
var option = {
webpack: {
// webpack configuration
},
// more configuration......
};
3) Set your files path and preprocessors:
option.files = [
{pattern: files, watch: false}
];
option.preprocessors = {};
option.preprocessors[files] = [ 'webpack', 'sourcemap' ];
// call config.set function
config.set(option);
4) Run in the terminal:
npm test --single_file=**/my-specific-file-spec.js
For more information check this PR:
https://github.com/webpack/karma-webpack/pull/178

There are different ways to do it.
Use --grep option. The disadvantage of this is that all the tests are preprocessed before running the specific test suite.
Use .only method. Disadvantage same as no. 1. Using both 1 and 2 method my node process used to crash often saying out of memory.
Limit the files options for processing. This is super fast.
Limit preprocessing to certain folder like Unit or Integration folder.
For this I have used custom cli option --only and in the karma config
const modules = config.only;
and in the the files pattern
files: typeof modules === 'string ? '[`tests/**/${module}/**/*.(test|spec).js`]: 'tests/**/*.(test|spec).js'
Advantage: Developers can run only certain tests when they make a small change way faster by limiting in the preprocessing phase.
You can also use combination of no.3 and no.1 or 2.

Related

How to run multiple feature files in sequence using Cucumber + protractor

I want to run feature files in a desired order or sequence, for example:
tags:"`#ProtractorScenario` or #CucumberScenario"
But cucumber scenario is getting executed first. Can someone guide me on this?
Note: Cucumber is executing scenario based on alphabetical order of feature file in folder
Also, in cases with more than 50+ feature files, what would be the best way to define sequencing of cucumber feature files?
In order to have reliable tests, your tests should be independent and not rely on the order they are run in. The reason being that your test shouldn't depend on the system being in a certain state, as this will lead to flaky tests. Each of your tests should set up the expected state (and teardown!), so they can be run independently.
Below is how protractor executes cucumber feature files:
Protractor finds out all feature files specified in specs, save the absolute file path into an array, let's call it feature_list.
Protractor starts a session (start a browser instance)
Protractor generates a Cucumber CLI as below, and execute the CLI to hand over the running control cucumber:
./node_modules/bin/cucumber --require xxx --format xxx feature1,feature2,....featureN
feature1,feature2,....featureN calculated by feature_list.join(',')
From above, we can learn the only opportunity to change the order
is given an order-done feature_list to protractor specs.
Note: every member of the feature_list should be absolute/relative
path of single feature file. folder and wildcard are not recommended to appear in the path.
You can get a solution code from my github: spec.filter.js, which implements:
filter feature file by cucumberOpts.tags
order filter result of above step 1 by priority
Guide to use spec.filter.js:
// protractor conf file
const specFilter = require('./spec.filter.js');
var config = {
seleniumAddress: 'xxxxx',
capabilities:'xxxx',
framework: 'custom',
frameworkPath: require.resolve('protractor-cucumber-framework'),
ignoreUncaughtExceptions: true,
specs: [
'./aa/**/*.feature',
'./bb/**/*.feature'
],
cucumberOpts: {
require: [
'xxx'
],
priorities: {
// feature has tag #SPGC-21542 or #SPGC-21944 or #SPGC-21946
// will has priority 1
'1': ['#SPGC-21542 or #SPGC-21944', '#SPGC-21946'],
// feature has tag #SPGC-22055 will has priority 2,
// feature has heighest priority will put ahead at
// the `specs` list and get executed firstly.
'2': ['#SPGC-22055']
}
tags: ""
}
....
};
exports.config = specFilter(config);

Karma check build environment

In the karma.conf.js you can set what browsers to use e.g. :
browsers: [
"Chrome",
"Firefox",
"IE"
],
Is there anyway in this configuration file to see what the build environment is e.g. Windows or Linux and then only run the tests in the appropriate browsers.
I basically don't want to have to keep changing the config file for karma every time I switch a OS.
After looking into Node.js I found out that you can get the operating system with the following call:
var os = require("os");
With the os variable I was then able to do simple if/else statements with os.type:
if(os.type()==='Linux')
I would then assign the appropriate browser options to the browser array in the config object.
browsers = ["Chrome","Firefox"];
All this logic was done inside the Karam.conf.js file but before the module.exports = function() call.

How to run particular protractor test case from command prompt

I am successfully able to run the protractor scripts. Below is the protractor.config.js file which I am using to run the protractor scripts.
var Jasmine2Reporter = require('protractor-jasmine2-screenshot-reporter');
var HtmlReporter = require('protractor-html-screenshot-reporter');
var jReporter=new Jasmine2Reporter({
dest: './protractor-result',
fileName: 'protractor-demo-tests-report.html'
});
var reporter=new HtmlReporter({
baseDirectory: './protractor-result', // a location to store screen shots.
docTitle: 'Protractor Demo Reporter',
docName: 'protractor-demo-tests-report.html'
});
exports.config = {
allScriptsTimeout: 11000,
specs: [
'testCaseOne.spec.js' // Hardcoded to run single script.
'*.spec.js' // to run all scripts.
],
capabilities: {
'browserName': 'chrome'
},
baseUrl: 'http://localhost:8000/app/',
framework: 'jasmine2',
};
I am successfully able to run the protractor scripts. Below is the protractor.config.js file which I am using to run the protractor scripts
To run above file, I used below command.
$ npm run protractor
My Expectation:
Now, I would like to run the single protractor script from command prompt. How this can be achieved? This will be useful when I will try to run the protractor test cases from any test management tool.
Can anyone please help me on this.
Try this:
protractor protractor.conf.js --specs='specs/run-just-this-spec.js'
If you want to run a specific test you need use jasmine2 and pass the grep option. https://github.com/angular/protractor/blob/19139272d190dd9c1888d9c3fc2f480f7c6c8edb/docs/jasmine-upgrade.md
Additionally to the given answers, you can use suites, which are sets of specs:
You can have suites which consist only of one spec.
You can run particular spec like this:
protractor --suite=my-suite-name
Also you can temporarily exclude suite or spec in Jasmine using xdescribe and xit (just type x before describe or it).
Also you can focus on particular suite or spec in Jasmin using fdescribe and fit (just type f before describe or it).
Use the node.js process.env object.
var w00t = process.env.TESTED || '*';
exports.config = {
allScriptsTimeout: 11000,
specs: [
w00t + '.spec.js'
],
Prepend TESTED=testCaseOn when you start protractor to execute the desired spec. To execute all scripts add nothing so that *.spec.js will be called.

Detecting Environment When Running Karma

I have two environments I'm running my tests in (locally, and travic ci). And I need to make a few tweaks in my tests if I'm running them locally.
Is it possible to do it using Karma without having two separate configuration files?
You can programmatically call karma and pass it a configuration object, then listen the callback to close the server:
karma.server.start(config, function (exitCode){
if(exitCode){
console.err('Error in somewhere!');
}
});
The config object is basically an object that contains some properties and you can use it to enrich a skeleton configuration file you already have.
Imagine to have a configuration file like the following in 'path/to/karma.conf.js':
// Karma configuration
module.exports = function(config) {
config.set({
// base path, that will be used to resolve files and exclude
basePath: '../',
// frameworks to use
frameworks: ['mocha'],
files: [ ... ].
// test results reporter to use
// possible values: 'dots', 'progress', 'junit', 'growl', 'coverage'
// choose it before starting Karma
// web server port
port: 9876,
// enable / disable colors in the output (reporters and logs)
colors: true,
// enable / disable watching file and executing tests whenever any file changes
autoWatch: false,
browsers: ['PhantomJS'],
// If browser does not capture in given timeout [ms], kill it
captureTimeout: 60000,
// Continuous Integration mode
// if true, it capture browsers, run tests and exit
singleRun: true,
plugins: [
'karma-mocha',
'karma-phantomjs-launcher'
]
});
};
Now I want to tweak it a bit before starting karma:
function enrichConfig(path){
var moreConfig = {
// say you want to overwrite/choose the reporter
reporters: ['progress'],
// put here the path for your skeleton configuration file
configFile: path
};
return moreConfig;
}
var config = enrichConfig('../path/to/karma.conf.js');
Currently with this technique we're generating several configuration for all our environment.
I guess you can configure your TravisCI configuration file to pass some arguments to the wrapper in order to activate some particular property in the enrichConfig function.
Update
If you want to pass parameters (e.g. the configuration file path) to your script, then just look up in the arguments array to pick it up.
Assume your script above it saved in a startKarma.js file, change your code to this:
var args = process.argv;
// the first two arguments are 'node' and 'startKarma.js'
var pathToConfig = args[2];
var config = enrichConfig(pathToConfig);
then:
$ node startKarma.js ../path/to/karma.conf.js

Karma command line doesn't display test results after adding code coverage

I'm using Karma to do some unit testing and to generate code coverage stats.
When i run the test from the command line without the code coverage settings in the karma config i can see the test results in the command line. i.e
Executed 3 of 3 SUCCESS (0.465 secs / 0.048 secs)
When I add the code coverage settings to the config and run the test, the coverage files get generated but i do not see the test results in the command line.
My config is:
basePath = '../';
files = [
JASMINE,
JASMINE_ADAPTER,
'https://ajax.googleapis.com/ajax/libs/angularjs/1.0.1/angular.min.js',
'app/lib/angular/angular.js',
'app/lib/angular/angular-scenario.js',
'test/lib/angular/angular-mocks.js',
'app.js', // include app first as other module hang off it
'public/javascript/**/*.js',
'test/unit/**/*.js'
];
/* code coverage settings */
preprocessors = {
'**/public/javascript/**/*.js': 'coverage'
};
reporters = ['coverage'];
/* end code coverage settings */
autoWatch = true;
browsers = ['Chrome'];
junitReporter = {
outputFile: 'test_out/unit.xml',
suite: 'unit'
};
I could just create separate scripts to generate the code coverage and run the tests, and my be better off doing that in terms of speed etc, but I wanted to know if I could do them together, and if so have I miss configured something?
When you added the "coverage" reporter in your config it seems you removed the "progress" reporter that used to be there by default.
Just change the reporters part of your config to:reporters = ['coverage','progress'] instead of reporters = ['coverage']