test writer skill
Focuses on integration tests, but might be more reusable
This commit is contained in:
parent
c9901691e5
commit
2d94bbde62
148
.pi/skills/test-writer/SKILL.md
Normal file
148
.pi/skills/test-writer/SKILL.md
Normal file
@ -0,0 +1,148 @@
|
|||||||
|
---
|
||||||
|
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
|
||||||
|
```
|
||||||
Loading…
x
Reference in New Issue
Block a user