How to run cleanup with vows.js? - node.js

I'm using Vows.js to test some node.js which is creating records in a database. As a result of this it creates some test records in the database. I'd like to remove these records once the tests have run. Is there a way to run a cleanup function when a batch of tests is run in Vows?

You can define the teardown function in your context that is executed once all the tests in your context are run.
vows.describe('Foo').addBatch({
'A Context' : {
topic : { foo: 'bar' },
'it works' : function (topic) { assert.equal(topic.foo, "bar"); },
teardown : function (topic) { topic.foo = "baz" }
}
});
You can see this in Vows own tests.

If it were me, I would use a separate test database when running automated tests, and empty that database before each test run.

There's an open pull request for vows implementing afterSuite:
https://github.com/phstc/vows/commit/d5b40e85e924e06cca560b4d8d6a264528bbab2b

Related

Node.JS: Make module runnable through require or from command line

I have a script setupDB.js that runs asynchronously and is intended to be called from command line. Recently, I added test cases to my project, some of which require a database to be set up (and thus the execution of aforementioned script).
Now, I would like to know when the script has finished doing its thing. At the moment I'm simply waiting for a few seconds after requiring setupDB.js before I start my tests, which is obviously a bad idea.
The problem with simply exporting a function with a callback parameter is that it is important that the script can be run without any overhead, meaning no command line arguments, no additional function calls etc., since it is part of a bigger build process.
Do you have any suggestions for a better approach?
I was also looking for this recently, and came across a somewhat-related question: "Node.JS: Detect if called through require or directly by command line
" which has an answer that helped me build something like the following just a few minutes ago where the export is only run if it's used as a module, and the CLI library is only required if ran as a script.
function doSomething (opts) {
}
/*
* Based on
* https://stackoverflow.com/a/46962952/7665043
*/
function isScript () {
return require.main && require.main.filename === /\((.*):\d+:\d+\)$/.exec((new Error()).stack.split('\n')[ 2 ])[ 1 ]
}
if (isScript) {
const cli = require('some CLI library')
opts = cli.parseCLISomehow()
doSomething(opts)
} else {
module.exports = {
doSomething
}
}
There may be some reason that this is not a good idea, but I am not an expert.
I have now handled it this way: I export a function that does the setup. At the beginning I check if the script has been called from command line, and if so, I simply call the function. At the same time, I can also call it directly from another module and pass a callback.
if (require.main === module) {
// Called from command line
runSetup(function (err, res) {
// do callback handling
});
}
function runSetup(callback) {
// do the setup
}
exports.runSetup = runSetup;
make-runnable npm module can help with this.

Node.js CronJob execution when using mocha for testing

