Agent Skillslobehub/lobehub › testing

testing

GitHub

Vitest测试指南,提供运行命令、数据库测试配置及核心原则。指导编写和维护测试,修复失败用例,提升覆盖率,调试测试问题及设置Mock,确保类型检查通过并遵循特定测试规范。

.agents/skills/testing/SKILL.md lobehub/lobehub

Trigger Scenarios

编写或更新测试代码 修复失败的测试用例 提升测试覆盖率 调试测试相关问题 设置测试Mock

Install

npx skills add lobehub/lobehub --skill testing -g -y
More Options

Non-standard path

npx skills add https://github.com/lobehub/lobehub/tree/canary/.agents/skills/testing -g -y

Use without installing

npx skills use lobehub/lobehub@testing

指定 Agent (Claude Code)

npx skills add lobehub/lobehub --skill testing -a claude-code -g -y

安装 repo 全部 skill

npx skills add lobehub/lobehub --all -g -y

预览 repo 内 skill

npx skills add lobehub/lobehub --list

SKILL.md

Frontmatter
{
    "name": "testing",
    "description": "Vitest testing guide. Use when writing or updating tests, fixing failing tests, improving coverage, debugging test issues, or setting up mocks.",
    "user-invocable": false
}

LobeHub Testing Guide

Quick Reference

Commands:

# Run specific test file
bunx vitest run --silent='passed-only' '[file-path]'

# Database package (client-db, PGlite — default, skips BM25/pg_search)
cd packages/database && bunx vitest run --silent='passed-only' '[file]'

# Database package (server-db, Postgres — BM25/pgvector parity, what CI measures coverage in)
cd packages/database && TEST_SERVER_DB=1 bunx vitest run --silent='passed-only' '[file]'

Never run bun run test - it runs all 3000+ tests (~10 minutes).

Database models/repositories: every new file under packages/database/src/models/** or src/repositories/** ships with a sibling __tests__/<name>.test.ts in the same PR. Use the real DB via getTestDB() (integration style), guard BM25/full-text-search blocks with describe.skipIf(!isServerDB), and always test user-isolation. See references/db-model-test.md for setup, schema gotchas, and the client-vs-server-db split.

Test Categories

Category Location Config
Webapp src/**/*.test.ts(x) vitest.config.ts
Packages packages/*/**/*.test.ts packages/*/vitest.config.ts
Desktop apps/desktop/**/*.test.ts apps/desktop/vitest.config.ts

Core Principles

  1. Prefer vi.spyOn over vi.mock - More targeted, easier to maintain
  2. Tests must pass type check - Run bun run type-check after writing tests
  3. After 1-2 failed fix attempts, stop and ask for help
  4. Test behavior, not implementation details
  5. Regression tests for bug fixes - After fixing a bug, add a regression test that fails before the fix and passes after, to prevent recurrence. Skip pure style/CSS fixes (selector, hover, mask, spacing, color) when the only practical assertion would be source-string matching on the stylesheet — that is not a regression test worth shipping.
  6. No new component tests - Only update existing React component tests. Complex logic should be extracted into hooks and tested there instead
  7. All source changes before any test changes - Complete all source file edits first, then update tests in a separate pass. Interleaving disrupts reasoning about the source changes, especially across many files

Basic Test Structure

import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';

beforeEach(() => {
  vi.clearAllMocks();
});

afterEach(() => {
  vi.restoreAllMocks();
});

describe('ModuleName', () => {
  describe('functionName', () => {
    it('should handle normal case', () => {
      // Arrange → Act → Assert
    });
  });
});

Mock Patterns

// ✅ Spy on direct dependencies
vi.spyOn(messageService, 'createMessage').mockResolvedValue('id');

// ✅ Use vi.stubGlobal for browser APIs
vi.stubGlobal('Image', mockImage);
vi.spyOn(URL, 'createObjectURL').mockReturnValue('blob:mock');

// ❌ Avoid mocking entire modules globally
vi.mock('@/services/chat'); // Too broad

UI Library Mocks (@lobehub/ui/base-ui)

Default: do NOT mock @lobehub/ui/base-ui — render the real components. vitest.config.mts redirects the library's internal MotionProvider to a static stub (tests/mocks/lobehubUiMotionProvider.tsx), so base-ui components render in tests without the app-level ConfigProvider. Please wrap your app with <ConfigProvider> (or <MotionProvider>) in a test means that redirect is not in effect (e.g. a package-local vitest config) — do not fix it by hand-mocking every component.

