I'm writing an API in NodeJS and testing using Mocha, Chai and SuperTest. I'm using a typical test-driven approach of writing the tests first then satisfying those tests with working code. However, because of the number of tests for all the different permutations, I've started writing empty placeholder tests so that I have all the it('should...') descriptions in place to remind me what to test when I get to that feature. For example:
it 'should not retrieve documents without an authorized user', (done) ->
done()
The problem with this is that done() is called without any assertion so the test is considered passing, so I've added the following assertion.
false.should.equal true # force failure
but it's a hack and the reason for failure that Mocha displays can seem confusing, especially when other full tests might be failing.
Is there any official way to intentionally fail placeholder tests like this in Mocha?
As of 05/19/2018 this is the official way: https://mochajs.org/#pending-tests
An unimplemented test shouldn't fail, it should be marked as pending.
A succinct method of marking a mocha test as not yet implemented is to not pass a callback function to the it handler.
describe("Traverse", function(){
describe("calls the visitor function", function(){
it("at every element inside an array")
it("at every level of a tree")
})
})
Running mocha test will display your unimplemented tests as pending.
$ mocha test
Traverse
calls the visitor function
- at every element inside an array
- at every level of a tree
0 passing (13ms)
2 pending
The official way to mark tests as not being ready for testing yet is to use skip, which is a method that appears as a field of describe and it. Here's an example:
describe("not skipped", function () {
it("bar", function () {
throw new Error("fail");
});
it.skip("blah", function () {
throw new Error("fail");
});
});
describe.skip("skipped", function () {
it("something", function () {
throw new Error("fail");
});
});
The above code, when put in a test.js file and run with $ mocha --reporter=spec test.js, produces:
not skipped
1) bar
- blah
skipped
- something
0 passing (4ms)
2 pending
1 failing
1) not skipped bar:
Error: fail
at Context.<anonymous> (/tmp/t33/test.js:3:15)
at callFn (/home/ldd/local/lib/node_modules/mocha/lib/runnable.js:223:21)
at Test.Runnable.run (/home/ldd/local/lib/node_modules/mocha/lib/runnable.js:216:7)
at Runner.runTest (/home/ldd/local/lib/node_modules/mocha/lib/runner.js:374:10)
at /home/ldd/local/lib/node_modules/mocha/lib/runner.js:452:12
at next (/home/ldd/local/lib/node_modules/mocha/lib/runner.js:299:14)
at /home/ldd/local/lib/node_modules/mocha/lib/runner.js:309:7
at next (/home/ldd/local/lib/node_modules/mocha/lib/runner.js:247:23)
at Object._onImmediate (/home/ldd/local/lib/node_modules/mocha/lib/runner.js:276:5)
at processImmediate [as _immediateCallback] (timers.js:354:15)
The test names that are preceded by - are skipped. Also, in a terminal that supports colors the tests that are skipped appear in blue (by opposition to red for failed tests and green for passing). A skipped test is said to be "pending" so Mocha reports the number of skipped tests as "2 pending".
If you pass a string or error to done() it will report it as an error. So:
it 'should not retrieve documents without an authorized user', (done) ->
done('not implemented')
would cause the test to fail with the output:
done() invoked with non-Error: not implemented
I like #Canyon's solution of just not passing a callback to mark the tests "pending", but in my case I want these placeholders to fail my CI builds, so making them actual failing tests like this was easier.
This is actually a good question because I would also find this super useful. After looking at it, I would think to just create your own wrapper "todo" or "fail" function that you can reuse throughout your codebase.
Examples below use a function called todo, which will print out the text "not yet implemented". This might be useful as a separate module even so you can import and use with all your tests. Might need to modify the code a bit...
Example in chai assert
var assert = require('chai').assert;
function todo() {
assert(false, "method not yet implemented");
};
describe("some code", function(){
it("should fail something", function(){
todo();
});
});
Example using chai assert , with the fail option (although it looks unncessary)
var assert = require('chai').assert;
function todo() {
assert.fail(true, true, "method not yet implemented"); //1st 2 args can be anything really
};
describe("some code", function(){
it("should fail something", function(){
todo();
});
});
Related
I'm struggling to find a way to unit test the validation of a field in mongoose. I currently have the following test:
it('should be invalid if googleId is empty', () =>
testBook.googleId = '';
const newBook = new Book(testBook);
return newBook.validate().catch((err) => {
should.exist(err.errors.googleId);
});
});
This test is not working as intended because, if I have a correct validation for googleId, the test will pass because it will assert the err.errors.googleId exists, but if I don't have any validation for googleId, it will also pass because the .catch() never gets called and it assumes the test is passing.
I've tried putting should.fail() inside a .then(), but that way it always ends up in .catch() but with different errors, if there's no validation it will be catched with the should.fail() error, if there's validation it will catch with the model validation error.
What would be the best way to achieve this kind of testing?
Thanks alot!
EDIT:
I've tried using the callback of newBook.validate() and it works, but I never use callbacks for model methods, I always tend to use promises, so should I be using the callback in this particular case or there's still a better way to handle it using promises?
You can use the second parameter to then and put something that throws in the first for example:
return newBook.validate().then(
resp => throw new Error("Test failed this should not resolve"),
err => should.exist(err.errors.googleId);
});
So now if the newBook.validate() is not rejected the test will fail. Since you aren't using catch() you don't stop it from causing the test to fail like it should. If the promise is rejected like it should be your test passes (assuming it meets the conditions set). This works because unlike catch() the error callback of then() doesn't catch errors thrown in then(). Of course you can put anything in the first callback that throws an error like assert.fail() or whatever your library has.
There is a chai-as-promised plugin that includes helpers to make Promise testing work more like normal chai expect/should does.
.rejectedWith and .rejected handle errors largely like regular .throw.
const chai = require('chai')
chai.should()
chai.use(require('chai-as-promised'))
it('should be invalid if googleId is empty', function(){
testBook.googleId = ''
const newBook = new Book(testBook)
return newBook.validate()
.should.be.rejectedWith('Validation Failed')
.and.eventually.have.nested.property('errors.googleId')
});
Just make sure you load the plugin last if you are loading any other chai plugins otherwise things go haywire.
I'm correctly working on refactoring my clone of the express-decorator NPM package. This includes refactoring the unit tests that were previously done using AVA. I decided to rewrite them using Mocha and Chai because I like the way they define tests a lot more.
So, what is my issue? Take a look at this code (I broke it down to illustrate the problem):
test('express', (t) => {
#web.basePath('/test')
class Test {
#web.get('/foo/:id')
foo(request, response) {
/* The test in question. */
t.is(parseInt(request.params.id), 5);
response.send();
}
}
let app = express();
let controller = new Test();
web.register(app, controller);
t.plan(1);
return supertest(app)
.get('/test/foo/5')
.expect(200);
});
This code works.
Here's (basically) the same code, now using Mocha and Chai and multiple tests:
describe('The test express server', () => {
#web.basePath('/test')
class Test {
#web.get('/foo/:id')
foo(request, response) {
/* The test in question. */
it('should pass TEST #1',
() => expect(toInteger(request.params.id)).to.equal(5))
response.send()
}
}
const app = express()
const controller = new Test()
web.register(app, controller)
it('should pass TEST #2', (done) => {
return chai.request(app)
.get('/test/foo/5')
.end((err, res) => {
expect(err).to.be.null
expect(res).to.have.status(200)
done()
})
})
})
The problem is that the TEST #1 is ignored by Mocha although that part of the code is run during the tests. I tried to console.log something there and it appeared in the Mocha log where I expected it to appear.
So how do I get that test to work? My idea would be to somehow pass down the context (the test suite) to the it function, but that's not possible with Mocha, or is it?
It looks like you are moving from tape or some similar test runner to Mocha. You're going to need to significantly change your approach because Mocha works significantly differently.
tape and similar runners don't need to know ahead of time what tests exist in the suite. They discover tests as they go along executing your test code, and a test can contain another test. Mocha on the other hand requires that the entire suite be discoverable before running any test.* It needs to know each and every test that will exist in your suite. It has some disadvantages in that you cannot add tests while the Mocha is running the test. You could not have a before hook for instance do a query from a database and from that create tests. You'd have instead to perform the query before the suite has started. However, this way of doing things also has some advantages. You can use the --grep option to select only a subset of tests and Mocha will do it without any trouble. You can also use it.only to select a single test without trouble. Last I checked, tape and its siblings have trouble doing this.
So the reason your Mocha code is not working is because you are creating a test after Mocha has started running the tests. Mocha won't right out crash on you but when you do this, the behavior you get is undefined. I've seen cases where Mocha would ignore the new test, and I've seen cases where it executed it in an unexpected order.
If this were my test what I'd do is:
Remove the call to it from foo.
Modify foo to simply record the request parameters I care about on the controller instance.
foo(request, response) {
// Remember to initialize this.requests in the constructor...
this.requests.push(request);
response.send()
}
Have the test it("should pass test #2" check the requests recorded on the controller:
it('should pass TEST #2', (done) => {
return chai.request(app)
.get('/test/foo/5')
.end((err, res) => {
expect(err).to.be.null
expect(res).to.have.status(200)
expect(controler.requests).to.have.lengthOf(1);
// etc...
done()
})
})
And would use a beforeEach hook to reset the controller between tests so that tests are isolated.
I'm doing tests for my React project using Jest + Enzyme.
Currently I would generate a new wrapper for each test in a suite.
example:
it('should render a title', () => {
let wrapper = shallow(<Component />);
expect(wrapper.find('#title')).toHaveLength(1);
});
it('should call closeModal function when clicked', () => {
let wrapper = shallow(<Component />);
wrapper.instance().closeModal = jest.fn();
let targetFunction = wrapper.instance().closeModal;
expect(targetFunction).toHaveBeenCalled();
});
I would like to know whether this is the standard or should I be generating the wrapper in a beforeAll and referencing that one.
I'm interested in this for the potential improvement in speed time. Right now I have 190 tests and they are done in 21.38s.
The problem with beforeAll is that it will use the same instance in all of your test. If you now change the internal state or props of a component in one of you test this can influent the result of the other test.
Normally I would use beforeAll to test different parts of a component without having a generic test like 'renders correct' but multiple small ones like 'renders the title', 'renders the body' and so on, were every test tests a single part of the component, as this will make it easier to find the place where something went wrong if the test fails.
I want to compute some values before some tests. what is the best way to do that? To use "before" or call functions?
// Way 1
var expect = require('chai').expect;
describe("a test", function() {
var val1, val2;
before(function() {
val1 = computeVal1();
});
it("should return hi1", function() {
expect(val1).to.equal('hi1');
});
before(function() {
val2 = computeVal2();
});
it("should return hi2", function() {
expect(val2).to.equal('hi2');
});
});
Is the above way is better or the below way is better?
// Way 2
var expect = require('chai').expect;
describe("a test", function() {
var val1, val2;
val1 = computeVal1();
it("should return hi1", function() {
expect(val1).to.equal('hi1');
});
val2 = computeVal2();
it("should return hi2", function() {
expect(val2).to.equal('hi2');
});
});
It really makes no difference in this case because ultimately in the second example computeVal1() will run before the tests do. However, given this is exactly what the before / beforeEach hooks were designed for, I would be inclined to stay consistent with the framework and use them.
This is from the mocha documentation:
describe('hooks', function() {
before(function() {
// runs before all tests in this block
})
after(function(){
// runs after all tests in this block
})
beforeEach(function(){
// runs before each test in this block
})
afterEach(function(){
// runs after each test in this block
})
// test cases
})
So, there is not much difference in using before or calling functions directly under the describe. In your second example, val2's value won't be available to the first test, but in the first example, val2's value will be.
However, it is better practice IMO, to use beforeEach. This way state from one test does not affect another test.
Using the hooks (before and beforeEach) to initialize the data that your test uses is usually the best thing to do. Consider this:
In your 2nd snippet, if computeVal1 or computeVal2 fail, then Mocha won't run any test whatsoever. In the 1st snippet, Mocha may run some tests before it tries to call them and they fail. If you have many test files that Mocha loads, it may matter to you that Mocha runs as many test as it can before a failure occurs.
In your 2nd snippet, Mocha will almost always run computeVal1 and computeVal2 even if they are not needed. If they are computationally costly, you'll pay this cost every time. If you run mocha --grep=foo so that it does not select any of your tests, both functions will be called.
In your first snippet, Mocha will run them only if they are needed. If you run mocha --grep=foo, Mocha won't call your functions.
In your 2nd snippet, even using describe.skip for your describe call won't make Mocha skip calling the functions.
The documentation at the official Mocha site contains this example:
describe('User', function(){
describe('#save()', function(){
it('should save without error', function(done){
var user = new User('Luna');
user.save(function(err){
if (err) throw err;
done();
});
})
})
})
I want to know when I should nest my tests in the describe function and what the basic purpose of describe is. Can I compare the first argument passed to describe to comments in a programming language? Nothing is shown of describe in the output on the console. Is it only for readability purposes, or there is some other use for this function?
Is there anything wrong if I use it like this?
describe('User', function(){
describe('#save()', function(){
var user = new User('Luna');
user.save(function(err){
if (err) throw err;
done();
})
})
})
If I do it this way, the test still passes.
The it call identifies each individual tests but by itself it does not tell Mocha anything about how your test suite is structured. How you use the describe call is what gives structure to your test suite. Here are some of the things that using describe to structure your test suite does for you. Here's an example of a test suite, simplified for the purpose of discussion:
function Foo() {
}
describe("Foo", function () {
var foo;
beforeEach(function () {
foo = new Foo();
});
describe("#clone", function () {
beforeEach(function () {
// Some other hook
});
it("clones the object", function () {
});
});
describe("#equals", function () {
it("returns true when the object passed is the same", function () {
});
it("returns false, when...", function () {
});
});
afterEach(function () {
// Destroy the foo that was created.
// foo.destroy();
});
});
function Bar() {
}
describe("Bar", function () {
describe("#clone", function () {
it("clones the object", function () {
});
});
});
Imagine that Foo and Bar are full-fledged classes. Foo has clone and equals methods. Bar has clone. The structure I have above is one possible way to structure tests for these classes.
(The # notation is used by some systems (like for instance, jsdoc) to indicate an instance field. So when used with a method name, it indicates a method called on an instance of the class (rather than a class method, which is called on the class itself). The test suite would run just as well without the presence of #.)
Provide Banners
Some of Mocha's reporters show the names you give to describe in the reports they produce. For instance, the spec reporter (which you can use by running $ mocha -R spec), would report:
Foo
#clone
✓ clones the object
#equals
✓ returns true when the object passed is the same
✓ returns false, when...
Bar
#clone
✓ clones the object
4 passing (4ms)
Help Select Parts to Run
If you want to run only some of the tests, you can use the --grep option. So if you care only about the Bar class, you can do $ mocha -R spec --grep Bar, and get the output:
Bar
#clone
✓ clones the object
1 passing (4ms)
Or if you care only about the clone methods of all classes, then $ mocha -R spec --grep '\bclone\b' and get the output:
Foo
#clone
✓ clones the object
Bar
#clone
✓ clones the object
2 passing (5ms)
The value given to --grep is interpreted as a regex so when I pass \bclone\b I'm asking only for the word clone, and not things like clones or cloned.
Provide Hooks
In the example above the beforeEach and afterEach calls are hooks. Each hook affects the it calls that are inside the describe call which is the parent of the hook. The various hooks are:
beforeEach which runs before each individual it inside the describe call.
afterEach which runs after each individual it inside the describe call.
before which runs once before any of the individual it inside the describe call is run.
after which runs once after all the individual it inside the describe call are run.
These hooks can be used to acquire resources or create data structures needed for the tests and then release resources or destroy these structures (if needed) after the tests are done.
The snippet you show at the end of your question won't generate an error but it does not actually contain any test, because tests are defined by it.
It's hard to add to Louis' excellent answer. There are a couple of advantages of the describe block that he didn't mention which are the skip and only functions.
describe.skip(...) {
...
}
will skip this describe and all its nested describe and it functions while:
describe.only(...) {
...
}
will only execute that describe and its nested describe and it functions. The skip() and only() modifiers can also be applied to the it() functions.
To my knowledge, describe is really just there for humans... So we can see different areas of the app. You can nest describe n levels deep.
describe('user',function(){
describe('create',function(){}
});
Describe is just used for the sake of understanding the purpose of the tests , it is also used to logically group the tests . Lets say you are testing the database API's , all the database tests could come under the outer describe , so the outer describe logically groups all the database related . Lets say there are 10 database related API's to test , each of the inner describe functions defines what those tests are ....
The particular role of describe is to indicate which component is being tested and which method of that component is also being tested.
for example, lets say we have a User Prototype
var User = function() {
const self = this;
function setName(name) {
self.name = name
}
function getName(name) {
return self.name;
}
return{setName, getName};
}
module.exports = User;
And it needs to be tested, so a spec file is created for unit test
var assert = require('assert');
var User = require("../controllers/user.controller");
describe("User", function() {
describe('setName', function() {
it("should set the name on user", function() {
const pedro = new User();
name = "Pedro"
pedro.setName(name);
assert(pedro.getName(), name);
});
});
});
It is easy to see that the purpose of describe is indicating the component to be tested and the nested describe methods indicate which methods needs to be tested