# Testing signals — google-gemini/gemini-cli

> Canonical page: https://codevetter.com/unpack/gemini-cli/testing-signals

# Testing signals — google-gemini/gemini-cli

Scanned commit d5b3e3accb26000d273abf16e0f1dd83aa5428a9 (2026-09-21). Generated by codevetter codevetter 1.12.0 on 2026-09-22.

Testing is heavy and layered: Vitest 3.2 with colocated *.test.ts(x) unit tests across every package (a large share of scanned TS files are tests), an integration-tests/ workspace running the real built binary (optionally under docker/podman sandbox) with recorded .responses fixtures, evals/ behavioral evals gated behind RUN_EVALS with an llm-judge, plus perf-tests/ and memory-tests/ with baseline updating. CI (ci.yml) enforces lint (eslint+actionlint+shellcheck+yamllint+prettier+sensitive-keywords+action pinning), build, typecheck, per-workspace test:ci, bundle smoke (`node ./bundle/gemini.js --version`), generated-settings-doc freshness, and lockfile checks. Husky+lint-staged run prettier/eslint on commit.
- Unit tests are colocated Vitest files next to sources (e.g. client.test.ts, scheduler.test.ts, extension-manager*.test.ts, App.test.tsx); vitest.config.ts per package; `npm run test` runs --workspaces plus a sea/sea-launch.test.js binary-launch check, and posttest runs a full build. — [package.json#L48-52](https://github.com/google-gemini/gemini-cli/blob/d5b3e3accb26000d273abf16e0f1dd83aa5428a9/package.json#L48-L52) [packages/cli/vitest.config.ts](https://github.com/google-gemini/gemini-cli/blob/d5b3e3accb26000d273abf16e0f1dd83aa5428a9/packages/cli/vitest.config.ts) [sea/sea-launch.test.js](https://github.com/google-gemini/gemini-cli/blob/d5b3e3accb26000d273abf16e0f1dd83aa5428a9/sea/sea-launch.test.js) [packages/core/src/core/client.test.ts](https://github.com/google-gemini/gemini-cli/blob/d5b3e3accb26000d273abf16e0f1dd83aa5428a9/packages/core/src/core/client.test.ts)
- integration-tests/ is a separate vitest root (52+ *.test.ts files) with testTimeout 300000, retry 2, 8-16 threads, globalSetup.ts, GEMINI_TEST_TYPE=integration, and *.responses replay fixtures for browser-agent/hooks/context-compression flows; sandbox variants selected via GEMINI_SANDBOX=none|docker|podman. — [integration-tests/vitest.config.ts](https://github.com/google-gemini/gemini-cli/blob/d5b3e3accb26000d273abf16e0f1dd83aa5428a9/integration-tests/vitest.config.ts) [integration-tests/globalSetup.ts](https://github.com/google-gemini/gemini-cli/blob/d5b3e3accb26000d273abf16e0f1dd83aa5428a9/integration-tests/globalSetup.ts) [package.json#L55-64](https://github.com/google-gemini/gemini-cli/blob/d5b3e3accb26000d273abf16e0f1dd83aa5428a9/package.json#L55-L64) [integration-tests/hooks-system.before-agent.responses](https://github.com/google-gemini/gemini-cli/blob/d5b3e3accb26000d273abf16e0f1dd83aa5428a9/integration-tests/hooks-system.before-agent.responses)
- Fake/recorded model backends are first-class test hooks: --fake-responses/--fake-responses-non-strict load FakeContentGenerator from a file and --record-responses wraps the real generator in RecordingContentGenerator — this is how the .responses fixtures are produced and replayed. — [packages/core/src/core/contentGenerator.ts#L215-228](https://github.com/google-gemini/gemini-cli/blob/d5b3e3accb26000d273abf16e0f1dd83aa5428a9/packages/core/src/core/contentGenerator.ts#L215-L228) [packages/core/src/core/contentGenerator.ts#L417-419](https://github.com/google-gemini/gemini-cli/blob/d5b3e3accb26000d273abf16e0f1dd83aa5428a9/packages/core/src/core/contentGenerator.ts#L417-L419) [packages/core/src/core/fakeContentGenerator.ts](https://github.com/google-gemini/gemini-cli/blob/d5b3e3accb26000d273abf16e0f1dd83aa5428a9/packages/core/src/core/fakeContentGenerator.ts) [packages/core/src/core/recordingContentGenerator.ts](https://github.com/google-gemini/gemini-cli/blob/d5b3e3accb26000d273abf16e0f1dd83aa5428a9/packages/core/src/core/recordingContentGenerator.ts) [packages/cli/src/config/config.ts#L474-489](https://github.com/google-gemini/gemini-cli/blob/d5b3e3accb26000d273abf16e0f1dd83aa5428a9/packages/cli/src/config/config.ts#L474-L489)
- evals/ contains ~30 *.eval.ts behavioral evals (answer-vs-act, plan_mode, prompt_injection_mcp, memory_persistence, model_steering, sandbox_recovery, ...) driven by an llm-judge.ts; only 'always_passing' run by default, all evals need RUN_EVALS=1. — [evals/llm-judge.ts](https://github.com/google-gemini/gemini-cli/blob/d5b3e3accb26000d273abf16e0f1dd83aa5428a9/evals/llm-judge.ts) [evals/vitest.config.ts](https://github.com/google-gemini/gemini-cli/blob/d5b3e3accb26000d273abf16e0f1dd83aa5428a9/evals/vitest.config.ts) [package.json#L53-54](https://github.com/google-gemini/gemini-cli/blob/d5b3e3accb26000d273abf16e0f1dd83aa5428a9/package.json#L53-L54) [evals/prompt_injection_mcp.eval.ts](https://github.com/google-gemini/gemini-cli/blob/d5b3e3accb26000d273abf16e0f1dd83aa5428a9/evals/prompt_injection_mcp.eval.ts) [docs/behavioral-evals.md](https://github.com/google-gemini/gemini-cli/blob/d5b3e3accb26000d273abf16e0f1dd83aa5428a9/docs/behavioral-evals.md)
- perf-tests/ and memory-tests/ are dedicated vitest roots with baseline files updated via UPDATE_PERF_BASELINES/UPDATE_MEMORY_BASELINES env flags, plus memory-nightly.yml and perf-nightly.yml scheduled workflows. — [package.json#L59-62](https://github.com/google-gemini/gemini-cli/blob/d5b3e3accb26000d273abf16e0f1dd83aa5428a9/package.json#L59-L62) [.github/workflows/perf-nightly.yml](https://github.com/google-gemini/gemini-cli/blob/d5b3e3accb26000d273abf16e0f1dd83aa5428a9/.github/workflows/perf-nightly.yml) [.github/workflows/memory-nightly.yml](https://github.com/google-gemini/gemini-cli/blob/d5b3e3accb26000d273abf16e0f1dd83aa5428a9/.github/workflows/memory-nightly.yml)
- CI runs a lint battery beyond eslint: scripts/lint.js --setup/--eslint/--actionlint/--shellcheck/--yamllint/--prettier/--sensitive-keywords/--check-github-actions-pinning, then build, typecheck, settings-doc regeneration check (docs:settings --check), and lockfile integrity. — [.github/workflows/ci.yml#L89-125](https://github.com/google-gemini/gemini-cli/blob/d5b3e3accb26000d273abf16e0f1dd83aa5428a9/.github/workflows/ci.yml#L89-L125) [scripts/lint.js](https://github.com/google-gemini/gemini-cli/blob/d5b3e3accb26000d273abf16e0f1dd83aa5428a9/scripts/lint.js)
- CI test matrix splits jobs by workspace: `npm run test:ci --workspace @google/gemini-cli` on one runner and core+a2a-server+vscode-ide-companion+test-utils (with coverage disabled) on another, followed by bundle verification `node ./bundle/gemini.js --version`. — [.github/workflows/ci.yml#L188-201](https://github.com/google-gemini/gemini-cli/blob/d5b3e3accb26000d273abf16e0f1dd83aa5428a9/.github/workflows/ci.yml#L188-L201) [.github/workflows/ci.yml#L279-292](https://github.com/google-gemini/gemini-cli/blob/d5b3e3accb26000d273abf16e0f1dd83aa5428a9/.github/workflows/ci.yml#L279-L292)
- A deflake harness exists (scripts/deflake.js + deflake.yml workflow + RUN_FLAKY_INTEGRATION flag) specifically to rerun integration suites, signalling acknowledged flaky e2e coverage. — [package.json#L24-26](https://github.com/google-gemini/gemini-cli/blob/d5b3e3accb26000d273abf16e0f1dd83aa5428a9/package.json#L24-L26) [package.json#L57](https://github.com/google-gemini/gemini-cli/blob/d5b3e3accb26000d273abf16e0f1dd83aa5428a9/package.json#L57) [.github/workflows/deflake.yml](https://github.com/google-gemini/gemini-cli/blob/d5b3e3accb26000d273abf16e0f1dd83aa5428a9/.github/workflows/deflake.yml)
- Test infrastructure deps include msw (HTTP mocking), mock-fs/memfs (fs virtualization), react-devtools-core, and a dedicated @google/gemini-cli-test-utils workspace; ink is replaced with a fork (@jrichman/ink) via npm overrides to make TUI testable. — [package.json#L81-91](https://github.com/google-gemini/gemini-cli/blob/d5b3e3accb26000d273abf16e0f1dd83aa5428a9/package.json#L81-L91) [package.json#L130-152](https://github.com/google-gemini/gemini-cli/blob/d5b3e3accb26000d273abf16e0f1dd83aa5428a9/package.json#L130-L152) [packages/test-utils/package.json](https://github.com/google-gemini/gemini-cli/blob/d5b3e3accb26000d273abf16e0f1dd83aa5428a9/packages/test-utils/package.json)
- eslint-plugin-headers enforces the Google Apache license header on source files, and lint-staged runs prettier+eslint --fix on commit via husky hooks. — [package.json#L126](https://github.com/google-gemini/gemini-cli/blob/d5b3e3accb26000d273abf16e0f1dd83aa5428a9/package.json#L126) [package.json#L172-183](https://github.com/google-gemini/gemini-cli/blob/d5b3e3accb26000d273abf16e0f1dd83aa5428a9/package.json#L172-L183) [packages/cli/index.ts#L1-6](https://github.com/google-gemini/gemini-cli/blob/d5b3e3accb26000d273abf16e0f1dd83aa5428a9/packages/cli/index.ts#L1-L6)
- Coverage gaps visible from the file tree: packages/devtools client has few colocated tests, scripts/ has a separate vitest config, and several heavy paths (sandbox.ts 1431 lines, AppContainer.tsx 2869 lines) have limited direct unit coverage relative to size — integration tests carry much of that weight. (inferred) — [packages/cli/src/utils/sandbox.ts](https://github.com/google-gemini/gemini-cli/blob/d5b3e3accb26000d273abf16e0f1dd83aa5428a9/packages/cli/src/utils/sandbox.ts) [packages/cli/src/ui/AppContainer.tsx](https://github.com/google-gemini/gemini-cli/blob/d5b3e3accb26000d273abf16e0f1dd83aa5428a9/packages/cli/src/ui/AppContainer.tsx) [packages/cli/vitest.config.ts](https://github.com/google-gemini/gemini-cli/blob/d5b3e3accb26000d273abf16e0f1dd83aa5428a9/packages/cli/vitest.config.ts)

Every claim links to its cited files at the pinned commit. Citations identify source evidence; they do not establish runtime correctness. Independent CodeVetter scan — not reviewed by upstream maintainers.

## Public product links

- [CodeVetter](https://codevetter.com/)
- [Download](https://codevetter.com/download)
- [Documentation](https://codevetter.com/docs/)
- [Source](https://github.com/Codevetter/codevetter)
