This unit test framework is just in its infancy. Although it is, on its surface, heaviliy inspired by Jest, I have no intentions of making a Jest implementation in Pike. Jest has more than 1,100 contributors and probably a couple of 100,000 lines of code.
Clone this repository and symlink it into your PIKE_MODULE_PATH
as
Pest.pmod
(or point to it with the Pike -M
argument).
Create a directory named test
(or call it what ever you like). Create a
test-runner file in this directory (it can be called whatever), but for the
sake of this example lets call it run-tests.pike
, which only needs to
inherit Pest.Main
.
# test/run-test.pike
inherit Pest.Main;
By default Pest.Main
will scan for files ending in *.spec.pike
, but what
file names to scan for can be given as option to Pest.Main
via the
-f|--file
option, which takes a glob
. You can also choose to run specific
tests based on their description by passing the -t|--test
option, which also
takes a glob
.
You can also pass the -v|--verbose
option to Pest.Main
to ge a more verbose
test report output.
So these are the default options to Pest.Main
:
-f|--file glob What files to treat as test files.
-t|--test glob What tests to run (matching test description)
-v|--verbose More verbose test result output
Ok, so now lets add a test-suite file to the test
directory.
# test/readme.spec.pike
import Pest;
// A test suite file must have a main method
int main() {
// ... that of the time of writing serves no great purpose
describe("This is a namespace/block", lambda () {
test("Expect some stuff to be 'truthy'", lambda () {
expect(true)->to_be_truthy();
expect(1)->to_be_truthy();
expect("a")->to_be_truthy();
});
test("Expect some stuff to be 'falsy'", lambda () {
expect(false)->to_be_falsy();
expect(0)->to_be_falsy();
expect(UNDEFINED)->to_be_falsy();
});
test("Expect some stuff to be the same (by reference)", lambda () {
mapping a = ([]);
mapping b = a;
expect(a)->to_be(b);
});
test("Expect some stuff to be the same (by value)", lambda () {
mapping a = ([ "index": 1, "value": "one" ]);
mapping b = ([ "index": 1, "value": "one" ]);
expect(a)->to_equal(b);
});
test("Expect some callback to have been called", lambda () {
void call_it(function cb) {
cb();
};
function my_callback = fn(lambda() {});
call_it(my_callback);
call_it(my_callback);
expect(my_callback)->to_have_been_called();
expect(my_callback)->to_have_been_called_n_times(2);
});
});
}
The result of running test/run-test.pike
should give an output like:
$~: pike __dev__/run.pike
Test suites: 1
Tests: 5
Running tests in "/path/to/project/test/readme.spec.pike"
Done
------------------------------------------------------------------------------
Ran 5 tests in 1 test-suite
5 tests succeeded, 0 tests failed
Ran all tests in 0.02100 seconds
------------------------------------------------------------------------------
Now, lets imagine a test fails (I mean it's just theoretical thougt), then the output would look something like:
Test suites: 1
Tests: 5
Running tests in "/path/to/project/test/readme.spec.pike"
Done
==============================================================================
1 test failed in "/path/to/project/test/readme.spec.pike"
@test: Expect some stuff to be 'falsy' (/path/to/project/test/readme.spec.pike:17)
Expected: "undefined"
Received: 1
15: test("Expect some stuff to be 'falsy'", lambda () {
16: expect(false)->to_be_falsy();
17: expect(1)->to_be_falsy();
: -----------------^^^^^^^^^^^
18: expect(UNDEFINED)->to_be_falsy();
19: });
------------------------------------------------------------------------------
Ran 5 tests in 1 test-suite
4 tests succeeded, 1 test failed
Ran all tests in 0.03000 seconds
------------------------------------------------------------------------------
If you want to skip certain tests or all tests in a certain describe()
-block
you can prefix those test()
s and describe()
s with skip->
:
skip->describe("Not yet ready...", lambda() { ... });
describe("Some other tests", lambda () {
// Skip for now, network stuff prohibits this from succeeding.
skip->test("Yadda", lambda() {});
});
-
Atm all tests and test-suites are run synchronously.
-
These are the implemented methods on
expect(expr)
-
->to_be_truthy()
: Checks that a value is "defined", which in Pike terms pretty much is anything not0
. -
->to_be_falsy()
: The inverse of the above. -
->to_equal(x)
: Checks that the arguments equals eachother by value. -
->to_be(x)
: Checks that the arguments are the same by reference. For primitive types this is the same as->to_equal()
. -
->to_have_been_called()
: Checks that a function has been called. The function given toexpect()
must be of typePest.Fn
(can be created via the "factory method"Pest.fn(callback)
). -
->to_have_been_called_n_times(n)
: Same as above except it checks if the function was called exactlyn
times. -
->to_throw(string|void)
: Expect the expression to throw an error. If a string is given as argument that should be the message of the thrown error. NOTE!expect()
must be given alambda () {}
wrapping the expression for this to work:expect(lambda() { throwing_expr(); })->to_throw();
-