Skip to content

test: add automated test framework and CI foundation - #25

Merged
uhs-robert merged 3 commits into
mainfrom
test/framework
Sep 10, 2026
Merged

uhs-robert merged 3 commits into
mainfrom
test/framework

Conversation

@uhs-robert

Copy link
Copy Markdown
Owner

Summary

Implements #24: a lightweight, dependency-free test harness plus CI, so the open feature PRs have somewhere to put their regression coverage.

  • adds describe/it, deep-equality and error assertions, and a result reporter
  • adds a stub module for the system-facing calls (vim.fn.system, vim.fn.executable, vim.system, vim.notify), restored per case
  • adds a runner exiting non-zero on failure: nvim -l tests/run.lua, wrapped as make test
  • adds make test PATTERN=<substring> to run a subset
  • runs the suite and stylua --check on every pull request
  • documents the harness, stubs, and how to add coverage in tests/README.md

Design

The harness runs inside headless Neovim via nvim -l, so the real vim API is available and only the handful of calls that reach the operating system need stubbing. That keeps the mocking surface small: a spec stubs the mount table or an SSH subprocess and calls the module directly.

No external dependency is introduced. Neovim is the only thing CI installs.

Two conventions keep cases isolated: stub.restore_all() undoes stubs at the end of a case, and stub.reload() clears cached sshfs.* modules so memoized state (configuration, SSHFS version detection) does not leak between cases.

Baseline coverage

41 cases against behavior already on main:

  • mount table parsing for Linux fuse.sshfs, macFUSE, and findmnt output, including non-sshfs lines, mounts outside the base directory, and a failing mount command
  • mount directory creation
  • SSH command construction: socket/batch/interactive option sets, tty and login shell handling, tilde expansion, single-quote escaping, ControlMaster teardown
  • ad-hoc host string parsing (user@host:path -p 2222 and its variants)
  • configuration merging and all three deprecation shims
  • remote-to-local path mapping

Follow-up

Feature-specific coverage stays with each feature PR, as those PRs describe. Once this lands, #20, #21, #22, and #23 pick it up and add their own regression suites.

Closes #24

Adds a dependency-free unit test harness that runs inside headless
Neovim, plus regression coverage for the behavior that exists on main.

The harness provides describe/it, deep-equality and error assertions,
and a runner (`nvim -l tests/run.lua`, wrapped as `make test`) that
exits non-zero on failure so CI can gate on it. A stub module replaces
the handful of system-facing calls the plugin makes (vim.fn.system,
vim.fn.executable, vim.system, vim.notify) and restores them per case,
so no test contacts a real SSH server or mount table.

Baseline suites cover mount table parsing for Linux fuse.sshfs, macFUSE
and findmnt output, mount directory creation, SSH command construction
including tilde expansion and quote escaping, ad-hoc host string
parsing, configuration merging with its deprecation shims, and remote
path mapping.

CI runs the suite and stylua --check on every pull request.

Refs #24
A call under test can return more than one value, and keeping only the
first silently turned assertions on the later ones into assertions on
nil.
A case that failed before its own restore_all left vim.fn stubs active for
every later case in the process, so one real failure cascaded into unrelated
false failures. The runner-level cleanup ran far too late to prevent it.
@uhs-robert
uhs-robert marked this pull request as ready for review September 10, 2026 22:55
@uhs-robert
uhs-robert merged commit b3b2f9a into main Sep 10, 2026
2 checks passed
@uhs-robert
uhs-robert deleted the test/framework branch September 10, 2026 22:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

test: add automated test framework and regression coverage

1 participant