8000 mini.nvim/doc/mini-test.txt at main · tssm/mini.nvim · GitHub
[go: up one dir, main page]

Skip to content

Latest commit

 

History

History
901 lines (729 loc) · 38.7 KB

mini-test.txt

File metadata and controls

901 lines (729 loc) · 38.7 KB
Table with expectation functions
Each function has the following behavior:
- Silently returns `true` if expectation is fulfilled.
- Throws an informative error with information helpful for debugging.
Mostly designed to be used within 'mini.test' framework.
Usage~
>
local x = 1 + 1
MiniTest.expect.equality(x, 2) -- passes
MiniTest.expect.equality(x, 1) -- fails
------------------------------------------------------------------------------
*MiniTest.expect.equality()*
`MiniTest.expect.equality`({left}, {right})
Expect equality of two objects
Equality is tested via |vim.deep_equal()|.
Parameters~
{left} `(any)` First object.
{right} `(any)` Second object.
------------------------------------------------------------------------------
*MiniTest.expect.no_equality()*
`MiniTest.expect.no_equality`({left}, {right})
Expect no equality of two objects
Equality is tested via |vim.deep_equal()|.
Parameters~
{left} `(any)` First object.
{right} `(any)` Second object.
------------------------------------------------------------------------------
*MiniTest.expect.error()*
`MiniTest.expect.error`({f}, {pattern}, {...})
Expect function call to raise error
Parameters~
{f} `(function|table)` Callable to be tested for raising error.
{pattern} `(string|nil)` Pattern which error message should match.
Use `nil` or empty string to not test for pattern matching.
{...} `(any)` Extra arguments with which `f` will be called.
------------------------------------------------------------------------------
*MiniTest.expect.no_error()*
`MiniTest.expect.no_error`({f}, {...})
Expect function call to not raise error
Parameters~
{f} `(function|table)` Callable to be tested for raising error.
{...} `(any)` Extra arguments with which `f` will be called.
------------------------------------------------------------------------------
*MiniTest.expect.reference_screenshot()*
`MiniTest.expect.reference_screenshot`({screenshot}, {path}, {opts})
Expect equality to reference screenshot
Parameters~
{screenshot} `(table|nil)` Array with screenshot information. Usually an output
of `child.get_screenshot()` (see |MiniTest-child-neovim.get_screenshot()|).
If `nil`, expectation passed.
{path} `(string|nil)` Path to reference screenshot. If `nil`, constructed
automatically in directory 'tests/screenshots' from current case info and
total number of times it was called inside current case. If there is no
file at `path`, it is created with content of `screenshot`.
{opts} `(table|nil)` Options:
- <force> - whether to forcefuly create reference screenshot.
Temporary useful during test writing. Default: `false`.
------------------------------------------------------------------------------
*MiniTest.new_expectation()*
`MiniTest.new_expectation`({subject}, {predicate}, {fail_context})
Create new expectation function
Helper for writing custom functions with behavior similar to other methods
of |MiniTest.expect|.
Parameters~
{subject} `(string|function|table)` Subject of expectation. If callable,
called with expectation input arguments to produce string value.
{predicate} `(function|table)` Predicate callable. Called with expectation
input arguments. Output `false` or `nil` means failed expectation.
{fail_context} `(string|function|table)` Information about fail. If callable,
called with expectation input arguments to produce string value.
Return~
`(function)` Expectation function.
Usage~
>
local expect_truthy = MiniTest.new_expectation(
'truthy',
function(x) return x end,
function(x) return 'Object: ' .. vim.inspect(x) end
)
------------------------------------------------------------------------------
*MiniTest.gen_reporter*
`MiniTest.gen_reporter`
Table with pre-configured report generators
Each element is a function which returns reporter - table with callable
`start`, `update`, and `finish` fields.
------------------------------------------------------------------------------
*MiniTest.gen_reporter.buffer()*
`MiniTest.gen_reporter.buffer`({opts})
Generate buffer reporter
This is a default choice for interactive (not headless) usage. Opens a window
with dedicated non-terminal buffer and updates it with throttled redraws.
Opened buffer has the following helpful Normal mode mappings:
- `<Esc>` - stop test execution if executing (see |MiniTest.is_executing()|
and |MiniTest.stop()|). Close window otherwise.
- `q` - same as `<Esc>` for convenience and compatibility.
General idea:
- Group cases by concatenating first `opts.group_depth` elements of case
description (`desc` field). Groups by collected files if using default values.
- In `start()` show some stats to know how much is scheduled to be executed.
- In `update()` show symbolic overview of current group and state of current
case. Each symbol represents one case and its state:
- `?` - case didn't finish executing.
- `o` - pass.
- `O` - pass with notes.
- `x` - fail.
- `X` - fail with notes.
- In `finish()` show all fails and notes ordered by case.
Parameters~
{opts} `(table|nil)` Table with options. Used fields:
- <group_depth> - number of first elements of case description (can be zero)
used for grouping. Higher values mean higher granularity of output.
Default: 1.
- <throttle_delay> - minimum number of milliseconds to wait between
redrawing. Reduces screen flickering but not amount of computations.
Default: 10.
- <window> - definition of window to open. Can take one of the forms:
- Callable. It is called expecting output to be target window id
(current window is used if output is `nil`). Use this to open in
"normal" window (like `function() vim.cmd('vsplit') end`).
- Table. Used as `config` argument in |nvim_open_win()|.
Default: table for centered floating window.
------------------------------------------------------------------------------
*MiniTest.gen_reporter.stdout()*
`MiniTest.gen_reporter.stdout`({opts})
Generate stdout reporter
This is a default choice for headless usage. Writes to `stdout`. Uses
coloring ANSI escape sequences to make pretty and informative output
(should work in most modern terminals and continuous integration providers).
It has same general idea as |MiniTest.gen_reporter.buffer()| with slightly
less output (it doesn't overwrite previous text) to overcome typical
terminal limitations.
Parameters~
{opts} `(table|nil)` Table with options. Used fields:
- <group_depth> - number of first elements of case description (can be zero)
used for grouping. Higher values mean higher granularity of output.
Default: 1.
- <quit_on_finish> - whether to quit after finishing test execution.
Default: `true`.
------------------------------------------------------------------------------
*MiniTest.new_child_neovim()*
`MiniTest.new_child_neovim`()
Create child Neovim process
This creates an object designed to be a fundamental piece of 'mini.test'
methodology. It can start/stop/restart a separate (child) Neovim process in
full (non-headless) mode together with convenience helpers to interact with
it through |RPC| messages.
For more information see |MiniTest-child-neovim|.
Return~
`child` Object of |MiniTest-child-neovim|.
Usage~
>
-- Initiate
local child = MiniTest.new_child_neovim()
child.start()
-- Use API functions
child.api.nvim_buf_set_lines(0, 0, -1, true, { 'Line inside child Neovim' })
-- Execute Lua code, Vimscript commands, etc.
child.lua('_G.n = 0')
child.cmd('au CursorMoved * lua _G.n = _G.n + 1')
child.type_keys('l')
print(child.lua_get('_G.n')) -- Should be 1
-- Use other `vim.xxx` Lua wrappers (executed inside child process)
vim.b.aaa = 'current process'
child.b.aaa = 'child process'
print(child.lua_get('vim.b.aaa')) -- Should be 'child process'
-- Always stop process after it is not needed
child.stop()
------------------------------------------------------------------------------
*MiniTest-child-neovim*
Child class
It offers a great set of tools to write reliable and reproducible tests by
allowing to use fresh process in any test action. Interaction with it is done
through |RPC| protocol.
Although quite flexible, at the moment it has certain limitations:
- Doesn't allow using functions or userdata for child's both inputs and
outputs. Usual solution is to move computations from current Neovim process
to child process. Use `child.lua()` and `child.lua_get()` for that.
- When writing tests, it is common to end up with "hanging" process: it
stops executing without any output. Most of the time it is because Neovim
process is "blocked", i.e. it waits for user input and won't return from
other call (like `child.api.nvim_exec_lua()`). Common causes are active
|hit-enter-prompt| (increase prompt height to a bigger value) or
Operator-pending mode (exit it). To mitigate this experience, most helpers
will throw an error if its immediate execution will lead to hanging state.
Also in case of hanging state try `child.api_notify` instead of `child.api`.
Notes:
- An important type of field is a "redirection table". It acts as a
convenience wrapper for corresponding `vim.*` table. Can be used both to
return and set values. Examples:
- `child.api.nvim_buf_line_count(0)` will execute
`vim.api.nvim_buf_line_count(0)` inside child process and return its
output to current process.
- `child.bo.filetype = 'lua'` will execute `vim.bo.filetype = 'lua'`
inside child process.
They still have same limitations listed above, so are not perfect. In
case of a doubt, use `child.lua()`.
- Almost all methods use |vim.rpcrequest()| (i.e. wait for call to finish and
then return value). See for `*_notify` variant to use |vim.rpcnotify()|.
- All fields and methods should be called with `.`, not `:`.
Class~
{child}
Fields~
{start} `(function)` Start child process. See |MiniTest-child-neovim.start()|.
{stop} `(function)` Stop current child process.
{restart} `(function)` Restart child process: stop if running and then
start a new one. Takes same arguments as `child.start()` but uses values
from most recent `start()` call as defaults.
{type_keys} `(function)` Emulate typing keys.
See |MiniTest-child-neovim.type_keys()|. Doesn't check for blocked state.
{cmd} `(function)` Execute Vimscript code from a string.
A wrapper for |nvim_exec()| without capturing output.
{cmd_capture} `(function)` Execute Vimscript code from a string and
capture output. A wrapper for |nvim_exec()| with capturing output.
{lua} `(function)` Execute Lua code. A wrapper for |nvim_exec_lua()|.
{lua_get} `(function)` Execute Lua code and return result. A wrapper
for |nvim_exec_lua()| but prepends string code with `return`.
{is_blocked} `(function)` Check whether child process is blocked.
{is_running} `(function)` Check whether child process is currently running.
{ensure_normal_mode} `(function)` Ensure normal mode.
{get_screenshot} `(function)` Returns table with two "2d arrays" of single
characters representing what is displayed on screen and how it looks.
{job} `(table|nil)` Information about current job. If `nil`, child is not running.
{api} `(table)` Redirection table for `vim.api`. Doesn't check for blocked state.
{api_notify} `(table)` Same as `api`, but uses |vim.rpcnotify()|.
{diagnostic} `(table)` Redirection table for |vim.diagnostic|.
{fn} `(table)` Redirection table for |vim.fn|.
{highlight} `(table)` Redirection table for `vim.highlight` (|lua-highlight)|.
{json} `(table)` Redirection table for `vim.json`.
{loop} `(table)` Redirection table for |vim.loop|.
{lsp} `(table)` Redirection table for `vim.lsp` (|lsp-core)|.
{mpack} `(table)` Redirection table for |vim.mpack|.
{spell} `(table)` Redirection table for |vim.spell|.
{treesitter} `(table)` Redirection table for |vim.treesitter|.
{ui} `(table)` Redirection table for `vim.ui` (|lua-ui|). Currently of no
use because it requires sending function through RPC, which is impossible
at the moment.
{g} `(table)` Redirection table for |vim.g|.
{b} `(table)` Redirection table for |vim.b|.
{w} `(table)` Redirection table for |vim.w|.
{t} `(table)` Redirection table for |vim.t|.
{v} `(table)` Redirection table for |vim.v|.
{env} `(table)` Redirection table for |vim.env|.
{o} `(table)` Redirection table for |vim.o|.
{go} `(table)` Redirection table for |vim.go|.
{bo} `(table)` Redirection table for |vim.bo|.
{wo} `(table)` Redirection table for |vim.wo|.
------------------------------------------------------------------------------
*MiniTest-child-neovim.start()*
child.start(args, opts)~
Start child process and connect to it. Won't work if child is already running.
Parameters~
{args} `(table)` Array with arguments for executable. Will be prepended
with `{'--clean', '-n', '--listen', <some address>}` (see |startup-options|).
{opts} `(table|nil)` Options:
- <nvim_executable> - name of Neovim executable. Default: |v:progpath|.
- <connection_timeout> - stop trying to connect after this amount of
milliseconds. Default: 5000.
Usage~
>
child = MiniTest.new_child_neovim()
-- Start default clean Neovim instance
child.start()
-- Start with custom 'init.lua' file
child.start({ '-u', 'scripts/minimal_init.lua' })
------------------------------------------------------------------------------
*MiniTest-child-neovim.type_keys()*
child.type_keys(wait, ...)~
Basically a wrapper for |nvim_input()| applied inside child process.
Differences:
- Can wait after each group of characters.
- Raises error if typing keys resulted into error in child process (i.e. its
|v:errmsg| was updated).
- Key '<' as separate entry may not be escaped as '<LT>'.
Parameters~
{wait} `(number|nil)` Number of milliseconds to wait after each entry. May be
omitted, in which case no waiting is done.
{...} `(string|table<number,string>)` Separate entries for |nvim_input()|,
after which `wait` will be applied. Can be either string or array of strings.
Usage~
>
-- All of these type keys 'c', 'a', 'w'
child.type_keys('caw')
child.type_keys('c', 'a', 'w')
child.type_keys('c', { 'a', 'w' })
-- Waits 5 ms after `c` and after 'w'
child.type_keys(5, 'c', { 'a', 'w' })
-- Special keys can also be used
child.type_keys('i', 'Hello world', '<Esc>')
------------------------------------------------------------------------------
*MiniTest-child-neovim.get_screenshot()*
child.get_screenshot()~
Compute what is displayed on (default TUI) screen and how it is displayed.
This basically calls |screenstring()| and |screenattr()| for every visible
cell (row from 1 to 'lines', column from 1 to 'columns').
Notes:
- Due to implementation details of `screenstring()` and `screenattr()` in
Neovim<=0.7, this function won't recognize floating windows displayed on
screen. It will throw an error if there is a visible floating window. Use
Neovim>=0.8 (current nightly) to properly handle floating windows. Details:
- https://github.com/neovim/neovim/issues/19013
- https://github.com/neovim/neovim/pull/19020
- To make output more portable and visually useful, outputs of
`screenattr()` are coded with single character symbols. Those are taken from
94 characters (ASCII codes between 33 and 126), so there will be duplicates
in case of more than 94 different ways text is displayed on screen.
Return~
`(table|nil)` Screenshot table with the following fields:
- <text> - "2d array" (row-column) of single characters displayed at
particular cells.
- <attr> - "2d array" (row-column) of symbols representing how text is
displayed (basically, "coded" appearance/highlighting). They should be
used only in relation to each other: same/different symbols for two
cells mean same/different visual appearance. Note: there will be false
positives if there are more than 94 different attribute values.
It also can be used with `tostring()` to convert to single string (used
for writing to reference file). It results into two visual parts
(separated by empty line), for `text` and `attr`. Each part has "ruler"
above content and line numbers for each line.
Returns `nil` if couldn't get a reasonable screenshot.
Usage~
>
local screenshot = child.get_screenshot()
-- Show character displayed row=3 and column=4
print(screenshot.text[3][4])
-- Convert to string
tostring(screenshot)
vim:tw=78:ts=8:noet:ft=help:norl:
0