Files
noteflow/.rag/14-testing.md

5.9 KiB

NoteFlow Testing Conventions

Location

  • Python: tests/ (pytest)
  • TypeScript: client/src/**/*.test.ts (Vitest)
  • Rust: client/src-tauri/src/**/*_tests.rs (cargo test)
  • E2E: client/e2e/ (Playwright)

Python Testing

Running Tests

pytest                           # Full suite
pytest -m "not integration"      # Skip external-service tests
pytest tests/domain/             # Run specific directory
pytest -k "test_segment"         # Run by pattern
pytest tests/quality/            # Quality gates

Markers

Marker Purpose
@pytest.mark.slow Model loading tests
@pytest.mark.integration External service tests
@pytest.mark.asyncio Async tests (auto-mode enabled)

Test Structure

  • Test files: test_*.py
  • Test functions: test_*
  • Fixtures in tests/conftest.py

Quality Gates (tests/quality/)

Run after any non-trivial changes:

pytest tests/quality/
Test File Enforces
test_test_smells.py No assertion roulette, no conditional logic, no loops in tests
test_magic_values.py No magic numbers in assignments
test_code_smells.py Code quality checks
test_duplicate_code.py No duplicate code patterns
test_stale_code.py No stale/dead code
test_decentralized_helpers.py Helpers consolidated properly
test_unnecessary_wrappers.py No unnecessary wrapper functions
test_baseline_self.py Baseline validation self-checks

Forbidden Patterns in Tests

  • Loops (for, while) — Use @pytest.mark.parametrize
  • Conditionals (if) — Use @pytest.mark.parametrize
  • Multiple assertions without messages — Add assertion messages
  • Empty catch blocks — All errors must be logged/handled

Global Fixtures (DO NOT REDEFINE)

Fixture Description
reset_context_vars Reset logging context variables
mock_uow Mock Unit of Work
crypto Crypto utilities
meetings_dir Temporary meetings directory
webhook_config Single-event webhook config
webhook_config_all_events All-events webhook config
sample_datetime Sample datetime
calendar_settings Calendar settings
meeting_id Sample meeting ID
sample_meeting Sample Meeting entity
recording_meeting Recording-state Meeting
sample_rate Audio sample rate
mock_grpc_context Mock gRPC context
mockasr_engine Mock ASR engine
mock_optional_extras Mock optional extras
mock_oauth_manager Mock OAuth manager
memory_servicer In-memory servicer
approx_float Approximate float comparison
approx_sequence Approximate sequence comparison

TypeScript Testing (Vitest)

Running Tests

cd client
npm run test              # Run all tests
npm run test:watch        # Watch mode
npm run test:coverage     # With coverage

Test Files

  • Unit tests: *.test.ts or *.test.tsx
  • Located next to source files

Patterns

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

describe('MyComponent', () => {
  it('should render correctly', () => {
    // Arrange
    const props = { title: 'Test' };
    
    // Act
    render(<MyComponent {...props} />);
    
    // Assert
    expect(screen.getByText('Test')).toBeInTheDocument();
  });
});

Rust Testing (cargo test)

Running Tests

cd client/src-tauri
cargo test                # All tests
cargo test -- --nocapture # With output

Test Files

  • Test modules: *_tests.rs
  • Unit tests: #[cfg(test)] modules in source files

Patterns

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

    #[test]
    fn test_audio_capture() {
        // Arrange
        let config = CaptureConfig::default();
        
        // Act
        let result = AudioCapture::new(config);
        
        // Assert
        assert!(result.is_ok());
    }
}

E2E Testing (Playwright)

Running Tests

cd client
npm run test:e2e          # Run all E2E tests
npm run test:e2e:ui       # With UI mode

Requirements

  • Frontend must be running on :5173
  • Backend server must be running

Test Files

  • Location: client/e2e/
  • Pattern: *.spec.ts

Makefile Quality Commands

make quality          # ALL quality checks (TS + Rust + Python)
make quality-py       # Python: lint + type-check + test-quality
make quality-ts       # TypeScript: type-check + lint + test-quality
make quality-rs       # Rust: clippy + lint

make e2e              # Playwright tests
make e2e-ui           # Playwright with UI
make e2e-grpc         # Rust gRPC integration tests

Test AAA Pattern

All tests should follow Arrange-Act-Assert:

def test_create_meeting():
    # Arrange
    service = MeetingService(mock_uow)
    params = MeetingCreateParams(title="Sprint Planning")
    
    # Act
    meeting = await service.create_meeting(params)
    
    # Assert
    assert meeting.title == "Sprint Planning"
    assert meeting.state == MeetingState.CREATED

Integration Tests

PostgreSQL (testcontainers)

@pytest.fixture
async def postgres_uow():
    async with PostgresContainer() as postgres:
        engine = create_async_engine(postgres.get_connection_url())
        yield SQLAlchemyUnitOfWork(engine)

gRPC Server

@pytest.fixture
async def grpc_server():
    server = await create_test_server()
    yield server
    await server.stop(grace=1.0)

Coverage Goals

Area Target
Critical business logic 100%
Domain entities 90%+
Application services 85%+
Infrastructure 70%+
gRPC mixins 80%+

Forbidden in Quality Tests

NEVER modify without explicit permission:

  • Adding entries to allowlists/baselines
  • Increasing thresholds
  • Adding exclusion patterns
  • Modifying filter functions

When quality tests fail:

  1. Fix the actual code (not the test)
  2. If false positive: improve detection logic
  3. NEVER add arbitrary values to allowlists