Firehose Bot f05dd00c55 test writer skill
Focuses on integration tests, but might be more reusable
2026-03-18 20:02:20 +00:00

149 lines
3.1 KiB
Markdown

---
name: test-writer
description: Writes tests following Elixir/Phoenix best practices. Ensures DRY tests with proper helper functions, no duplicated setup code, and correct parameter defaults. Use when writing or modifying tests.
---
# Test Writer Skill
## Overview
This skill provides guidelines for writing clean, maintainable Elixir/Phoenix tests following best practices.
## Core Principles
### 1. DRY Tests
Avoid duplication by creating focused helper functions:
**Bad:**
```elixir
test "GET /users returns index", %{conn: conn} do
conn = get(conn, "/users")
body = html_response(conn, 200)
assert body =~ "Users"
end
test "GET /users/:id returns show", %{conn: conn} do
conn = get(conn, "/users/1")
body = html_response(conn, 200)
assert body =~ "User"
end
```
**Good:**
```elixir
defp goto_users_page(conn, suffix \\ ""), do: get(conn, "/users" <> suffix)
test "GET /users returns index", %{conn: conn} do
conn = goto_users_page(conn)
assert html_response(conn, 200) =~ "Users"
end
test "GET /users/:id returns show", %{conn: conn} do
conn = goto_users_page(conn, "/1")
assert html_response(conn, 200) =~ "User"
end
```
### 2. Separate Helpers for Different Assertion Patterns
Don't use conditionals in helpers to handle different cases:
**Bad:**
```elixir
defp goto_users_page(conn, suffix \\ "", check_title \\ true) do
path = "/users" <> suffix
conn = get(conn, path)
body = html_response(conn, 200)
if check_title, do: assert body =~ "Users"
assert body =~ "AppLayout"
body
end
```
**Good:**
```elixir
defp goto_users_page(conn, suffix \\ "") do
path = "/users" <> suffix
conn = get(conn, path)
body = html_response(conn, 200)
assert body =~ "Users"
assert body =~ "AppLayout"
body
end
defp goto_user_page(conn, suffix) do
path = "/users" <> suffix
conn = get(conn, path)
body = html_response(conn, 200)
assert body =~ "AppLayout"
body
end
```
## Test Structure
### Context Block
```elixir
describe "resource name" do
# Shared setup in context if needed
# test "scenario" do ...
end
```
### Value Aliasing
Never reuse value names. Elixir is immutable, but value aliasing is confusing. Use unique, meaningful names for the left hand side of assignments. Or use pipes `|>` to eliminate the need for naming.
```elixir
test "GET /users returns index", %{conn: conn} do
# don't reassign
response = get(conn, "/users")
# ...
end
```
## Common Patterns
### HTML Pages with Layout
```elixir
defp goto_resource_page(conn, suffix \\ ""), do: ...
# Asserts common layout elements and page-specific content
```
### API Endpoints
```elixir
test "GET /api/resource returns JSON", %{conn: conn} do
conn = conn |> put_req_header("accept", "application/json")
conn = get(conn, "/api/resource")
response = json_response(conn, 200)
# Assert structure
end
```
### Error Handling
```elixir
test "returns 404 for nonexistent", %{conn: conn} do
assert html_response(get(conn, "/nonexistent"), 404)
end
```
## Running Tests
### One focused test file
```bash
cd /path/to/app
mix test test/path/to_test.exs
```
### all tests
```bash
make test
```