So, I've got some js code which is a slackbot which supposed to simply listen and parse the date provided, then start a CronJob to run a certain function according to the cron or date format provided. Something like this.
var CronJob = require ('cron').CronJob;
...
robot.respond(date, function (msg)) {
if(!isValidDate(date)) msg.reply("not a valid date);
var interval = isCronDate(date) ? date : new Date(date);
msg.reply("Job about to be scheduled.")
var schedule = new CronJob(interval, processDataOnDate(), function() { msg.reply("hello") }, true);
}
I've got a coffee file testing this code, and I expect certain responses back, but I do NOT expect the cron job to be executed based on the date I've provided in my test code. However, it is. Is this normal? Does mocha force the code to finish execution due to the fact that this is a unit test, or am I doing something wrong? I am running this to execute my unit test.
mocha --compilers coffee:coffee-script/register
For further information I am running this as a slackbot, so this is all done in the form of 'say' and 'reply.' One of my tests looks like this.
beforeEach ->
yield #room.user.say 'bob', '#bot schedule at 2017-05-25 18:00:00'
expect(#room.messages).to.eql [
['bob', 'bot schedule at 2017-05-25 18:00:00']
['bot', 'Job about to be scheduled']
]
The test fails and informs me that the actual result included the message 'hello' from the bot, despite the fact that the date I've provided in my test is in the future.
The last parameter when you're initializing your CronJob indicates that it should execute the job immediately:
new CronJob(interval, processDataOnDate(), function() { msg.reply("hello") }, true);
That will cause the job to execute immediately, even though your execution date is in the future.
See: https://www.npmjs.com/package/cron#api

Intern Promise Timeouts

I am writing some functional tests with Intern and came across the following section of text...
"The test will also fail if the promise is not fulfilled within the timeout of the test (the default is 30 seconds; set this.timeout to change the value)."
at...
https://github.com/theintern/intern/wiki/Writing-Tests-with-Intern#asynchronous-testing
How do I set the promise timeout for functional tests? I have tried calling timeout() directly on the promise but it isn't a valid method.
I have already set the various WD timeout (page load timeout, implicit wait etc...) but I am having issues with promises timing out.
Setting the timeout in my tests via the suggested API's just didn't work.
Its far from ideal but I ended up modifying Test.js directly and hard coding in the timeout I wnated.
I did notice when looking through the source that there was a comment on the timeout code saying something like // TODO timeouts not working correctly yet
It seems to be working okay on the latest version:
define([
'intern!object',
'intern/chai!assert',
'require',
'intern/dojo/node!leadfoot/helpers/pollUntil'
], function (registerSuite, assert, require, pollUntil) {
registerSuite(function(){
return {
name: 'index',
setup: function() {
},
'Test timeout': function () {
this.timeout = 90000;
return this.remote.sleep(45000);
}
}
});
});
You can also add defaultTimeout: 90000 to your configuration file (tests/intern.js in the default tutorial codebase) to globally set the timeout. This works well for me.
A timeout for a test is either set by passing the timeout as the first argument to this.async, or by setting this.timeout (it is a property, not a method).
For anyone who found their way here while using InternJS 4 and utilizing async/await for functional testing: timeout and executeAsync just wouldn't work for me, but the pattern below did. Basically I just executed some logic and used the sleep method at a longer interval than the setTimeout. Keep in mind that the javascript run inside of execute is block scoped so you will want to cache anything you want to reference later on the window object. Hopefully this saves someone else some time and frustration...
test(`timer test`, async ({remote}) => {
await remote.execute(`
// run setup logic, keep in mind this is scoped and if you want to reference anything it should be window scoped
window.val = "foo";
window.setTimeout(function(){
window.val = "bar";
}, 50);
return true;
`);
await remote.sleep(51); // remote will chill for 51 ms
let data = await remote.execute(`
// now you can call the reference and the timeout has run
return window.val;
`);
assert.strictEqual(
data,
'bar',
`remote.sleep(51) should wait until the setTimeout has run, converting window.val from "foo" to "bar"`
);
});

CasperJS, parallel browsing WITH the testing framework

Question : I would like to know if it's possible to do parallel browsing with the testing framework in one script file, so with the tester module and casperjs test command.
I've seen some people create two casper instances :
CasperJS simultaneous requests and https://groups.google.com/forum/#!topic/casperjs/Scx4Cjqp7hE , but as said in the doc, we can't create new casper instance in a test script.
So i tried doing something similar-simple example- with a casper testing script (just copy and execute this it will work):
var url1 = "http://casperjs.readthedocs.org/en/latest/testing.html"
,url2 = "http://casperjs.readthedocs.org/en/latest/testing.html"
;
var casperActions = {
process1: function () {
casper.test.begin('\n********* First processus with our test suite : ***********\n', function suite(test) {
"use strict";
casper.start()
.thenOpen(url1,function(){
this.echo("1","INFO");
});
casper.wait(10000,function(){
casper.test.comment("If parallel, it won't be printed before comment of the second processus !");
})
.run(function() {
this.test.comment('----------------------- First processus over ------------------------\n');
test.done();
});
});
},
process2: function () {
casper.test.begin('\n********* Second processus with our test suite : ***********\n', function suite(test) {
"use strict";
casper.start()
.thenOpen(url1,function(){
this.echo("2","INFO");
});
casper.test.comment("Hi, if parallel, i'm first !");
casper.run(function() {
this.test.comment('----------------------- Second processus over ------------------------\n');
test.done();
});
});
}
};
['process1', 'process2'].forEach(function(href) {
casperActions[href]();
});
But it's not parallel, they are executed one by one.
Currently, i do some parallel browsing but with node so not in the file itself, using child process. So if you split my previous code in two files -proc1.js,proc2.js- (just the two scenarios->casper.test.begin{...}), and launch the code below via node, something like that will work-with Linux, i have to search the equivalent syntax for windows- :
var exec = require("child_process").exec
;
exec('casperjs test proc1.js',function(err,stdout,stderr){
console.log('stdout: ' + stdout);
console.log('endprocess1');
});
exec('casperjs test proc2.js',function(err,stdout,stderr){
console.log('stdout: ' + stdout);
console.log('endprocess2');
});
My problem is that the redirections and open new urls is quite long, so i want for some of them being execute in parallel. I could do XXX files and launch them in parallel with node, but i don't want XXX files with 5 lines of code, so if someone succeeded (if it's possible) to open urls in parrallel in the same testing file without node (so without multiple processes), please teach me!
And i would like to know what is the difference between chaining instructions, or re-use the casper object each time :
so between that :
casper.test.begin('\n********* First processus with our test suite : ***********\n', function suite(test) {
"use strict";
casper.start()
.thenOpen(url1,function(){
this.echo("1","INFO");
})
.wait(10000,function(){
casper.test.comment("If parallel, it won't be print before comment of the second processus !");
})
.run(function() {
this.test.comment('----------------------- First processus over ------------------------\n');
test.done();
});
});
And that :
casper.test.begin('\n********* First processus with our test suite : ***********\n', function suite(test) {
"use strict";
casper.start();
casper.thenOpen(url1,function(){
this.echo("1","INFO");
});
casper.wait(10000,function(){
casper.test.comment("If parallel, it won't be print before comment of the second processus !");
})
casper.run(function() {
this.test.comment('----------------------- First processus over ------------------------\n');
test.done();
});
});
Chaining my instructions, will it block all the chain if one of my step fail (promise rejected) instead of executing every casper steps?
So it would be better to chaining instructions with dependant steps [like thenClick(selector)] and use the casper object with independant steps (like open a new url), wouldn't it?
Edit : i tried and if a step fail, chained or not, it will stop all the next steps, so i don't see the difference using chained steps or not...
Well, chaining or using the casper object each time is just a matter of taste, it does the same, and we can't launch several instances of casper in a testing script. If you have a loop which opens some links, you'll have to wait for each page to be loaded sequentially.
To launch parallel browsing with the testing framework, you have to do multiple processes, so using node does the trick.
After digging, I finally split files with too many redirections to be not longer than my main scenario which can't be split. A folder with 15 files is executed -parallel- in 2/4 min, on local machine.
There's no official support for parallel browsing right now in casperjs, There are multiple work arounds I've set up several different environments and am about to test witch one is the best
I see one person is working with multiple casper instances this way.
var google = require('casper').create();
var yahoo = require('casper').create();
google.start('http://google.com/');
yahoo.start('http://yahoo.com/', function() {
this.echo(google.getTitle());
});
google.run(function() {});
yahoo.run(function() {});
setTimeout(function() {
yahoo.exit();
}, 5000);
Currently I am running multiple caspers in node using 'child_process'. It is very heave on both CPU and memory

Testing events that fire multiple times

So, Im using vows js for testing node apps.
I have some code which emits the same event multiple times.
Vows (0.7.0) seems fine when testing events that fire once, but if your code emits the same event multiple times, vows complains.
A pull request which I believe might solve this problem was submitted over a year ago but nothing seems to have happened with it...
Does anybody know of a test framework which will allow me to test an object which emits the same event n times?
Here's what I mean (in vows):
vows.describe("Vows test").addBatch({
"A test ": {
topic: function () {
var topic = new(events.EventEmitter);
for(var i=0; i<10;i++) {
topic.emit('woot', 'woot');
}
return topic;
},
on: {
"woot": {
"will catch event the woot event" : function (ret) {
assert.strictEqual(ret, 'woot');
}
}
}
}
})
Cheers...

Resources