Skip to content

Instantly share code, notes, and snippets.

@graue graue/testingStyles.js
Last active Aug 29, 2015

Embed
What would you like to do?
Styles of property-based testing in JavaScript
// Option #1
prop('addition is commutative', [Number, Number], function(a, b) {
return add(a, b) === add(b, a);
});
// Option #2
prop('addition is commutative', function(any) {
var a = any(Number);
var b = any(Number);
return add(a, b) === add(b, a);
});
// Option #3
prop('addition is commutative', function() {
var a = gentest.gen(Number);
var b = gentest.gen(Number);
return add(a, b) === add(b, a);
});
// Option #4
prop('addition is commutative', function() {
var a = this.get(Number);
var b = this.get(Number);
return add(a, b) === add(b, a);
});
// Option #5
prop('addition is commutative',
[gentest.types.int, gentest.types.int],
function(a, b) {
return add(a, b) === add(b, a);
});
// Option #6
prop('addition is commutative', function(a, b) {
return add(a, b) === add(b, a);
}, [gentest.types.int, gentest.types.int]);
// Option #7
var tests = [
{
name: 'addition is commutative',
prop: function(a, b) {
return add(a, b) === add(b, a);
},
argTypes: [gentest.types.int, gentest.types.int]
}
];
// Option #8
var prop_isCommutative = function(a, b) {
return add(a, b) === add(b, a);
};
gentest.run(prop_isCommutative,
gentest.types.int,
gentest.types.int);
// Option #9a
forAll({a: Number, b: Number}, function() {
return add(this.a, this.b) === add(this.b, this.a);
});
// Option #9b
forAll({a: Number, b: Number}, function(r) {
return add(r.a, r.b) === add(r.b, r.a);
});
// Option #10
describe('addition', function() {
it('is commutative',
{a: Number, b: Number},
function(r) {
return add(r.a, r.b) === add(r.b, r.a);
}
);
it('is associative',
{a: Number, b: Number, c: Number},
function(r) {
return add(r.a, add(r.b, r.c)) === add(add(r.a, r.b), r.c);
}
);
});
@graue

This comment has been minimized.

Copy link
Owner Author

graue commented Aug 6, 2014

Leaning towards a modification of #9b without abusing built-in constructors (instead of Number, we'll stick to gentest.types.int), and presenting two choices:

var t = gentest.types;

// usage: forAll(obj || array, name, func)

// pass an object, get a context with generated values as attributes
forAll({a: t.int, b: t.int}, 'addition is commutative', function(ctx) {
  var a = ctx.a, b = ctx.b;
  return add(a, b) === add(b, a);
});

// or...
// pass an array, get generated values as arguments
forAll([t.int, t.int], 'addition is commutative', function(a, b) {
  return add(a, b) === add(b, a);
});

Completely a matter of preference. The manual handling of ctx in the first example is crummy boilerplate to have to write, but it's not the end of the world, and the first style will become awesome when using either esnext (once destructuring is added):

forAll({a: t.int, b: t.int}, 'addition is commutative', function({a, b}) {
  return add(a, b) === add(b, a);
});

or CoffeeScript:

forAll {a: t.int, b: t.int}, 'addition is commutative', ({a, b}) ->
  add(a, b) == add(b, a)

So with good sugar on the way, and available already for those willing to use CoffeeScript, I think it's too good to resist offering that option.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.