Property testing in Javascript
Make
make
Test
Runs the tests in priv/*.js
make test
Running
Then you can try running the properjs command in the properjs repository:
./properjs PATH/TO/file.js Object
./properjs PATH/TO/file.js Object PATH/TO/include.js 0 PATH/TO/otherfile.js OtherObject
where PATH/TO/file.js is a source file for your code,
Object.props is how properjs discovers its properties,
and 0 denotes a source file without any properties defined
By default running properjs with no arguments runs the Proper.prop properties.
Example
Given that reversing a reversed string should always be the same, we can write a test that asserts this behaviour.
// string.js
String.prototype.reverse = function() {
return this.split("").reverse().join("");
};
String.props = {
reverse: function() {
return FORALL(string(),
function(s) {
assert.equal(s, s.reverse().reverse());
}
);
}
};Then run it with:
./properjs string.js String
Compiling to use QuviQ QuickCheck
By default PropEr is used, but to compile to use your system's QuviQ QuickCheck installation compile with:
make cleanebin compile_eqc
Supported Types/Generators/Properties
FORALL(type(), type(), ..., function(v1, v2, ...) { return $boolean() | undefined })
Each argument to FORALL before the last function argument is a
generator for a type that will then be passed to your function.
Needs to return true or undefined on success and false on test
failure.
var myprop = FORALL(integer(), integer(), integer(),
function(one, two, three) {
assert.equal(typeof one, 'number');
assert.equal(typeof two, 'number');
assert.equal(typeof three, 'number');
return true; // optional due to being synonymous with undefined
}
);LET(type(), type(), ..., function(v1, v2, ...) { return new_value })
Allows you to define a custom type based on others. The function needs to return the generated value for your new type.
An even number generator would required an integer and multiple it by 2.
function even_number() {
return LET(integer(),
function(i) {
return i * 2;
}
);
}SUCHTHAT(type(), function(v) { return $boolean() })
Returns the value generated by type() if the condition function returns
true. Otherwise the value will be skipped and a new one generated.
There is a hard limit on the number of suchthat attempts that is not yet
configurable via javascript.
function even_number() {
return SUCHTHAT(integer(),
function(i) {
return i % 2 == 0;
}
);
}The example of even_number() using a LET is prefered over this example
since it does not throw away any generated values.
oneof(type(), type(), ...) oneof(array(type()))
Returns a randomly selection member of its arguments or the first element if there is only one and it is a list.
function board_size() {
return oneof(9, 13, 19);
}
// equivalent to the above
function board_size() {
return oneof([9, 13, 19]);
}Basic Types
integer()integer(integer(), integer())generates an integer between its two arguments (inclusive)pos_integer()positive integerneg_integer()negative integernon_neg_integer()positive integer or0$float()$float($float(), $float())generates a float between its two arguments (inclusive)string()$boolean()trueorfalsestring()array(type())generates an array of its argumentchar_code()
