Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 34 additions & 1 deletion .github/copilot-instructions.md
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ class PlayerModel(BaseModel):
## Common Issues

1. **SQLAlchemy errors** → Always catch + rollback in services
2. **Test file** → `test_main.py` excluded from Black (preserves long names)
2. **Test file** → `test_main.py` excluded from Black
3. **Database location** → Local: `./storage/`, Docker: `/storage/` (volume)
4. **Pydantic validation** → Returns 422 (not 400)
5. **Import order** → stdlib → third-party → local
Expand All @@ -155,6 +155,39 @@ curl http://localhost:9000/players # 200 OK
- Line length: 88
- Complexity: ≤10

## Test Naming Convention

Integration tests follow an action-oriented pattern:

**Pattern:**
```
test_request_{method}_{resource}_{param_or_context}_response_{outcome}
```
Comment thread
coderabbitai[bot] marked this conversation as resolved.
Outdated

**Components:**
- `method` - HTTP verb: `get`, `post`, `put`, `delete`
- `resource` - `players` (collection) or `player` (single resource)
- `param_or_context` - Request details: `id_existing`, `squadnumber_nonexistent`, `body_empty`
- `response` - Literal separator
- `outcome` - What's asserted: `status_ok`, `status_not_found`, `body_players`, `header_cache_miss`

**Examples:**
```python
def test_request_get_players_response_status_ok(client):
"""GET /players/ returns 200 OK"""

def test_request_get_player_id_existing_response_body_player_match(client):
"""GET /players/{player_id} with existing ID returns matching player"""

def test_request_post_player_body_empty_response_status_unprocessable(client):
"""POST /players/ with empty body returns 422 Unprocessable Entity"""
```

**Docstrings:**
- Single-line, concise descriptions
- Complements test name (doesn't repeat)
- No "Expected:" prefix (redundant)
Comment thread
coderabbitai[bot] marked this conversation as resolved.

## Commit Messages

Follow Conventional Commits format (enforced by commitlint in CI):
Expand Down
5 changes: 5 additions & 0 deletions .github/workflows/python-cd.yml
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,11 @@ jobs:
else
echo "📝 Generating changelog from $PREVIOUS_TAG to ${{ steps.version.outputs.tag_name }}"
CHANGELOG=$(git log --pretty=format:"- %s (%h)" ${PREVIOUS_TAG}..${{ steps.version.outputs.tag_name }})

# Guard against empty changelog (e.g., re-tagging same commit)
if [ -z "$CHANGELOG" ]; then
CHANGELOG="No new changes since $PREVIOUS_TAG"
fi
fi

# Write changelog to file
Expand Down
17 changes: 15 additions & 2 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,8 @@ async def get_stats(
1. Tests (`tests/test_main.py`):

```python
async def test_given_get_when_player_stats_then_returns_200():
def test_request_get_player_id_existing_stats_response_status_ok(client):
"""GET /players/{player_id}/stats with existing ID returns 200 OK"""
...
```

Expand Down Expand Up @@ -110,10 +111,22 @@ No Alembic migrations:

## Testing Strategy

**Naming Pattern:**

```text
test_request_{method}_{resource}_{param_or_context}_response_{outcome}
```

- `players` (collection) vs `player` (single resource)
- Examples: `test_request_get_players_response_status_ok`, `test_request_post_player_body_empty_response_status_unprocessable`

**Guidelines:**

- Use `tests/player_stub.py` for data
- Test real DB (fixtures handle setup)
- Cover: happy paths + errors + edges
- Cache tests: verify `X-Cache` header
- Docstrings: Single-line, concise, no "Expected:" prefix

## Planning Tips

Expand All @@ -130,7 +143,7 @@ No Alembic migrations:
- `test_main.py`: Excluded from Black
- SQLAlchemy errors: Catch + rollback in services
- Validation errors: 422 (not 400)
- Test file naming: `test_given_when_then` pattern
- Test naming: `test_request_{method}_{resource}_{context}_response_{outcome}` pattern

## Cross-Tool Notes

Expand Down
Binary file modified storage/players-sqlite3.db
Binary file not shown.
20 changes: 10 additions & 10 deletions tests/player_stub.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,16 +54,16 @@ def nonexistent_player():
Creates a test stub for a nonexistent (new) Player.
"""
return Player(
id=12,
first_name="Leandro",
middle_name="Daniel",
last_name="Paredes",
date_of_birth="1994-06-29T00:00:00.000Z",
squad_number=5,
position="Defensive Midfield",
abbr_position="DM",
team="AS Roma",
league="Serie A",
id=24,
first_name="Thiago",
middle_name="Ezequiel",
last_name="Almada",
date_of_birth="2001-04-26T00:00:00.000Z",
squad_number=16,
position="Attacking Midfield",
abbr_position="AM",
team="Atlanta United FC",
league="Major League Soccer",
starting11=0,
)

Expand Down
Loading