Detecting Environment When Running Karma - karma-runner

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

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);

Error : You need to include some adapter that implements __karma__.start method

I'm trying to run unit tests using karma and i'm getting the error You need to include some adapter that implements __karma__.start method!. I tried running with grunt and karma start commands. I did googling and all the solutions didn't work out. Not sure what i'm doing wrong. I included the right adapter which comes with karma-jasmine, which has the __karma__.start method, under plugins in karma.conf.js file. Here's my configuration file :-
module.exports = function(config){
config.set({
// root path location that will be used to resolve all relative paths in files and exclude sections
basePath : '../',
files : [
'bower_components/angular/angular.js',
'bower_components/angular-mocks/angular-mocks.js',
'node_modules/requirejs/require.js',
'node_modules/karma-jasmine/lib/adapter.js',
'app.js',
'mainapp/mainapp.js',
'mainapp/notes/notes.js',
'mainapp/notes/partial/create/create.js',
'mainapp/notes/partial/create/create-spec.js'
],
// files to exclude
exclude: [
'bower_components/angular/angular/*.min.js'
],
// karma has its own autoWatch feature but Grunt watch can also do this
autoWatch : false,
// testing framework, be sure to install the correct karma plugin
frameworks: ['jasmine', 'browserify', 'requirejs'],
// browsers to test against, be sure to install the correct browser launcher plugins
browsers : ['PhantomJS'],
// map of preprocessors that is used mostly for plugins
preprocessors: {
'mainapp/notes/partial/create/create-spec.js' : ['browserify']
},
reporters: ['progress'],
// list of karma plugins
plugins : [
'karma-teamcity-reporter',
'karma-chrome-launcher',
'karma-phantomjs-launcher',
'karma-babel-preprocessor',
'karma-requirejs',
'karma-jasmine',
'karma-browserify'
],
singleRun: true
})}
Using the requirejs framework turns off the automatic calling of __karma__.start. You need to create a file that a) configures RequireJS and b) calls __karma__.start to kick of the tests. Here's an example. It scans through the files that Karma is serving to find the files that contains tests. This is based on a naming convention that any file that ends with spec.js or test.js is a test file. It converts the file names to module names. It then configures RequireJS. One thing it does is pass all the test modules as deps so that all test modules are loaded right away. It sets __karma__.start as callback so that when all modules passed in deps are loaded, the tests start.
var allTestFiles = [];
var TEST_REGEXP = /(spec|test)\.js$/i;
Object.keys(window.__karma__.files).forEach(function(file) {
if (TEST_REGEXP.test(file)) {
// Normalize paths to RequireJS module names.
allTestFiles.push(file);
}
});
require.config({
baseUrl: '/base',
paths: {
'chai': 'node_modules/chai/chai',
'chai-jquery': 'node_modules/chai-jquery/chai-jquery',
'jquery': 'node_modules/jquery/dist/jquery.min',
'underscore': '//cdnjs.cloudflare.com/ajax/libs/underscore.js/1.6.0/underscore-min',
'sn/sn-underscore': 'static/scripts/sn/sn-underscore',
'vendor/jquery-ui': '//cdnjs.cloudflare.com/ajax/libs/jqueryui/1.11.4/jquery-ui.min'
},
deps: allTestFiles,
callback: window.__karma__.start
});
You need to include this file in your files parameter in your karma.conf.js file. Since you use the requirejs framework, you just need to put it first in the list. For instance, if you call the file test-main.js (as suggested in Karma's documentation):
files: [
'test-main.js',
...
]
If you load RequireJS yourself by listing it in files, you need to put test-main.js after RequireJS.

Karma angular testing failed to instantiate module

I am just starting to set up some tests with Karma. I some tests working with jdDom, but did not like how it was configuring. However, I am not sure how to point to the js files correctly. As I am getting this error
Error: [$injector:modulerr] Failed to instantiate module ha.module.utility due to:
Error: [$injector:nomod] Module 'ha.module.utility' is not available! You either misspelled the module name or forgot to load it. If registering a module ensure that you specify the dependencies as the second argument.
I started a file with jsdom that required the core modules
require('../../../src/modules/core/module.core.built.js');
require('../../../src/modules/utility/module.utility.built.js');
These scripts are where my modules reside. I am not sure where to put them in the karma file. Or if this is even the issue . Here is my karma file below. I removed the comments that come with karma init so it could be quicker to read on this post.
config.set({
// base path that will be used to resolve all patterns (eg. files, exclude)
basePath: 'Scripts/',
frameworks: ['jasmine'],
// list of files / patterns to load in the browser
files: [
'jquery /jquery libraries ',
'../node_modules/angular/angular.js',
'../node_modules/angular-mocks/angular-mocks.js',
'test2/*.js',
'tests/**/*.js'
],
exclude: [
'tests/old/**',
'tests/**/*.setup.js'
],
// preprocess matching files before serving them to the browser
// available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor
preprocessors: {
'../Templates/**/*.html' : ['ng-html2js']
},
ngHtml2JsPreprocessor: {
// setting this option will create only a single module that contains templates
// from all the files, so you can load them all with angular.mock.module('foo')
//stripPrefix: "Templates/",
//prependPrefix: "Templates/",
moduleName: 'templates'
},
// available reporters: https://npmjs.org/browse/keyword/karma-reporter
reporters: ['progress'],
port: 9876,
colors: true,
logLevel: config.LOG_INFO,
autoWatch: true,
browsers: ['Chrome'],
singleRun: true,
concurrency: Infinity
Basically I need these tests to find the modules.
Your modules' directives, controllers, and all other required files should be uploaded into your list of "files," like this:
files: [
'../node_modules/angular/angular.js',
'../node_modules/angular-mocks/angular-mocks.js',
'../../../src/modules/core/module.core.built.js',
'../../../src/modules/utility/module.utility.built.js',
'test2/*.js',
'tests/**/*.js'
],

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.

How do I run only certain tests in karma?

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.