I'm creating my own tests using Cucumber-js and now I find myself with some step definition that I could reuse.
More specifically, I wanted to create a package with my common steps and then include the library into the different test suites.
I was playing around with
module.exports = function () {
this.Given(`I'm standard`, function(done) {
})
}
but when I use require() in the test suite it doesn't find the steps.
I was looking around but I couldn't find any documentation around this. Is this some bad practice? and If so, how I can avoid to repeat exactly the same code in different test suite packages?
Just create a _shared.spec.ts file within the folder of your tests and cucumber.js is gonna find directly the shared definition to reuse.
Related
I'd like to add an important functionality that I can use at work without using require() every time. So, I thought modifying built-in objects can make this happen but I could not locate the locations of those objects to do the modification.
Are those objects in NodeJS binary? Would that mean I have to fork the whole NodeJS repo to make this happen?
Please, I don't want to use prototype editing etc which are same as require. I need to have native feeling.
First off, I agree with an earlier comment that this sounds like a bit of an XY problem where we could better help you if you describe what problem you're really trying to solve. Portable node.js programs that work anywhere or work with any future versions of node.js don't rely on some sort of custom configured environment in order to run. They use the built-in capabilities of node.js and they require/import in external things they want to add to the environment.
Are those objects in NodeJS binary?
Yes, they are in the executable.
Would that mean I have to fork the whole NodeJS repo to make this happen?
Yes.
Please, I don't want to use prototype editing etc which are same as require. I need to have native feeling.
"Native feeling"? This sounds like you haven't really bought into the node.js module architecture. It is different than many other environments. It's easy to get used to over time. IMO, it would really be better to go with the flow and architecture of the platform rather than make some custom version of node.js just to save one line of typing in your startup code.
And, the whole concept of adding a number of globals you can use anywhere pretty much shows that you haven't fully understood the design, architectural, code reuse and testability advantages of the module design baked into node.js. If you had, you wouldn't be trying to write a lot of code that can't be reused in other ways that you don't anticipate now.
That said, in searching through the node.js source code on Github, I found this source file node.js which is where lots of things are added to the node.js global object such as setTimeout(), clearTimeout(), setImmediate(), clearImmediate() and so on. So, that source file seems to be where node.js is setting up the global object. If you wanted to add your own things there, that's one place where it would be done.
To provide a sample of that code (you can see the link above for the complete code):
if (!config.noBrowserGlobals) {
// Override global console from the one provided by the VM
// to the one implemented by Node.js
// https://console.spec.whatwg.org/#console-namespace
exposeNamespace(global, 'console', createGlobalConsole(global.console));
const { URL, URLSearchParams } = require('internal/url');
// https://url.spec.whatwg.org/#url
exposeInterface(global, 'URL', URL);
// https://url.spec.whatwg.org/#urlsearchparams
exposeInterface(global, 'URLSearchParams', URLSearchParams);
const {
TextEncoder, TextDecoder
} = require('internal/encoding');
// https://encoding.spec.whatwg.org/#textencoder
exposeInterface(global, 'TextEncoder', TextEncoder);
// https://encoding.spec.whatwg.org/#textdecoder
exposeInterface(global, 'TextDecoder', TextDecoder);
// https://html.spec.whatwg.org/multipage/webappapis.html#windoworworkerglobalscope
const timers = require('timers');
defineOperation(global, 'clearInterval', timers.clearInterval);
defineOperation(global, 'clearTimeout', timers.clearTimeout);
defineOperation(global, 'setInterval', timers.setInterval);
defineOperation(global, 'setTimeout', timers.setTimeout);
defineOperation(global, 'queueMicrotask', queueMicrotask);
// Non-standard extensions:
defineOperation(global, 'clearImmediate', timers.clearImmediate);
defineOperation(global, 'setImmediate', timers.setImmediate);
}
This code is built into the node.js executable so the only way I know of to directly modify it (without hackish patching of the executable itself) would be to modify the file and then rebuild node.js for your platform into a custom build.
On a little more practical note, you can also use the -r module command line argument to tell node.js to run require(module) before starting your main script. So, you could make a different way of starting node.js from a shell file that always passes the -r fullPathToYourModule argument to node.js so it will always run your startup module that adds things to the global object.
Again, you'd be doing this just to save one line of typing in your startup file. It is really worth doing that?
I've written a Node.js CLI and would like further development to proceed in a TDD style. I have an ideal workflow in mind and want to know if it is possible with existing frameworks.
When I write a new function, I'd like to document its preconditions in an assertion that will throw an error if e.g. input doesn't validate.
Postconditions should be specified in or near the function
The pre and postconditions should generate tests to be run with npm test
Assertions should only be checked in development mode
Documentation in each function should generate (html|md) documentation for the CLI
If I want to add tests other than precondition / postcondition / invariant tests it should be easy to do so
When mocking tests, there should be a way to specify "the universe before" and "the universe after". For instance to test a command that scaffolds a new project a-la express, I should be able to specify the initial directory structure as empty ({}) and the final directory structure as a JSON object representing the result ({ name: "project", path: "/project", type: "directory", children: { ... } }) <-- or something like that. This seems to require the ability to intercept writes to the file system.
I don't have a candidate library for automated test generation yet. I think a mix of Mocha, rewire and Contractual / Obligations might work for everything else, but I'm interested to hear about other approaches.
While realizing that my project setup might be the root cause of my problem, here's what I'd like some help with (moving from another framework to Intern):
I've different (>20) projects in one dev workspace, so I've (>20) different directories with test code. I'd like a project to be testable on itself, but also would like to execute all suites together.
I am specifying to use RequireJS as an AMD loader and where my tests can be found per project (one for nodeJS, one for browsers) through a config file. PLUS I have one overall config file specifying all the files.
You can image there is quite the duplication, what would be a good approach to DRY this up?
Note: it would also be welcome to help to describe my problem better (more generic or less TLDR)!
Since Intern configuration files are just AMD modules you can use the normal dependency loading mechanism to load and combine configuration data from multiple files:
// in your “do everything” master configuration
define([
'projectA/tests/intern',
'projectB/tests/intern',
'projectC/tests/intern',
// …
], function () {
var configs = Array.prototype.slice.call(arguments, 0);
function getCombined(key) {
return Array.prototype.concat.apply([], configs.map(function (config) {
return config[key];
}));
}
return {
suites: getCombined('suites'),
functionalSuites: getCombined('functionalSuites'),
// …
};
});
I'm a bit stuck with understanding how to write complicated Gruntfile.js and use it with tests. Am I using Grunt in a right way? I would like to ask community for help and contribute in an other way.
I'm writing a new task for Grunt and want to roll it out for wide audience on Github and npm. I want to make automated testing for this task (and I want to learn how to do it properly!).
I want to test different options combinations (about 15 by now). So, I should multiple times:
run cleanup
run my task with next options set
run tests and pass options object to the test
Some non-working code to look at for better understanding:
Gruntfile:
grunt.initConfig({
test_my_task: {
testBasic: {
options: {
//first set
}
},
testIgnore: {
options: {
//another set
}
},
//...
}
clean: {
tests: ['tmp'] // mmm... clean test directory
},
// mmm... unit tests.
nodeunit: {
tests: ['test/*.js'] //tests code is in 'tests/' dir
}
});
grunt.registerTask('test', ['test_my_task']);
I know how to check if tmp/ folder is in desired state when options object given.
The problem is putting things together.
I would ask just for template code as an answer, npo need to put working example.
PS: you can propose another testing tool, nodeunit is not a must.
PPS: crap, I could have written this in plain javascript by now! Maybe I'm doing wrong that I want to put Grunt into the unit tests? But I want to test how my task works in real environment with different options passed from Grunt...
You might want to have a look at the grunt-lintspaces configuration. The tests look like this, and it seems like a good way to do it. grunt-lintspaces uses nodeunit but a lot of plugins these days seem to.
If you don't want to test actual grunt output and instead functionality, you could use grunt-mocha-test - https://github.com/pghalliday/grunt-mocha-test which I am using for the grunt-available-tasks tests. I prefer the describe style of testing personally, it reads very well; the advantage of using this is that you actually test what your plugin does without including a ton of config in your Gruntfile; i.e. test code should be in the tests.
Grunt is well tested already so it doesn't make sense to test that its configuration works. Just test the functionality of your own plugin.
What is used for BDD and TDD with node.js?
I'm used to use Cucumber + RSpec. What's a good combo for node.js?
thanks
Update
Mocha gets my vote now!
You could have a look at the testing modules section from the node.js modules page. For example Vows is a pretty popular BDD framework.
Vows is a behavior driven development framework for Node.js.
Check out mocha - (github)
Also mocha-cakes, my attempt for Cucumber syntax on mocha.
If you are used to rspec, Jasmine is pretty nice. I've not used it on Node.js, but I have used it for testing a backbone app. It's syntax is very similar to rspec. Taken from the site above:
describe("Jasmine", function() {
it("makes testing JavaScript awesome!", function() {
expect(yourCode).toBeLotsBetter();
});
});
It's listed in the link provided by Alfred above, but since folks listed Vows as an example, I figured I'd give Jasmine a bump, especially since it's syntactically similar to rspec ;)
There is the 'Vows' project for BDD on Node http://vowsjs.org, looks pretty nice. It's a bit different from RSpec/Cucumber, but it's pretty fun
Maybe a little later, but what you're looking for is Kyuri: https://github.com/nodejitsu/kyuri
"kyuri is a node.js Cucumber implementation with a few extra asynchronous keywords. it supports 160+ languages and exports to VowsJS stubs"
Also, nodejitsu seems to have built a web app for managing a project Kyuri feature specs in a collaborative way, it's named "prenup", I would give it a look.
You could also try yadda. It plugs into other test libraries including mocha, jasmine, casper & webdriver, but also lets you write proper feature files instead of merely annotating you tests in situ. A typical test might look like...
var Yadda = require('yadda');
Yadda.plugins.mocha();
feature('./features/bottles.feature', function(feature) {
var library = require('./bottles-library');
var yadda = new Yadda.Yadda(library);
scenarios(feature.scenarios, function(scenario, done) {
yadda.yadda(scenario.steps, done);
});
});
And the feature file...
Feature: Mocha Asynchronous Example
Scenario: A bottle falls from the wall
Given 100 green bottles are standing on the wall
when 1 green bottle accidentally falls
then there are 99 green bottles standing on the wall
And output...
Mocha Asynchronous Example
✓ A bottle falls from the wall
1 passing (12ms)
Check out Buster.JS. Created by Christian Johansen, who literally wrote the book on javascript testing.
Buster supports both TDD and BDD. It does browser testing with browser automation (think JsTestDriver), QUnit style static HTML page testing, testing in headless browsers (PhantomJS, jsdom), and more.
Package a
(bdd and mocking)
https://npmjs.org/package/a
Very compact syntax, context separated from acts, chainable acts.
Easy Cmd line runner that searches recursively.
Unit tests: Mocha is great for unit tests.
BDD tests If you want a BDD test framework for Node.js then I'd recommend the Cucumber package.
I was going through the same concern last month .
For BDD :
Though Mocha itself provides BDD style by their describe and it statements.
For styles like cucumber , you can try :
mocha-cakes
mocha-gherkin
cucumber.js
kyuri
mocha-cucumber
They all have their own styles. I am sorry I can not provide working snippets now , let me know #Donald which one you select. Would like to know your insight.
I too was looking for a good Gherkin implementation, found mocha-cakes/mocha-cakes-2 which were nice but not very full featured. So I build my own with mocha as the base, which has parity with the gherkin language including Scenario Outlines. It also makes it easy to reference the data in your test. Its different to cucumber.js as its all inline not separate files. You can find the project here:
livedoc-mocha