Karma run single test

Karma Runner

Karma Runner Problem Overview


I use karma to run tests. I have many tests and running all tests is a very slow process. I want to run only a single test in order to spend less time, because all tests are run about 10 minutes.

Is it possible?

Karma Runner Solutions


Solution 1 - Karma Runner

If you are using the Karma/Jasmine stack, use:

fdescribe("when ...", function () { // to [f]ocus on a single group of tests
  fit("should ...", function () {...}); // to [f]ocus on a single test case
});

... and:

xdescribe("when ...", function () { // to e[x]clude a group of tests
  xit("should ...", function () {...}); // to e[x]clude a test case
});

When you're on Karma/Mocha:

describe.only("when ...", function () { // to run [only] this group of tests
  it.only("should ...", function () {...}); // to run [only] this test case
});

... and:

describe.skip("when ...", function () { // to [skip] running this group of tests
  it.skip("should ...", function () {...}); // to [skip] running this test case
});

Solution 2 - Karma Runner

Update: karma has changed.

Now use fit() and fdescribe()

f stands for focused!

Solution 3 - Karma Runner

For Angular users!

I know two ways:

  1. Visual Studio Code Extension:

The easiest way is to use the vscode-test-explorer extension along with its child angular-karma-test-explorer and jasmine-test-adapter, you'll get a list of current test to run one by one if you want:

enter image description here

  1. Directly modify test.ts

For me, i wasn't able to use the extension way because of this bug, and so i ended up modifying the test.ts file (as stated here by Shashi), just to consolidate that answer here, by default context looks like this:

const context = require.context('./', true, /\.spec\.ts$/);

You should modify it's RegExp to match the files that you'r willing to test, for example if you want to test a single file named "my.single.file.custom.name.spec.ts" it'll look this way:

const context = require.context('./', true, /my\.single\.file\.custom\.name\.spec\.ts$/);

For more details about require parameters you may find it here at their wiki.

  1. Karma runner improvement

Currently there's an open issue to improve their current behaviour, you can follow their progress at their github page (https://github.com/karma-runner/karma/issues/1507).

Solution 4 - Karma Runner

a) You can pass a pattern that describes your single file as command line argument to the karma start command:

# build and run all tests
$ karma start

# build and run only those tests that are in this dir
$ karma start --grep app/modules/sidebar/tests

# build and run only this test file
$ karma start --grep app/modules/sidebar/tests/animation_test.js

Source: https://gist.github.com/KidkArolis/fd5c0da60a5b748d54b2

b) You can use a Gulp (or Grunt ect.) task that starts Karma for you. This gives you more flexibility on how to execute Karma. You are for example able to pass custom command line arguments to those tasks. This strategy is also useful if you want to implement a watch mode that only executes the changed tests. (The Karma watch mode would execute all tests.) Another use case would be to only execute tests for files with local changes before you do a commit. Also see Gulp examples below.

c) If you use VisualStudio, you might want to add an external tool command to the context menu of the solution explorer. This way, you can start the test from that context menu instead of using the console. Also see

https://stackoverflow.com/questions/45321194/how-to-execute-custom-file-specific-command-task-in-visual-studio

Example Gulp file

//This gulp file is used to execute the Karma test runner
//Several tasks are available, providing different work flows
//for using Karma. 

var gulp = require('gulp');
var karma = require('karma');
var KarmaServerConstructor = karma.Server;
var karmaStopper = karma.stopper;
var watch = require('gulp-watch');
var commandLineArguments = require('yargs').argv;
var svn = require('gulp-svn');
var exec = require('child_process').exec;
var fs = require('fs');

//Executes all tests, based on the specifications in karma.conf.js
//Example usage: gulp all
gulp.task('all', function (done) {
    var karmaOptions = { configFile: __dirname + '/karma.conf.js' };
    var karmaServer = new KarmaServerConstructor(karmaOptions, done);
    karmaServer.on('browsers_change', stopServerIfAllBrowsersAreClosed); //for a full list of events see http://karma-runner.github.io/1.0/dev/public-api.html
    karmaServer.start();   
});

