Repository navigation
Testing
Loky edited this page Oct 13, 2026
·
7 revisions
Last run (v0.17.1): 25 suites, 212 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.
- 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. - Result handlers (
GitotBranchResults,GitotSyncResults,GitotResultRouter) are built withnullpanels and anullengine; a test only drives the paths that never reach them, so a missing guard crashes the test instead of passing silently. - A test that needs a collaborator gets a fake or
null:GitLfsruns on a realGitEnginethat never executes a command (the test emitscommand_completeditself);GitotPushFlowgetsnullfor 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 isGitIgnore, in a scratch folder underuser://, never in the project.
| 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 |
| Suite | Tests | Covers |
|---|---|---|
git_engine_test |
24 |
owner/repo parsing, web_url() (accepted forms, refused unsafe forms), remote-URL decoding, file lists (reliable flag), which commands take the write lock (push and pull yes, fetch and tag push no), branch-name safety, init / remote add, remote URL validation, per-call on_done (callback plus broadcast, also for a refused remote delete) |
git_runner_test |
15 | Log parsing, Windows output re-decoding, shell string and exit marker, shell-safety whitelist, a dropped write still completes (-1), the network write lock, long path lists split in chunks and chunk outputs merged |
git_sync_orchestrator_test |
4 |
plan_push(): normal, behind (blocked, never forced), diverged (force confirmation) |
git_lfs_test |
9 | LFS state machine (no binary, not initialized, ready), transitions, pattern guards, teardown, merge with the upstream list, a failed local read reports failure |
git_ignore_test |
4 | Default .gitignore written only when missing, never overwrites, unwritable folder, template content |
| 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 |
4 | Timeout clamp, pass-through values, confirmations on by default, Output echo on by default |
gitot_logger_test |
2 | The one failure shape: error, git's raw message, hint |
gitot_result_router_test |
10 | Commit summary (file list dropped, hook output skipped), stash and pop lines, a failed status or log repaints nothing, origin state, remote add success and failure |
gitot_branch_results_test |
9 | Every branch command dispatched, silent failed branch list, switch / create / delete failure text, current-branch answer (unborn branch / detached) |
gitot_sync_results_test |
11 | Every sync command dispatched, push / pull / force-push lines, label fallbacks, failure shape, timeout hint, a pull moves HEAD and a push does not, ahead/behind state, tag push |
gitot_push_flow_test |
2 | No origin asks for a remote; with an origin it does not |
gitot_dock_test |
2 | Focus-in refresh cooldown (3 s), first focus-in is never skipped |
| 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 |
5 | Issues header: repo, open / Bug / High priority counts, no count, before any fetch; github.com-only remote detection; dirty count from the parsed status |
github_issue_parser_test |
1 |
count_where(): exact match only, Urgent is not High, empty list |
- 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, the failed status shown as a clean tree).
- GdUnit runs tests in a separate game process, where
EditorInterfacedoes not exist: a class whose constructor reads the editor theme (GitotStatusTree) cannot be built in a test. Keep the logic in static helpers or plain objects. - 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 emitLFS_VERSIONwith exit 0 orLFS_INSTALL: both makeGitLfsrun one.
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.
- 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.