Skip to content

Commit ebfdee0

Browse files
committed
feat: add pgTAP testing skill for database test patterns (#298)
# Add pgTAP Testing Skill for Database Testing Added a new Claude skill for pgTAP testing that provides comprehensive guidance for writing database tests in pgflow. The skill includes: - Complete test structure patterns and examples - Common assertion techniques for database testing - Helper function documentation for test setup and verification - Realtime event testing patterns - Test organization and execution instructions This skill will help developers write effective database tests using the pgTAP framework, with specific focus on pgflow testing patterns. The skill includes a detailed reference of helper functions in a separate markdown file. Also updated the schema-dev skill to reference the new pgTAP testing skill for additional test patterns and helpers.
1 parent 8fe2e2d commit ebfdee0

File tree

4 files changed

+578
-2
lines changed

4 files changed

+578
-2
lines changed

.claude/settings.json

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,10 +46,13 @@
4646
"Read(./.notes/**)",
4747
"Write(./.notes/**)",
4848
"Edit(./.notes/**)",
49-
"Skill(scratch-capture)",
50-
"Skill(scratch-review)",
5149
"Skill(idea-refine)",
50+
"Skill(migration-management)",
5251
"Skill(notes-sync)",
52+
"Skill(pgtap-testing)",
53+
"Skill(schema-dev)",
54+
"Skill(scratch-capture)",
55+
"Skill(scratch-review)",
5356
"Skill(unblock)",
5457
"AskUserQuestion",
5558
"WebSearch",
Lines changed: 282 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,282 @@
1+
---
2+
name: pgtap-testing
3+
description: Guide pgTAP test writing in pgflow. Use when user asks to write pgTAP test, add test for feature, test SQL function, or asks how to test database scenarios. Provides test patterns and helper functions.
4+
---
5+
6+
# pgTAP Testing Guide
7+
8+
**CRITICAL**: Tests live in `pkgs/core/supabase/tests/`, helpers in `pkgs/core/supabase/seed.sql`
9+
10+
## Quick Reference
11+
12+
**Test Structure:**
13+
```sql
14+
begin;
15+
select plan(N); -- Declare number of tests
16+
select pgflow_tests.reset_db(); -- Clean state
17+
-- ... setup and assertions ...
18+
select finish();
19+
rollback;
20+
```
21+
22+
**Common Assertions:**
23+
- `is(actual, expected, description)` - Equality check
24+
- `results_eq(query1, query2, description)` - Compare query results
25+
- `ok(boolean, description)` - Boolean check
26+
- `throws_ok(query, description)` - Expect error
27+
28+
**Running Tests:**
29+
```bash
30+
# Single test
31+
./scripts/run-test-with-colors pkgs/core/supabase/tests/path/to/test.sql
32+
33+
# All tests
34+
pnpm nx test:pgtap core
35+
```
36+
37+
## Test Structure
38+
39+
All pgTAP tests follow this pattern:
40+
41+
```sql
42+
begin; -- Start transaction
43+
select plan(N); -- Declare number of tests
44+
45+
-- Setup phase
46+
select pgflow_tests.reset_db();
47+
select pgflow_tests.setup_flow('sequential');
48+
49+
-- Test assertions
50+
select is(
51+
(select count(*) from pgflow.runs),
52+
1::bigint,
53+
'Should create one run'
54+
);
55+
56+
select finish(); -- Complete tests
57+
rollback; -- Roll back transaction
58+
```
59+
60+
**Key points:**
61+
- Transaction ensures isolation (BEGIN...ROLLBACK)
62+
- `plan(N)` must match exact number of assertions
63+
- `reset_db()` cleans state between test runs
64+
- All changes are rolled back
65+
66+
## Common Patterns
67+
68+
### Testing Single Functions
69+
70+
Test a function's return value or side effects:
71+
72+
```sql
73+
begin;
74+
select plan(2);
75+
select pgflow_tests.reset_db();
76+
select pgflow_tests.setup_flow('sequential');
77+
78+
-- Execute function
79+
select pgflow.start_flow('sequential', '"hello"'::jsonb);
80+
81+
-- Test: Check created run
82+
select results_eq(
83+
$$ SELECT flow_slug, status from pgflow.runs $$,
84+
$$ VALUES ('sequential', 'started') $$,
85+
'Run should be created with correct status'
86+
);
87+
88+
select finish();
89+
rollback;
90+
```
91+
92+
### Testing Workflows (Setup → Execute → Assert)
93+
94+
Test complete workflows with multiple steps:
95+
96+
```sql
97+
begin;
98+
select plan(3);
99+
select pgflow_tests.reset_db();
100+
select pgflow_tests.setup_flow('sequential');
101+
102+
-- Start flow
103+
select pgflow.start_flow('sequential', '"hello"'::jsonb);
104+
105+
-- Poll and start task
106+
select pgflow_tests.read_and_start('sequential');
107+
108+
-- Complete task
109+
select pgflow.complete_task(
110+
(select run_id from pgflow.runs limit 1),
111+
'first',
112+
0,
113+
'{"result": "done"}'::jsonb
114+
);
115+
116+
-- Test: Task completed
117+
select is(
118+
(select status from pgflow.step_tasks
119+
where step_slug = 'first' limit 1),
120+
'completed',
121+
'Task should be completed'
122+
);
123+
124+
select finish();
125+
rollback;
126+
```
127+
128+
### Testing Error Conditions
129+
130+
Verify functions throw expected errors:
131+
132+
```sql
133+
begin;
134+
select plan(1);
135+
select pgflow_tests.reset_db();
136+
137+
-- Test: Invalid flow slug
138+
select throws_ok(
139+
$$ SELECT pgflow.start_flow('nonexistent', '{}') $$,
140+
'Flow not found: nonexistent'
141+
);
142+
143+
select finish();
144+
rollback;
145+
```
146+
147+
### Testing Realtime Events
148+
149+
Verify realtime notifications are sent:
150+
151+
```sql
152+
begin;
153+
select plan(3);
154+
155+
-- CRITICAL: Create partition before testing realtime
156+
select pgflow_tests.create_realtime_partition();
157+
158+
select pgflow_tests.reset_db();
159+
select pgflow.create_flow('sequential');
160+
select pgflow.add_step('sequential', 'first');
161+
162+
-- Capture run_id in temporary table
163+
with flow as (
164+
select * from pgflow.start_flow('sequential', '{}')
165+
)
166+
select run_id into temporary run_ids from flow;
167+
168+
-- Test: Event was sent
169+
select is(
170+
pgflow_tests.count_realtime_events(
171+
'run:started',
172+
(select run_id from run_ids)
173+
),
174+
1::int,
175+
'Should send run:started event'
176+
);
177+
178+
-- Test: Event payload is correct
179+
select is(
180+
(select payload->>'status'
181+
from pgflow_tests.get_realtime_message(
182+
'run:started',
183+
(select run_id from run_ids)
184+
)),
185+
'started',
186+
'Event should have correct status'
187+
);
188+
189+
-- Cleanup
190+
drop table if exists run_ids;
191+
192+
select finish();
193+
rollback;
194+
```
195+
196+
## Common Assertions
197+
198+
**Equality checks:**
199+
```sql
200+
select is(actual, expected, 'description');
201+
```
202+
203+
**Query result comparison:**
204+
```sql
205+
select results_eq(
206+
$$ SELECT col1, col2 FROM table1 $$,
207+
$$ VALUES ('val1', 'val2') $$,
208+
'description'
209+
);
210+
```
211+
212+
**Boolean checks:**
213+
```sql
214+
select ok(boolean_expression, 'description');
215+
```
216+
217+
**Error handling:**
218+
```sql
219+
select throws_ok($$ SELECT function_call() $$, 'error message');
220+
select lives_ok($$ SELECT function_call() $$, 'should not error');
221+
```
222+
223+
**Pattern matching:**
224+
```sql
225+
select alike(actual, 'pattern%', 'description');
226+
```
227+
228+
## Helper Functions
229+
230+
pgflow provides test helpers in `pgflow_tests` schema. See [helpers.md](helpers.md) for complete reference.
231+
232+
**Most commonly used:**
233+
- `reset_db()` - Clean all pgflow data and queues
234+
- `setup_flow(slug)` - Create predefined test flow
235+
- `read_and_start(flow_slug)` - Poll and start tasks
236+
- `poll_and_complete(flow_slug)` - Poll and complete task
237+
- `poll_and_fail(flow_slug)` - Poll and fail task
238+
- `create_realtime_partition()` - Required for realtime tests
239+
- `count_realtime_events(type, run_id)` - Count events sent
240+
- `get_realtime_message(type, run_id)` - Get full event message
241+
242+
## Test Organization
243+
244+
**Directory structure:**
245+
```
246+
pkgs/core/supabase/tests/
247+
├── start_flow/ # Tests for starting flows
248+
├── complete_task/ # Tests for task completion
249+
├── fail_task/ # Tests for task failures
250+
├── realtime/ # Tests for realtime events
251+
└── [feature]/ # Group related tests by feature
252+
```
253+
254+
**Naming convention:**
255+
- Test files: `descriptive_name.test.sql`
256+
- One test file per specific behavior
257+
- Group related tests in directories
258+
259+
## Running Tests
260+
261+
**Single test:**
262+
```bash
263+
./scripts/run-test-with-colors pkgs/core/supabase/tests/start_flow/creates_run.test.sql
264+
```
265+
266+
**All tests:**
267+
```bash
268+
pnpm nx test:pgtap core
269+
```
270+
271+
**Watch mode:**
272+
```bash
273+
pnpm nx test:pgtap:watch core
274+
```
275+
276+
## Example Test Files
277+
278+
See existing tests for patterns:
279+
- `tests/start_flow/creates_run.test.sql` - Basic workflow
280+
- `tests/complete_task/completes_task_and_updates_dependents.test.sql` - Complex workflow
281+
- `tests/realtime/start_flow_events.test.sql` - Realtime testing
282+
- `tests/type_violations/*.test.sql` - Error testing

0 commit comments

Comments
 (0)