//Executes only one test which has to be passed as command line argument --filePath
//The option --browser also has to be passed as command line argument.
//Example usage:  gulp single --browser="Chrome_With_Saved_DevTools_Settings" --filePath="C:\myTest.spec.js"
gulp.task('single', function (done) {     

    var filePath = commandLineArguments.filePath.replace(/\\/g, "/");

    var karmaOptions = {
        configFile: __dirname + '/karma.conf.js',
        action: 'start',        
        browsers: [commandLineArguments.browser],       
        files: [
            './Leen.Managementsystem/bower_components/jquery/dist/jquery.js',
            './Leen.Managementsystem/bower_components/globalize/lib/globalize.js',
            { pattern: './Leen.Managementsystem/bower_components/**/*.js', included: false },
            { pattern: './Leen.Managementsystem.Tests/App/test/mockFactory.js', included: false },
            { pattern: './Leen.Managementsystem/App/**/*.js', included: false },
            { pattern: './Leen.Managementsystem.Tests/App/test/*.js', included: false },
            { pattern: filePath, included: false },
            './Leen.Managementsystem.Tests/App/test-main.js',
            './switchKarmaToDebugTab.js' //also see https://stackoverflow.com/questions/33023535/open-karma-debug-html-page-on-startup
        ]
    };

    var karmaServer = new KarmaServerConstructor(karmaOptions, done);   
    karmaServer.on('browsers_change', stopServerIfAllBrowsersAreClosed);
    karmaServer.start();     
});

//Starts a watch mode for all *.spec.js files. Executes a test whenever it is saved with changes. 
//The original Karma watch mode would execute all tests. This watch mode only executes the changed test.
//Example usage:  gulp watch 
gulp.task('watch', function () {

    return gulp //
        .watch('Leen.Managementsystem.Tests/App/**/*.spec.js', handleFileChanged)
        .on('error', handleGulpError);

    function handleFileChange(vinyl) {

        var pathForChangedFile = "./" + vinyl.replace(/\\/g, "/");

        var karmaOptions = {
            configFile: __dirname + '/karma.conf.js',
            action: 'start',
            browsers: ['PhantomJS'],
            singleRun: true,
            files: [
                    './Leen.Managementsystem/bower_components/jquery/dist/jquery.js',
                    './Leen.Managementsystem/bower_components/globalize/lib/globalize.js',
                    { pattern: './Leen.Managementsystem/bower_components/**/*.js', included: false },
                    { pattern: './Leen.Managementsystem.Tests/App/test/mockFactory.js', included: false },
                    { pattern: './Leen.Managementsystem/App/**/*.js', included: false },
                    { pattern: './Leen.Managementsystem.Tests/App/test/*.js', included: false },
                    { pattern: pathForChangedFile, included: false },
                    './Leen.Managementsystem.Tests/App/test-main.js'
            ]
        };

        var karmaServer = new KarmaServerConstructor(karmaOptions);
        karmaServer.start();

    }

});

//Executes only tests for files that have local changes
//The option --browser has to be passed as command line arguments.
//Example usage:  gulp localChanges --browser="Chrome_With_Saved_DevTools_Settings"
gulp.task('localChanges', function (done) {   
       
    exec('svn status -u --quiet --xml', handleSvnStatusOutput);

    function handleSvnStatusOutput(error, stdout, stderr) {

        if (error) {
            throw error;
        }
       
        var changedJsFiles = getJavaScriptFiles(stdout);   
        var specFiles = getSpecFiles(changedJsFiles);


        if(specFiles.length>0){
            console.log('--- Following tests need to be executed for changed files: ---');
            specFiles.forEach(function (file) {
                console.log(file);
            });
            console.log('--------------------------------------------------------------');
        } else{
            console.log('Finsihed: No modified files need to be tested.');
            return;
        }

        var files = [
                './Leen.Managementsystem/bower_components/jquery/dist/jquery.js',
                './Leen.Managementsystem/bower_components/globalize/lib/globalize.js',
                { pattern: './Leen.Managementsystem/bower_components/**/*.js', included: false },
                { pattern: './Leen.Managementsystem.Tests/App/test/mockFactory.js', included: false },
                { pattern: './Leen.Managementsystem/App/**/*.js', included: false },
                { pattern: './Leen.Managementsystem.Tests/App/test/*.js', included: false }];

        specFiles.forEach(function (file) {
            var pathForChangedFile = "./" + file.replace(/\\/g, "/");
            files = files.concat([{ pattern: pathForChangedFile, included: false }]);
        });

        files = files.concat([ //
            './Leen.Managementsystem.Tests/App/test-main.js', //
            './switchKarmaToDebugTab.js'
        ]);

        var karmaOptions = {
            configFile: __dirname + '/karma.conf.js',
            action: 'start',
            singleRun: false,
            browsers: [commandLineArguments.browser],
            files: files              
        };

        var karmaServer = new KarmaServerConstructor(karmaOptions, done);
        karmaServer.on('browsers_change', stopServerIfAllBrowsersAreClosed);
        karmaServer.start();
    }  
    

});

