# Implementation Tasks: add-pytest-tests ## 1. Test Infrastructure Setup - [x] Create `tests/` directory structure - [x] `tests/unit/` for pure logic tests - [x] `tests/integration/` for database and resolver tests - [x] `tests/e2e/` for full API tests - [x] `tests/mcp/` for MCP server tests - [x] Create `tests/conftest.py` with shared fixtures - [x] Database fixture (in-memory SQLite) - [x] Async session fixture - [x] Test client fixture for FastAPI/GraphQL - [x] Create `tests/__init__.py` ## 2. Unit Tests - [x] `tests/unit/test_validation.py` - [x] Test `validate_first_name()` with valid input - [x] Test `validate_first_name()` with empty string - [x] Test `validate_first_name()` with whitespace only - [x] Test `validate_email()` with valid emails - [x] Test `validate_email()` with invalid emails - [x] Test `validate_email()` with None (should pass) - [x] Test `validate_email()` with empty string (should pass) - [x] Test `validate_phone()` with valid E.164 numbers - [x] Test `validate_phone()` with invalid numbers - [x] Test `validate_phone()` with None (should pass) - [x] Test `validate_phone()` with empty string (should pass) ## 3. Integration Tests - Database - [x] `tests/integration/test_member_model.py` - [x] Test creating member with minimal data (firstName only) - [x] Test creating member with complete data - [x] Test member timestamps (created_at, updated_at) - [x] Test member __repr__ ## 4. Integration Tests - GraphQL Resolvers - [x] `tests/integration/test_member_queries.py` - [x] Test `member(id)` query with existing member - [x] Test `member(id)` query with non-existent ID (returns None) - [x] Test `members` query with multiple members - [x] Test `members` query returns empty array when no members - [x] Test `members` sorting (last name nulls last, then first name) - [x] `tests/integration/test_member_mutations.py` - [x] Test `createMember` with minimal data (firstName only) - [x] Test `createMember` with complete data - [x] Test `createMember` with invalid email (validation error) - [x] Test `createMember` with invalid phone (validation error) - [x] Test `createMember` with empty firstName (validation error) - [x] Test `updateMember` successfully updates fields - [x] Test `updateMember` with non-existent ID (MemberNotFoundError) - [x] Test `updateMember` with partial data (only updates provided fields) - [x] Test `updateMember` with invalid email (validation error) - [x] Test `deleteMember` successfully deletes member - [x] Test `deleteMember` with non-existent ID (MemberNotFoundError) ## 5. E2E Tests - GraphQL API - [x] `tests/e2e/test_graphql_api.py` - [x] Test complete query flow (list members via HTTP) - [x] Test complete mutation flow (create member via HTTP) - [x] Test GraphQL introspection query (__schema) - [x] Test GraphQL type introspection (__type) - [x] Test error responses (400 for validation errors) ## 6. MCP Server Tests - [x] `tests/mcp/test_mcp_server.py` - [x] Test MCP server initialization - [x] Test `list_tools()` returns 6 tools - [x] Test `list_members` tool execution - [x] Test `get_member` tool execution - [x] Test `get_member` with non-existent ID - [x] Test `create_member` tool execution - [x] Test `update_member` tool execution - [x] Test `get_graphql_schema` tool execution - [x] Test `execute_graphql_query` tool with simple query - [x] Test `execute_graphql_query` tool with variables - [x] Test error handling when API is unavailable ## 7. Documentation - [x] Update README.md - [x] Add "Running Tests" section - [x] Add test command examples - [x] Add "Test Organization" section - [x] Document test coverage goals ## 8. Validation - [x] Run `uv run pytest` and verify all tests pass - [x] Run `uv run pytest --verbose` for detailed output - [x] Run `uv run pytest tests/unit` to test unit tests - [x] Run `uv run pytest tests/integration` to test integration tests - [x] Run `uv run pytest tests/e2e` to test e2e tests - [x] Run `uv run pytest tests/mcp` to test MCP tests - [x] Verify no changes to production code (except bug fixes if found) - [x] Run `openspec validate add-pytest-tests --strict`