When a test genuinely wants simplified DOM, compose the canonical stubs over the real module instead of writing a closed factory (closed factories break whenever the library migrates a component's import path):

vi.mock('@lobehub/ui/base-ui', async (importOriginal) => ({
  ...(await importOriginal<object>()),
  ...(await import('~base-ui-stubs')).baseUiStubs,
}));

~base-ui-stubs (tests/mocks/baseUiStubs.tsx) covers ActionIcon / Button / Text / Tag / Avatar / Alert / toast / confirmModal / createModal with standard aria semantics. A per-file factory is still fine when assertions need bespoke testid conventions — but keep it composed over importOriginal so unknown exports never go missing.

Detailed Guides

See references/ for specific testing scenarios:

  • Database Model testing: references/db-model-test.md
  • Electron IPC testing: references/electron-ipc-test.md
  • Zustand Store Action testing: references/zustand-store-action-test.md
  • Agent Runtime E2E testing: references/agent-runtime-e2e.md
  • Desktop Controller testing: references/desktop-controller-test.md

Fixing Failing Tests — Optimize or Delete?

When tests fail due to implementation changes (not bugs), evaluate before blindly fixing:

Keep & Fix (update test data/assertions)

  • Behavior tests: Tests that verify what the code does (output, side effects, user-visible behavior). Just update mock data formats or expected values.
    • Example: Tool data structure changed from { name } to { function: { name } } → update mock data
    • Example: Output format changed from Current date: YYYY-MM-DD to Current date: YYYY-MM-DD (TZ) → update expected string

Delete (over-specified, low value)

  • Param-forwarding tests: Tests that assert exact internal function call arguments (e.g., expect(internalFn).toHaveBeenCalledWith(expect.objectContaining({ exact params }))) — these break on every refactor and duplicate what behavior tests already cover.
  • Implementation-coupled tests: Tests that verify how the code works internally rather than what it produces. If a higher-level test already covers the same behavior, the low-level test adds maintenance cost without coverage gain.

Decision Checklist

  1. Does the test verify externally observable behavior (API response, DB write, rendered output)? → Keep
  2. Does the test only verify internal wiring (which function receives which params)? → Check if a behavior test already covers it. If yes → Delete
  3. Is the same behavior already tested at a higher integration level? → Delete the lower-level duplicate
  4. Would the test break again on the next routine refactor? → Consider raising to integration level or deleting

When Writing New Tests

  • Prefer integration-level assertions (verify final output) over white-box assertions (verify internal calls)
  • Use expect.objectContaining only for stable, public-facing contracts — not for internal param shapes that change with refactors
  • Mock at boundaries (DB, network, external services), not between internal modules

Common Issues

  1. Module pollution: Use vi.resetModules() when tests fail mysteriously
  2. Mock not working: Check setup position and use vi.clearAllMocks() in beforeEach
  3. Test data pollution: Clean database state in beforeEach/afterEach
  4. Async issues: Wrap state changes in act() for React hooks

Version History

  • a06b4e2 Current 2026-08-29 06:01
  • 29fe043 2026-08-20 18:34

Same Skill Collection

.agents/skills/add-provider-doc/SKILL.md
.agents/skills/add-setting-env/SKILL.md
.agents/skills/agent-runtime-hooks/SKILL.md
.agents/skills/agent-signal/SKILL.md
.agents/skills/agent-testing-bot/SKILL.md
.agents/skills/agent-tracing/SKILL.md
.agents/skills/agent-work/SKILL.md
.agents/skills/builtin-tool/SKILL.md
.agents/skills/chat-sdk/SKILL.md
.agents/skills/cleanup-git-worktrees/SKILL.md
.agents/skills/cli/SKILL.md
.agents/skills/data-fetching-architecture/SKILL.md
.agents/skills/db-migrations/SKILL.md
.agents/skills/debug-package/SKILL.md
.agents/skills/deep-review/SKILL.md
.agents/skills/design-prototype/SKILL.md
.agents/skills/desktop/SKILL.md
.agents/skills/docs-changelog/SKILL.md
.agents/skills/drizzle/SKILL.md
.agents/skills/heterogeneous-agent/SKILL.md
.agents/skills/hotkey/SKILL.md
.agents/skills/i18n/SKILL.md
.agents/skills/linear/SKILL.md
.agents/skills/llm-generation/SKILL.md
.agents/skills/modal/SKILL.md
.agents/skills/model-bank-metadata/SKILL.md
.agents/skills/product-design/SKILL.md
.agents/skills/project-overview/SKILL.md
.agents/skills/react/SKILL.md
.agents/skills/response-compliance/SKILL.md
.agents/skills/skills-audit/SKILL.md
.agents/skills/spa-routes/SKILL.md
.agents/skills/split-micro-app/SKILL.md
.agents/skills/store-data-structures/SKILL.md
.agents/skills/trpc-router/SKILL.md
.agents/skills/typescript/SKILL.md
.agents/skills/upstash-workflow/SKILL.md
.agents/skills/ux-audit/SKILL.md
.agents/skills/ux/SKILL.md
.agents/skills/version-release/SKILL.md
.agents/skills/zustand/SKILL.md
.agents/skills/agent-testing/SKILL.md
.agents/skills/compose-atoms/SKILL.md
.agents/skills/debug-frontend-with-browser/SKILL.md
.agents/skills/pr/SKILL.md
packages/builtin-skills/src/acceptance/SKILL.md

Metadata

Files
0
Version
a06b4e2
Hash
f3a94451
Indexed
2026-08-20 18:34

ホーム - Wiki
Copyright © 2011-2026 iteam. Current version is 2.155.2. UTC+08:00, 2026-08-30 02:16
浙ICP备14020137号-1 $お客様$