Advanced pgTAP Testing
While basic pgTAP provides excellent testing capabilities, you can enhance the testing workflow using database development tools and helper packages. This guide covers advanced testing techniques using database.dev and community-maintained test helpers.
Using database.dev
Database.dev is a package manager for Postgres that allows installation and use of community-maintained packages, including testing utilities.
Setting up dbdev
To use database development tools and packages, install some prerequisites:
Installing test helpers
The Test Helpers package provides utilities that simplify testing Supabase-specific features:
Test helper benefits
The test helpers package provides several advantages over writing raw pgTAP tests:
-
Simplified User Management
- Create test users with
tests.create_supabase_user()
- Switch contexts with
tests.authenticate_as()
- Retrieve user IDs using
tests.get_supabase_uid()
- Create test users with
-
Row Level Security (RLS) Testing Utilities
- Verify RLS status with
tests.rls_enabled()
- Test policy enforcement
- Simulate different user contexts
- Verify RLS status with
-
Reduced Boilerplate
- No need to manually insert auth.users
- Simplified JWT claim management
- Clean test setup and cleanup
Schema-wide Row Level Security testing
When working with Row Level Security, it's crucial to ensure that RLS is enabled on all tables that need it. Create a simple test to verify RLS is enabled across an entire schema:
Test file organization
When working with multiple test files that share common setup requirements, it's beneficial to create a single "pre-test" file that handles the global environment setup. This approach reduces duplication and ensures consistent test environments.
Creating a pre-test hook
Since pgTAP test files are executed in alphabetical order, create a setup file that runs first by using a naming convention like 000-setup-tests-hooks.sql
:
This setup file should contain:
- All shared extensions and dependencies
- Common test utilities
- A simple always green test to verify the setup
Here's an example setup file:
Benefits
This approach provides several advantages:
- Reduces code duplication across test files
- Ensures consistent test environment setup
- Makes it easier to maintain and update shared dependencies
- Provides immediate feedback if the setup process fails
Your subsequent test files (001-auth-tests.sql
, 002-rls-tests.sql
) can focus solely on their specific test cases, knowing that the environment is properly configured.
Example: Advanced RLS testing
Here's a complete example using test helpers to verify RLS policies putting it all together:
Not another todo app: Testing complex organizations
Todo apps are great for learning, but this section explores testing a more realistic scenario: a multi-tenant content publishing platform. This example demonstrates testing complex permissions, plan restrictions, and content management.
System overview
This demo app implements:
- Organizations with tiered plans (free/pro/enterprise)
- Role-based access (owner/admin/editor/viewer)
- Content management (posts/comments)
- Premium content restrictions
- Plan-based limitations
What makes this complex?
-
Layered Permissions
- Role hierarchies affect access rights
- Plan types influence user capabilities
- Content state (draft/published) affects permissions
-
Business Rules
- Free plan post limits
- Premium content visibility
- Cross-organization security
Testing focus areas
When writing tests, verify:
- Organization member access control
- Content visibility across roles
- Plan limitation enforcement
- Cross-organization data isolation
1. App schema definitions
The app schema tables are defined like this:
2. RLS policies declaration
Now to setup the RLS policies for each tables:
3. Test cases:
Now everything is setup, let's write RLS test cases, note that each section could be in its own test: