Unit testing
Inko's standard library provides a module used for writing unit tests:
std.test
. Using this module one writes their unit tests like so:
import std.test.Tests
fn pub tests(t: mut Tests) {
t.test('The name of the test') fn (t) {
t.equal(10, 20)
}
}
Each test can specify one or more expectations to check. If an expectation fails, the failure is recorded and the test continues running. Not aborting the test upon the first failure makes it easier to measure progress and makes the testing process less frustrating, as you aren't shown only the first failure per test.
Tests are run in a randomised order, and concurrently. By default the number of concurrent tests equals the number of available CPU cores, but this can be changed if necessary.
For more information about the testing API, take a look at the source code of
the std.test
module.
In the future Inko will support generating source code documentation, at which point looking at the source code is no longer necessary.
Testing structure
Test files follow the naming convention of test_X.inko
, where X is the name of
the module tested. Tests are to be placed in a directory called test
and
mirror the module hierarchy of the module they are testing. For example, the
tests for the standard library are organised as follows:
std/test/
└── std
├── fs
│ ├── test_dir.inko
│ ├── test_file.inko
│ └── test_path.inko
├── net
│ ├── test_ip.inko
│ └── test_socket.inko
├── test_array.inko
├── test_bool.inko
├── ...
└── test_tuple.inko
Running tests
With these files in place you can run your tests using inko test
. When doing
so, make sure your current working directory is the directory containing the
test
directory, otherwise Inko won't find your unit tests.
The inko test
command supports filtering tests by their name. For example, to
run tests of which the name contains "kittens" you'd run the tests like so:
inko test kittens
You can also filter by a file path, only running the tests in that file:
inko test test_kittens.inko
Testing private types and methods
Following the structure outlined above, you're able to test private types and
methods, as tests and the modules they are testing both exist in the same root
namespace. That is, tests for std.foo
would be located in the module
std.test_foo
, and thus have access to private types and methods defined in any
module under the std
root namespace. This in turn removes the need to mark
types or methods as public just so you can test them.