スキル一覧に戻る
bradhannah

testing

by bradhannah

1🍴 0📅 2026年1月25日
GitHubで見るManusで実行

SKILL.md


name: testing description: Comprehensive guide to running tests, coverage, and writing tests for backend, frontend, E2E, and Tauri license: MIT compatibility: opencode metadata: audience: developers workflow: testing

Testing Guide

Use this skill when running tests, checking coverage, writing new tests, or debugging test failures.

Architecture Overview

LayerRunnerLocationCoverage
BackendBun testapi/src/**/*.test.tsBun native
FrontendVitestsrc/**/*.test.tsV8 (Node.js required)
E2EPlaywrighttests/e2e/**/*.spec.tsN/A
Rustcargo testsrc-tauri/src/Not yet implemented

Quick Commands

# Run all tests
make test

# Individual test suites
make test-backend      # Backend only (Bun)
make test-frontend     # Frontend only (Vitest)
make test-e2e          # E2E only (Playwright)

# With coverage
make test-backend-coverage   # Bun native coverage
make test-frontend-coverage  # Requires Node.js
make test-coverage           # Both (skips frontend if no Node.js)

# Quality checks
make lint              # ESLint + Clippy
make format-check      # Prettier + rustfmt

Coverage Goals

MetricGoalCurrent
Backend line coverage>=80%~94%
Frontend line coverage>=80%Measured in CI
Total test count>600681

Node.js Exception for Frontend Coverage

This is the ONLY exception to the "no Node.js" rule in this project.

Why Required

Vitest's coverage provider (@vitest/coverage-v8) depends on node:inspector, which Bun hasn't implemented yet.

Setup (macOS)

  1. Install NVM:

    curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.1/install.sh | bash
    source ~/.zshrc
    
  2. Install and use Node.js 22:

    nvm install 22
    nvm use 22
    
  3. Run coverage:

    make test-frontend-coverage
    # or: npx vitest run --coverage
    

The project has a .nvmrc file configured for Node.js 22.


Backend Testing (Bun)

Configuration

  • Runner: Bun's native test runner
  • Files: api/src/**/*.test.ts (co-located with source)
  • Command: cd api && bun test

Test Structure

api/src/
├── services/
│   ├── bills-service.ts
│   ├── bills-service.test.ts    # Tests next to source
│   ├── storage.ts
│   └── storage.test.ts
└── utils/
    ├── validators.ts
    └── validators.test.ts

Writing Backend Tests

import { describe, it, expect, beforeEach, mock } from 'bun:test';
import { BillsService } from './bills-service';

describe('BillsService', () => {
  let service: BillsService;

  beforeEach(() => {
    service = new BillsService();
  });

  it('should create a bill', async () => {
    const bill = await service.create({ name: 'Test', amount: 100 });
    expect(bill.id).toBeDefined();
    expect(bill.name).toBe('Test');
  });

  it('should validate required fields', () => {
    expect(() => service.validate({})).toThrow('Name is required');
  });
});

Mocking in Bun

import { mock } from 'bun:test';

// Mock a module
mock.module('./storage', () => ({
  read: mock(() => Promise.resolve([])),
  write: mock(() => Promise.resolve()),
}));

Frontend Testing (Vitest)

Configuration

  • Config file: vitest.config.ts
  • Environment: jsdom
  • Files: src/**/*.{test,spec}.ts
  • Setup file: vitest-setup.ts

Key Config Options

// vitest.config.ts
export default defineConfig({
  plugins: [sveltekit(), svelteTesting()],
  test: {
    environment: 'jsdom',
    include: ['src/**/*.{test,spec}.{js,ts}'],
    globals: true,
    coverage: {
      provider: 'v8',
      include: ['src/**/*.{ts,svelte}'],
    },
  },
});

Writing Frontend Tests

import { describe, it, expect, vi, beforeEach } from 'vitest';
import { get } from 'svelte/store';
import { billsStore } from './bills';

