I have the test in my node application...
it('will call done', function(done) {
myObj.fn(function(){
done();
}
});
and the code....
myObj.fn = function(success){
setTimeout(2000000000,success);
}
When I run the test I get this in the output...
-MacBook-Pro:torus-pqdata user$ npm test
> torus-pqdata#0.0.0 test /Stuff/code bases/2015/torus-pqdata
> jasmine-node specs/
However as you can see the unit test just exits without failing but I need it to timeout (I am trying to simulate something hanging). How do I get it to timeout?
Swap the arguments in setTimeout:
myObj.fn = function(success){
setTimeout(success, 200000000);
}
Here's some reference from MDN: https://developer.mozilla.org/en-US/docs/Web/API/WindowTimers/setTimeout
Related
I am creating a test suite that will be run by mocha. In the test, I plan on using should and chai at the very least. I am testing JSON objects. I want mocha to be silent about successful tests and I want to control what the errors look like at the end of the run. Right now, there is a lot of red text describing the JSON object and other information. What I want is to override the output.
Here is an example test for an element in the JSON object which I would import from testData.
var should = require("should");
var chai = require("chai");
var expect = chai.expect;
const testData = require("./testData");
for (t of testData.data) {
describe("This will fail", function() {
it("Should have a zipperNut",function(done) {
t.should.have.property('zipperNut');
done();
});
});
}
What I want is to see just this:
$ mocha testSuite.js
zipperNut
$
And so on for all the tests I want to run. Can I do this? Do I need to use a different library?
Mocha's output is determined by something called a "default reporter". If you want to change the output you can specify a different reporter, which is presumably available through npm or similar. To specify a new custom reporter you do this:
$ mocha --reporter my-reporter.js
Where my-reporter.js is the file containing my "reporter". For me, I just want the plain name of the failing tests, so my reporter would look like:
'use strict';
const Mocha = require('mocha');
const {
EVENT_RUN_END,
EVENT_TEST_FAIL,
} = Mocha.Runner.constants;
class MyReporter {
constructor(runner) {
const stats = runner.stats;
runner
.on(EVENT_TEST_FAIL, (test, err) => {
console.log(
`${test.title}`
);
})
.once(EVENT_RUN_END, () => {
console.log(`end: ${stats.passes}/${stats.passes + stats.failures} ok`);
});
}
}
module.exports = MyReporter;
Documentation here:
https://mochajs.org/api/tutorial-custom-reporter.html
How can I test JavaScript code without using an additional framework such as Mocha? Is it possible to create a unit test case, write test functions manually, test the code, etc.?
I've tried to write a test case, but even though they were in the same folder, I couldn't link them.
Let's say this is a function in the main.js file
function calculate(a, b) {
return a + b;
}
And this is a test case in the testMain.js file
function testCalculate(){
if(calculate(1, 1) == 2)
console.log('It Works!');
else
console.log('Test failed');
}
testCalculate();
When I try to run testMain.js in the IntelliJ IDEA IDE I get an error similar to
"ReferenceError: calculate is not defined"
It depends whether you are trying to test Node.js code or front end code. In both cases you have to "expose" the function under test to your test framework.
Node.js
// main.js
const obj = {};
obj.sum = (a, b) => {
return a+b;
};
module.exports = obj; // Export 'obj' so that it is visible from your test runner
// test.js
const main = require('main.js');
const assert = require('assert');
const it = (desc, fn) => {
try {
fn();
console.log('\x1b[32m%s\x1b[0m', `\u2714 ${desc}`);
} catch (error) {
console.log('\n');
console.log('\x1b[31m%s\x1b[0m', `\u2718 ${desc}`);
console.error(error);
}
};
it('should return the sum of two numbers', () => {
assert.strictEqual(main.sum(5, 10), 15);
});
When you run node test.js you should be able to see the test result.
Front End
// app.js
self.myapp = myapp; // All the methods in myapp will be exposed globally
myapp.sum = function(a, b) {
return a + b;
}
// test.js
function it(desc, fn) {
try {
fn();
console.log('\x1b[32m%s\x1b[0m', '\u2714 ' + desc);
} catch (error) {
console.log('\n');
console.log('\x1b[31m%s\x1b[0m', '\u2718 ' + desc);
console.error(error);
}
}
function assert(condition) {
if (!condition) {
throw new Error();
}
}
it('should return a sum of two integers', function(){
assert(myapp.sum(5, 10) === 15);
});
// test.html - This is your test runner for the front end
<html>
...
<body>
...
<script src="app.js"></script>
<script src="test.js"></script>
</body>
</html>
Open test.html in a browser and open the browser console. You should be able to see the success message.
This way you can write test cases for Node.js and front end JavaScript code without using Mocha or any other framework.
To make your code work, your testMain.js file needs to import your main.js code somehow.
In the main.js file:
function calculate(a, b) {
return a+b;
}
module.exports.calculate = calculate
in testMain.js file, import the main.js:
var main = require('main.js')
function testCalculate(){
if(main.calculate(1+1)==2)
console.log('It Works!');
else
console.log('Test failed');
}
Note: I'm aware this isn't necessarily showing good coding style, just aiming to demonstrate what the original issue was with minimal changes to the original snippets
That said, it's not usually worth reinventing the wheel and building your own test framework. Can you clarify the reason why you would like to avoid an existing framework? If you are looking for simplicity, maybe something like jstinytest would do the trick.
If it is a Node.js application you can simply require the other file and import the other function. If the project uses Babel you can use ES6 import to import the function from the other file.
I was also bothered by the same issue for a while. The question is how to test your JavaScript code with out a testing framework since testing frame works bring a lot to the table and most of the time they get into the way.
The answer is to use assertion libraries without the testing frame work. For example you can just use chai assertion library with out mocha frame work
you can simple install chai with
npm install chai
After that you can just use it:
var should = require('chai').should()
const log = console.log;
//log(should);
//const letters = "abcdef";
const letters = 555;
letters.should.be.a('string');
When I execute a testing witch need the ending result of a vscode.windows.terminal the testing gave me a false positive. I need wait until the terminal operation end in order to execute the asserts.
I use a class named Stack witch have a pom file. My test start with the execution of cd and mvn clean install using the vscode.windows.terminal. The idea of the test assertion is verify the existence of the target file.
const buildProgram = () => {
const terminal = vscode.window.createTerminal();
terminal.show();
terminal.sendText('cd ' + stackDirectory);
terminal.sendText('mvn clean install');
}
it("Stack Project build taget directory exists", function() {
const promise = Promise.all([buildProgram()])
.then(() => {
return fs.existsSync(stackDirectory + "/target");
});
expect(promise).to.eventually.equal(false);
});
This test runs without problem but in the end the target directory is not created.
Here is a function which listens for terminal exit then resolves promise. Essensially we sendText(yourCommandHere+";exit") such that the terminal exits after executing your command, and then listen for that exit.
Additionally, I would believe that when sending multiple commands its better to send them on one line, eg: terminal.sendText(command+";", false); terminal.sendText(command2+";exit") such that we assure the commands are run in the correct order.
export async function callInInteractiveTerminal(
command: string,
shellPath?: string,
name?: string,
location?: vscode.TerminalLocation
): Promise<vscode.TerminalExitStatus> {
const terminal = vscode.window.createTerminal({
shellPath,
name,
location: location ? location : vscode.TerminalLocation.Panel,
});
terminal.show();
terminal.sendText(command, false);
terminal.sendText("; exit");
return new Promise((resolve, reject) => {
const disposeToken = vscode.window.onDidCloseTerminal(
async (closedTerminal) => {
if (closedTerminal === terminal) {
disposeToken.dispose();
if (terminal.exitStatus !== undefined) {
resolve(terminal.exitStatus);
} else {
reject("Terminal exited with undefined status");
}
}
}
);
});
}
After further research it seems this function only works when terminalLocation is TerminalLocation.Panel, not TerminalLocation.Editor.
I'm also a little worried that a fast command might have the exit run before the eventlistener starts, but it works for my use case since i only use it when the terminal needs human interaction.
I find a possible solution replacing the test for this:
it("Stack Project build taget directory exists", function() {
buildProgram();
return new Promise((resolve, reject) => setTimeout(function(){
// Assert here.
if(fs.existsSync(stackDirectory + "/target")){
resolve();
}
reject();
}, 5000));
}).timeout('7s');
I don't really like the idea of using timeout but I don't find a way to say if the terminal is busy.
Is there a way of quitting test suite and stop executing further test cases, if a test case fails in protractor?
In case of jasmine testing framework, you are not the first asking about it.
There are relevant open discussions/issues on exiting after a first failure, --fail-fast option:
Bail on first failure
--fail-fast option?
Please add --fail-fast support
Long story short, this is an open issue and some day jasmine would have the functionality built-in. Currently, use a third-party jasmine-bail-fast module.
Aside from that, there is a handy realtimeFailure jasmine setting. If you set it to true it would not fail the whole test run, but it would show errors in a real time - immediately after happening - this can possibly cover your use case. Set it in jasmineNodeOpts:
exports.config = {
seleniumAddress: 'http://127.0.0.1:4444/wd/hub',
...
jasmineNodeOpts: {
realtimeFailure: true
}
}
Here is my solution to skip tests on first fail with Jasmine 2 and Protractor.
Hope it helps.
exports.config = {
onPrepare: function () {
//skip tests after first fail
var specs = [];
var orgSpecFilter = jasmine.getEnv().specFilter;
jasmine.getEnv().specFilter = function (spec) {
specs.push(spec);
return orgSpecFilter(spec);
};
jasmine.getEnv().addReporter(new function () {
this.specDone = function (result) {
if (result.failedExpectations.length > 0) {
specs.forEach(function (spec) {
spec.disable()
});
}
};
});
}
};
jasmine-bail-fast didn't work in my case. Not sure if it was because of some conflicts with my other report plugins.
In case anyone is having the same problem. You can try protractor-fast-fail
import failFast from 'protractor-fail-fast';
exports.config = {
// if import statement doesn't work, use this instead of import for older versions of node
// plugins: [{
// package: 'protractor-fail-fast'
// }],
onPrepare: function() {
jasmine.getEnv().addReporter(failFast.init());
},
afterLaunch: function() {
failFast.clean();
}
}
Worked perfectly well for me.
EDIT: added import statement in code snippet to reflect readme of projactor-fast-fail
you don't need all those third party plugins. Use native process.exit().
Code example:
it("test", function()
{
...
if(isExit)
{
browser.driver.close().then(function()
{
process.exit(1);
});
}
});
profit.
I want to run Karma a couple of times with different preprocessors. Based on the failures, the karma exec listens to --preprocessors on the commandline, but I can't get it set up properly.
The following all return the same error.
karma start --single-run web-app/karma.conf.js --preprocessors "{\"../grails-app/assets/javascripts/**/!(lib)/**/*.js\": \"jshints\"}"
karma start --single-run web-app/karma.conf.js --preprocessors {"../grails-app/assets/javascripts/**/!(lib)/**/*.js": "jshints"}
karma start --single-run web-app/karma.conf.js --preprocessors "{'../grails-app/assets/javascripts/**/!(lib)/**/*.js': 'jshints'}"
The error:
/usr/lib/node_modules/karma/lib/config.js:145
Object.keys(preprocessors).forEach(function(pattern) {
^
TypeError: Object.keys called on non-object
at Function.keys (native)
at normalizeConfig (/usr/lib/node_modules/karma/lib/config.js:145:10)
at Object.parseConfig (/usr/lib/node_modules/karma/lib/config.js:293:10)
at Object.exports.start (/usr/lib/node_modules/karma/lib/server.js:282:20)
Why am I doing this, are there any alternatives?
The coverage and jshint preprocessors aren't compatible. I could copy the karma.conf.js but that's not a great long-term option for maintainability.
Create a karma.conf.js template.
module.exports = {
...
}
Create a wrapper for karma (let's call it 'wrapper.js'):
var karma = require('karma');
function configurator(options){
var config = getTemplate();
// based on the options object will add different preprocessors
if(options.blah){
config.preprocessors["../grails-app/assets/javascripts/**/!(lib)/**/*.js"] = 'whatever';
}
return config;
}
function getTemplate(){
return {
// start with an empty object
preprocessors: {},
// point to the template, we will enrich it
configFile : __dirname + 'path/to/your/karma.conf.js'
};
}
function startKarma(options){
var config = configurator(options);
karma.server.start(config, function(exitCode){
// exit code === 0 is OK
if (!exitCode) {
console.log('\tTests ran successfully.\n');
// rerun with a different preprocessor
startKarma({blah1: true});
} else {
// just exit with the error code
process.exit(exitCode);
}
});
}
function passedArg(string){
// look at the arguments passed in the CLI
return process.argv.indexOf(string) > -1;
}
function start(){
// start with empty options
var options = {};
if(passedArg('blah')){
options.blah = true;
}
//start karma!
startKarma(options);
}
start();
At this point you can pass the parameter from the console:
$ node wrapper.js blah
For more information about the karma API have a look at: http://karma-runner.github.io/0.8/dev/public-api.html