willy
v1.0.3
Published
An assertion library that reads very naturally.
Downloads
30
Maintainers
Readme
Installation | Built-in Tests | Custom Tests
Willy is an assertion library designed to be simple and readable. It doesn't follow the normal BDD/TDD assertion styles, but reads more like questions.
var will = require('willy').will;
describe('some test suite', function () {
it('should do X, Y, and Z', function () {
// Will it?
will(true).be(true);
});
});
Willy...
- is super easy to use
- includes a bunch of built-in tests
- makes custom tests easy
- supports promises
Keep it simple, so you can focus on your code, not your tests. Compare testing instanceof
in a few different assertion libraries.
// Chai
expect(foo).to.be.an.instanceof(Foo);
// Shouldjs
foo.should.be.an.instanceOf(Foo)
// Jasmine
expect(foo).toEqual(jasmine.any(Foo));
// Willy
will(foo).beA(Foo);
Want to add to Willy's repertoire? That's easy, too.
willy.define(function beASubstringOf() {
return this.expected.indexOf(this.actual) > -1;
});
will('potato').beASubstringOf('Bender Bending Rodriguez');
// expected 'potato' to be a substring of 'Bender Bending Rodriguez'
Installation
Use npm, man. Keep it simple.
npm install willy --save-dev
Usage
Built-in Tests
- be
- beA
- beAn
- beDefined
- beFalsy
- beGreaterThan
- beLessThan
- beLike
- beMoreThan
- beNull
- beTruthy
- beUndefined
- exist
- have
- haveAny
- haveOnly
- haveOwn
- match
- throw
be
Test identity.
// pass
will(3).be(3);
// fail
will('3').be(3);
beA/beAn
Test inheritance.
This also handles some of the weirdness of JavaScript, so that String
and Number
literals act as expected.
var Foo = function () {};
var foo = new Foo();
// pass
will(foo).beA(Foo);
will('').beA(String);
will([]).beAn(Array);
// fail
will('').beA(Number);
beDefined
Test for a defined value.
var foo = 123;
var bar;
// pass
will(foo).beDefined();
// fail
will(bar).beDefined();
beFalsy
Test for a falsy value.
// pass
will('').beFalsy();
// fail
will('asdf').beFalsy();
beGreaterThan
Test a value to see if it's greater than another.
// pass
will(4).beGreaterThan(3);
// fail
will(3).beGreaterThan(3);
beLessThan
Test a value to see if it's less than another.
// pass
will(3).beLessThan(4);
// fail
will(3).beLessThan(3);
beLike
Test equality.
// pass
will('').beLike(false);
// fail
will('false').beLike(false);
This also works on objects, including Arrays, recursively.
// pass
will({
foo: 'bar',
baz: [1, 2, 3],
quux: null
}).beLike({
foo: 'bar',
baz: [1, 2, 3],
quux: null
});
will([1, 2, 3]).beLike([1, 2, 3]);
// fail
will({
foo: {
bar: {
baz: {
quux: true
}
}
}
}).beLike({
foo: {
bar: {
baz: {
quux: false
}
}
}
});
will([1, 2, 3]).beLike([3, 2, 1]);
beMoreThan
Test a value to see if it's more than another.
// pass
will(4).beMoreThan(3);
// fail
will(3).beMoreThan(3);
beNull
Test for null
.
// pass
will(null).beNull();
// fail
will(undefined).beNull();
beTruthy
Test for a truthy value.
// pass
will('asdf').beTruthy();
// fail
will('').beTruthy();
beUndefined
Test for an undefined
value.
var foo;
var bar = 123;
// pass
will(foo).beUndefined();
// fail
will(bar).beUndefined();
exist
Test the existence of a property.
// pass
var foo = { bar: 1 };
will(foo.bar).exist();
// fail
will(foo.baz).exist();
have
Test the existence of multiple items/properties in an Array/Object. all must be present
// pass
will([1, 2, 3]).have(1);
will([1, 2, 3]).have([1, 2]);
will({ foo: 1, bar: 1 }).have('foo');
will({ foo: 1, bar: 1 }).have(['foo', 'bar']);
// fail
will([2, 3]).have(1);
will([1, 2]).have([1, 3]);
will({ foo: 1, bar: 1 }).have('baz');
will({ foo: 1, bar: 1 }).have(['foo', 'baz']);
haveAny
Test the existence of one item/property in an Array/Object
// pass
will([1, 2, 3]).haveAny(1);
will([1, 2, 3]).haveAny([3, 6]);
will({ foo: 1, bar: 1 }).haveAny('foo');
will({ foo: 1, bar: 1 }).haveAny(['foo', 'baz']);
// fail
will([2, 3]).haveAny(1);
will([1, 2]).haveAny([3, 6]);
will({ foo: 1, bar: 1 }).haveAny('baz');
will({ foo: 1, bar: 1 }).haveAny(['baz', 'quux']);
haveOnly
Test an Array/Object for unexpected items/properties.
// pass
will([1]).haveOnly(1);
will([1, 2, 3]).haveOnly([1, 2, 3]);
will({ foo: 1 }).haveOnly('foo');
will({ foo: 1, bar: 1 }).haveOnly(['foo', 'bar']);
// fail
will([1, 2]).haveOnly(1);
will([1, 2, 3]).haveOnly([1, 2]);
will({ foo: 1, bar: 1 }).haveOnly('baz');
will({ foo: 1, bar: 1, baz: 1 }).haveOnly(['foo', 'bar']);
haveOwn
Test for an own property.
var Foo = function () {};
var foo = new Foo();
foo.bar = true;
Foo.prototype.baz = true;
// pass
will(foo).haveOwn('bar');
// fail
will(foo).haveOwn('baz');
match
Test against RegExp.
// pass
will('asdf').match(/SD/i);
// fail
will('asdf').match(/SD/);
throw
Test for an error being thrown.
var bad = function () {
throw new Error('whoops');
};
var good = function () {};
// pass
will(bad).throw();
// fail
will(good).throw();
Custom Tests
To define new tests, use willy.define
. The function should return an expression used to determine if the test passes or fails.
willy.define(function beASubstringOf() {
return this.expected.indexOf(this.actual) > -1;
});
will('potato').beASubstringOf('Bender Bending Rodriguez');
// expected 'potato' to be a substring of 'Bender Bending Rodriguez'
Inside every test function
this.actual
is the value passed towill()
this.expected
is the optional value passed to the test
Advanced
Pass an object to willy.define
to give you more options. The object's properties should be:
- fn - The function used to perform the test.
- explanation (optional) - An explanation of what you were testing. If omitted, the test's name will be converted.
- name (optional) - The name of your test. This can usually be figured out, but ocassionally you may want to be explicit.
Changing the Explanation
// providing a better explanation
willy.define({
fn: function beASubstringOf() {
return this.expected.indexOf(this.actual) > -1;
},
explanation: 'be found inside of'
});
will('potato').beASubstringOf('Bender Bending Rodriguez');
// expected 'potato' to be found inside of 'Bender Bending Rodriguez'
Changing the Name
// providing a different name
willy.define({
fn: function () {
return this.expected.indexOf(this.actual) > -1;
},
name: 'lieWithin'
});
will('potato').lieWithin('Bender Bending Rodriguez');
// expected 'potato' to lie within 'Bender Bending Rodriguez'
Bulk Definitions
If you're lazy, use willy.loadDefinitions
to define multiple tests at a time.
willy.loadDefinitions({
beASubstringOf: {
fn: function () {
return this.expected.indexOf(this.actual) > -1;
},
explanation: 'be found inside of'
},
lieWithin: {
fn: function () {
return this.expected.indexOf(this.actual) > -1;
}
}
});
Modularize It
For supreme laziness, keep your custom tests in a Node module. This will allow you to build up a collection of custom tests you can reuse with all your projects.
my-tests.js
exports.beASubstringOf = {
fn: function () {
return this.expected.indexOf(this.actual) > -1;
},
explanation: 'be found inside of'
};
exports.lieWithin = {
fn: function () {
return this.expected.indexOf(this.actual) > -1;
}
};
A Test Suite
var willy = require('willy'),
will = willy.will;
willy.loadDefinitions(require('./my-tests.js'));
describe('a test suite', function () {
it('should be pretty easy to share custom tests', function () {
will('potato').lieWithin('Bender Bending Rodriguez');
// expected 'potato' to lie within 'Bender Bending Rodriguez'
});
});