describe('billsStore', () => {
  beforeEach(() => {
    vi.resetAllMocks();
  });

  it('should start with empty bills', () => {
    const bills = get(billsStore);
    expect(bills).toEqual([]);
  });

  it('should add a bill', async () => {
    await billsStore.add({ name: 'Test', amount: 50 });
    const bills = get(billsStore);
    expect(bills).toHaveLength(1);
  });
});

Testing Svelte Components

import { render, screen } from '@testing-library/svelte';
import Toast from './Toast.svelte';

describe('Toast', () => {
  it('renders message', () => {
    render(Toast, { props: { message: 'Hello' } });
    expect(screen.getByText('Hello')).toBeInTheDocument();
  });
});

E2E Testing (Playwright)

Configuration

  • Config file: playwright.config.ts
  • Test directory: tests/e2e/
  • Base URL: http://localhost:1420
  • Web server: make dev-browser (auto-started)

Running E2E Tests

# Run all E2E tests
make test-e2e

# Run with UI (interactive)
npx playwright test --ui

# Run specific test file
npx playwright test tests/e2e/smoke.spec.ts

# Debug mode
npx playwright test --debug

Writing E2E Tests

import { test, expect } from '@playwright/test';

test.describe('Dashboard', () => {
  test('should load the main page', async ({ page }) => {
    await page.goto('/');
    await expect(page.locator('h1')).toContainText('Budget');
  });

  test('should navigate to settings', async ({ page }) => {
    await page.goto('/');
    await page.click('text=Settings');
    await expect(page).toHaveURL('/settings');
  });
});

Playwright Tips

  • Screenshots on failure: automatically saved
  • Traces: enabled on first retry (trace: 'on-first-retry')
  • Reports: HTML report at playwright-report/

Rust Testing (Tauri)

Currently no Rust tests exist in src-tauri/. To add them:

Adding Rust Unit Tests

// src-tauri/src/lib.rs

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_port_parsing() {
        let line = "Listening on http://localhost:3456";
        let port = extract_port(line);
        assert_eq!(port, Some(3456));
    }
}

Running Rust Tests

cd src-tauri && cargo test

Adding to Makefile (future)

test-rust: ## Run Rust tests
	@echo "Running Rust tests..."
	@cd src-tauri && cargo test

CI Integration

GitHub Actions runs tests automatically on PRs:

  1. Backend tests: bun test with coverage
  2. Frontend tests: npx vitest run --coverage (uses Node.js)
  3. E2E tests: Playwright on headless Chromium
  4. Linting: ESLint + Clippy

Coverage reports are uploaded as artifacts on each PR.


Test File Inventory

Backend Tests (29 files)

api/src/services/*.test.ts   # Service tests
api/src/utils/*.test.ts      # Utility tests

Frontend Tests (14 files)

src/stores/*.test.ts         # Store tests
src/lib/*.test.ts            # Library tests
src/components/**/*.test.ts  # Component tests

E2E Tests (1 file)

tests/e2e/smoke.spec.ts      # Smoke tests

Troubleshooting

"Cannot find module" in tests

# Reinstall dependencies
bun install
cd api && bun install

Frontend coverage not working

# Ensure Node.js is installed
node --version  # Should be 22.x

# If using nvm
nvm use 22
make test-frontend-coverage

E2E tests timing out

# Kill stray processes
make kill-dev

# Increase timeout in playwright.config.ts if needed

Vitest hanging

# Clear Vite cache
rm -rf node_modules/.vite

# Run with verbose output
bunx vitest run --reporter=verbose

スコア

総合スコア

50/100

リポジトリの品質指標に基づく評価

SKILL.md

SKILL.mdファイルが含まれている

+20
LICENSE

ライセンスが設定されている

0/10
説明文

100文字以上の説明がある

0/10
人気

GitHub Stars 100以上

0/15
最近の活動

3ヶ月以内に更新がある

0/10
フォーク

10回以上フォークされている

0/5
Issue管理

オープンIssueが50未満

+5
言語

プログラミング言語が設定されている

+5
タグ

1つ以上のタグが設定されている

0/5

レビュー

💬

レビュー機能は近日公開予定です