Testing

Flow

Currently flow tests are aimed to work as unit tests.

If new to zig, it always is a good idea to review the zig tests documentation and also an introduction to testing.

To work with tests you will need to:

Flow tests are placed in the directory test.

Running the tests

To run the full set of tests, inside flow, use f5, which runs a task that invokes:

zig build test

it will work if flow was invoked from the project root, which is the same place that you would normally run the tests when on the terminal.

Run a particular test

To run an specific test use Dtest-filter option with the name of your test, i.e., for the test called test_block_name use:

zig build test -Dtest-filter="test_block_name"

Adding tests

Tests are needed when:

Tests are placed under test directory. Add your test in the file that exercises the functionality and makes proof of it behaving as expected. Maintain the logic test as simple as possible. It’s possible to add additional functions to make the tests readable and extendable though.

public functions are straightforward tested, while there are some conventions for testing private functions.

Testing private functions

Some internal logic of a module can be tested without the need to be exposed to other modules.

In such cases the module that has the logic should provide a pub test_internal, by convention, exposing the target functionalities to be tested.

For example in src/tui/mode/helix.zig, test_internal exposes the private function

fn move_cursor_long_word_right_end(root: Buffer.Root, cursor: *Cursor, metrics: Buffer.Metrics) error{Stop}!void

with

pub const test_internal = struct {
    pub const move_cursor_long_word_right = private.move_cursor_long_word_right;
.
.
.
};

And in test/tests_helix.zig, helix is imported as

const helix = @import("tui").exports.mode.helix;

Later on using the function move_cursor_long_word_right as

try helix.test_internal.move_cursor_long_word_right_end(root, cursor, the_metrics);

In case there is need of a new test file for concern separation, continue to the next section.

Adding a new test file

Three steps are required for adding a new test file:

  1. Create a new test file
  2. Include the test to the set of tests
  3. Optionally, make available a module to the build system for your particular test

Create the test file

Place your test file under test directory, the name should be prefixed with tests_.

For the rest of this section we will use as a sample tests_project_manager.zig.

Include the test file

Tests files are linked via test/tests.zig, import your new test_file alphabetically as in our sample:

pub const project_manager = @import("tests_project_manager.zig");

Import required modules when building tests

In build.zig import the required module under tests.root_module, for the current example:

tests.root_module.addImport("project_manager", project_manager_mod);

Sample of adding a new test file for project manager.

FAQ on tests

I need to test something that requires importing the editor ¿What do I do?

There are two paths from here:

  1. Refactor your code to test the lower level functions
  2. Extend the tests to automate via external tools

Refactor to test lower level functions

Refactor the functions involved in the functionality to make them not rely directly with editor and other higher level components, and test the lower level ones.

For example, in vim NORMAL mode, the key F looks for a character to the left in the same line, if the character is not found it goes to the beginning of the line. In the case of hx NOR mode, the F key looks for a character to the beginning of the file, if found, makes a selection from the initial cursor position to the character found, if not, no selection is made and the cursor is not moved at all.

Given that Helix has that movement and selection functionality, finding the character was the first action and hence the search function is the one tested in test/tests_helix.zig, given that positioning the selection is rather simple compared to looking for the character. It was decided to test the search functionality making it not depend on editor, but only on the cursor, buffer, metrics and context, all of them do not require graphic elements at all.

The group of functions beyond_eol can be seen in this commit and whose tests are here.

Use additional tools to test a running flow session

Use additional tools to invoke the built editor and send keys to it, modify a file and then compare the initial contents of the file and the resulting contents of your file and the expected ones.

If in doubt about how to do something, please ask.