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