Skip to content

Testing

Loky edited this page Oct 12, 2026 · 7 revisions

Testing

Last run (v0.17.0): 22 suites, 179 tests, 0 failures (Godot 4.7.2, Windows).

Two layers: automated tests for the pure logic (GdUnit4: no real git process, no scene) and a manual regression checklist for everything that needs the editor or a real remote.

How the code is made testable

  • Parsers and helpers are static or RefCounted: text in, data out (GitStatusParser, GitDiffParser, GitEngine.web_url(), GitotUi.sync_symbol()...).
  • Panels take their widgets by constructor injection, and their text rules are static helpers (GitotBranchPanel, GitotLfsPanel, GithubPanel._header_text()), so the wording is tested without building a scene.
  • A test that needs a collaborator gets a fake or null: GitLfs runs on a real GitEngine that never executes a command (the test emits command_completed itself); GitotPushFlow gets null for the engine, orchestrator and tag panel, because the code under test never reaches them.
  • Nothing touches your global git config, your git lfs install, the network or a real repository. The only disk I/O is GitIgnore, in a scratch folder under user://, never in the project.

Run

  1. Install GdUnit4 and enable it.
  2. Open the GdUnit4 panel, select res://test/, Run. A single suite can be run from its file's context menu.
  3. After adding a test file, open the project once: Godot creates its .uid file. Commit it with the test.
  4. After any change to the plugin lifecycle, close and reopen the whole editor before testing (hot-reload is not enough).

Automated: what each suite covers

Parsers (git output to data)

Suite Tests Covers
git_status_parser_test 11 status --porcelain=v2: untracked, staged / unstaged / both, deleted, conflict, spaces, quoted non-ASCII paths, ignored and malformed lines
git_diff_parser_test 14 Gutter hunks (added, modified, pure deletion), full diff viewer (hunks, files, malformed headers, a content line that looks like a file header), --name-status
git_log_parser_test 4 Entries, order, malformed lines, blank input
git_branch_parser_test 8 Current / other / remote branches, the origin/HEAD alias skipped, separator inside a subject, order
git_stash_parser_test 8 Custom and default (WIP) subjects, index from the selector, slashes and colons in names, a malformed line does not shift indices
git_lfs_parser_test 18 ls-files --json (local, pointer-only, defaults, non-ASCII), .gitattributes patterns (CRLF, empty), local / remote merge by oid, summary counts and sizes
git_path_test 9 Git's quoted paths to real UTF-8: octal bytes, tab, quote, backslash, empty

Engine, runner, planning

Suite Tests Covers
git_engine_test 19 owner/repo parsing, web_url() (accepted forms, refused unsafe forms), remote-URL decoding, file lists (reliable flag), which commands take the write lock, branch-name safety, init / remote add, remote URL validation
git_runner_test 8 Log parsing, Windows output re-decoding, shell string and exit marker, shell-safety whitelist
git_sync_orchestrator_test 4 plan_push(): normal, behind (blocked, never forced), diverged (force confirmation)
git_lfs_test 8 LFS state machine (no binary, not initialized, ready), transitions, pattern guards, teardown, merge with the upstream list
git_ignore_test 4 Default .gitignore written only when missing, never overwrites, unwritable folder, template content

State, settings, messages

Suite Tests Covers
gitot_repo_state_test 6 Sync state, changed signal only on a real change, no-origin default, label fallbacks
gitot_settings_test 3 Timeout clamp, pass-through values, confirmations on by default
gitot_logger_test 2 The one failure shape: error, git's raw message, hint
gitot_result_router_test 15 Result lines (commit, push, pull, stash), fallbacks, failure text, silent failed branch list, current-branch answer (unborn branch / detached), origin state, remote add success and failure
gitot_push_flow_test 2 No origin asks for a remote; with an origin it does not

UI text and rules (no scene)

Suite Tests Covers
gitot_ui_test 14 Sync key / symbol / color / counts / tooltips, ellipsize, scope label, push tooltip, amend confirmation texts
gitot_branch_panel_test 12 Fold title, row annotation (local / remote copy), status text with counts, sync tooltips
gitot_lfs_panel_test 6 State text, setup steps, dashboard stats (empty, zero counters, bracket escaping)
github_panel_test 3 Issues header: repo, open / Bug / High priority counts, no count, before any fetch
github_issue_parser_test 1 count_where(): exact match only, Urgent is not High, empty list

Conventions

  • One file per class: test/<class_snake_case>_test.gd, extends GdUnitTestSuite, a header comment saying what the suite covers.
  • One behavior per test, named for it (test_behind_only_is_blocked_never_forced), not for the function.
  • A bug fix comes with the test that would have caught it (the failed branch list that crashed outside a repository, the unborn branch shown as detached).
  • Security rules are tested from both sides, accepted and refused inputs: remote URLs, branch names, shell arguments, web_url() (no token in a link).
  • No test may start a real git process. In git_lfs_test, never emit LFS_VERSION with exit 0 or LFS_INSTALL: both make GitLfs run one.

Manual

The editor flows are checked by hand with a regression-checklist before each release: lifecycle, stage, commit / sync, no repository / first push (Initialize repository, remote URL prompt), status line link, stash, branches, tags, history, gutter, GitHub Issues (including the header counts), output messages, settings.

Not covered

  • Git LFS against a real LFS remote (Install LFS, real push / pull / prune, the not-installed views).
  • Git older than 2.32, and a project inside a repository subfolder.
  • Linux, macOS, and code pages other than Windows-1252.

Clone this wiki locally