function getJavaScriptFiles(stdout) {
    var jsFiles = [];

    var lines = stdout.toString().split('\n');
    lines.forEach(function (line) {
        if (line.includes('js">')) {
            var filePath = line.substring(9, line.length - 3);
            jsFiles.push(filePath);
        }
    });
    return jsFiles;
}

function getSpecFiles(jsFiles) {

    var specFiles = [];
    jsFiles.forEach(function (file) {

        if (file.endsWith('.spec.js')) {
            specFiles.push(file);
        } else {
            if (file.startsWith('Leen\.Managementsystem')) {
                var specFile = file.replace('Leen\.Managementsystem\\', 'Leen.Managementsystem.Tests\\').replace('\.js', '.spec.js');
                if (fs.existsSync(specFile)) {
                    specFiles.push(specFile);
                } else {
                    console.error('Missing test: ' + specFile);
                }
            }
        }
    });
    return specFiles;
}

function stopServerIfAllBrowsersAreClosed(browsers) {
    if (browsers.length === 0) {
        karmaStopper.stop();
    }
}

function handleGulpError(error) {
  

  throw error;
}

Example settings for ExternalToolCommand in VisualStudio:

> Title: Run Karma using Chrome > > Command: cmd.exe > > Arguments: /c gulp single > --browser="Chrome_With_Saved_DevTools_Settings" --filePath=$(ItemPath) > > Initial directory: $(SolutionDir) > > Use Output window: true

Solution 5 - Karma Runner

If you want to run karma test with angular, You just need to modify your test.ts file.

Find line const context = require.context('./', true, /\.spec\.ts$/);

If you want to run your.component.spec.ts modify line to: const context = require.context('./', true, /your\.component\.spec\.ts$/);

Solution 6 - Karma Runner

Changing it() to iit() should work for running single test. Also, similar, for describe() block we can use ddescribe()

Solution 7 - Karma Runner

Change your karma conf to only include the test you want to run instead of a full directory.

Inside the files : [...]

You might want to comment the preprocessors if you need/want to debug your test in chrome to avoid having your js minified.

Solution 8 - Karma Runner

Yes, this is an old thread.

The following situation has occurred on me 2 - 3 times now in the past few years. More so when I haven't done much unit testing and have come back to it.

I started up my Karma and found the tests, after initial start up, should have completed within 1 second to now take 20 seconds. Additionally, attempting to debug the unit tests within Chrome became tediously slow. The network tab showed all the files taking 2 - 3 seconds per file.

Solution: I didn't realize Fiddler was open. Close it and restart your tests.

Solution 9 - Karma Runner

Answer proposal for special Angular/IE case: The only thing that worked so far for me using "karma-ie-launcher", in order to run IE as browser, was modifying "include" property of tsconfig.spec.json to explicitly reference target test file using universal qualified path and not globs e.g. "C:\filepath\my-test.spec.ts", for compilation purposes. "In addition" the test.ts file should be appropriately amended to target said file for test file limitation purposes. Be aware that the cache will need to be initially deleted in IE for this scheme to take effect.

(For Angular/Chrome case modification of test.ts alone would be sufficient.)

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
Questionuser3730696View Question on Stackoverflow
Solution 1 - Karma RunnerDan K.K.View Answer on Stackoverflow
Solution 2 - Karma RunnerbrendanView Answer on Stackoverflow
Solution 3 - Karma Runnerluiscla27View Answer on Stackoverflow
Solution 4 - Karma RunnerStefanView Answer on Stackoverflow
Solution 5 - Karma RunnerShashi RanjanView Answer on Stackoverflow
Solution 6 - Karma Runnerstanislav.chetvertkovView Answer on Stackoverflow
Solution 7 - Karma RunnerRonan QuillevereView Answer on Stackoverflow
Solution 8 - Karma RunnerEsaithView Answer on Stackoverflow
Solution 9 - Karma RunnerKieran RyanView Answer on Stackoverflow