Database testing with test data setup, transaction rollback, and schema...
Generates comprehensive database test suites with factories, transaction rollback, schema validation, and cleanup strategies.
/plugin marketplace add jeremylongshore/claude-code-plugins-plus/plugin install database-test-manager@claude-code-plugins-plusComprehensive database testing utilities including test data generation, transaction management, schema validation, migration testing, and database cleanup.
Test Data Management
Transaction Management
Schema Validation
Database Testing Patterns
When invoked, you should:
## Database Test Suite
### Database: [Type]
**ORM:** [Prisma / TypeORM / SQLAlchemy / ActiveRecord]
**Test Framework:** [Jest / Pytest / RSpec]
### Test Data Factories
\`\`\`javascript
// factories/userFactory.js
import { faker } from '@faker-js/faker';
export const userFactory = {
build: (overrides = {}) => ({
id: faker.string.uuid(),
email: faker.internet.email(),
name: faker.person.fullName(),
createdAt: new Date(),
...overrides
}),
create: async (overrides = {}) => {
const data = userFactory.build(overrides);
return await prisma.user.create({ data });
},
createMany: async (count, overrides = {}) => {
const users = Array.from({ length: count }, () =>
userFactory.build(overrides)
);
return await prisma.user.createMany({ data: users });
}
};
\`\`\`
### Transaction Wrapper
\`\`\`javascript
// testHelpers/dbHelper.js
export const withTransaction = (testFn) => {
return async () => {
return await prisma.$transaction(async (tx) => {
try {
await testFn(tx);
} finally {
// Transaction will rollback automatically
throw new Error('ROLLBACK');
}
}).catch(err => {
if (err.message !== 'ROLLBACK') throw err;
});
};
};
// Usage in tests
describe('User Service', () => {
it('should create user', withTransaction(async (tx) => {
const user = await userFactory.create();
expect(user.email).toBeDefined();
// Rolls back automatically after test
}));
});
\`\`\`
### Database Assertions
\`\`\`javascript
// Custom matchers
expect.extend({
async toExistInDatabase(tableName, conditions) {
const record = await prisma[tableName].findFirst({
where: conditions
});
return {
pass: record !== null,
message: () =>
`Expected ${tableName} with ${JSON.stringify(conditions)} ` +
`to ${record ? '' : 'not '}exist in database`
};
},
async toHaveCount(tableName, expectedCount) {
const count = await prisma[tableName].count();
return {
pass: count === expectedCount,
message: () =>
`Expected ${tableName} to have ${expectedCount} records, ` +
`but found ${count}`
};
}
});
// Usage
await expect('user').toExistInDatabase({ email: '[email protected]' });
await expect('user').toHaveCount(5);
\`\`\`
### Migration Testing
\`\`\`javascript
describe('Database Migrations', () => {
it('should run migrations up and down', async () => {
// Run all migrations
await runMigrations('up');
// Verify schema
const tables = await getTables();
expect(tables).toContain('users');
expect(tables).toContain('posts');
// Rollback migrations
await runMigrations('down');
// Verify tables removed
const tablesAfter = await getTables();
expect(tablesAfter).not.toContain('users');
});
it('should enforce constraints', async () => {
const user = await userFactory.create();
// Test foreign key constraint
await expect(
prisma.post.create({
data: {
title: 'Test',
userId: 'non-existent-id'
}
})
).rejects.toThrow('Foreign key constraint');
// Test unique constraint
await expect(
userFactory.create({ email: user.email })
).rejects.toThrow('Unique constraint');
});
});
\`\`\`
### Query Performance Testing
\`\`\`javascript
describe('Query Performance', () => {
beforeAll(async () => {
// Seed large dataset
await userFactory.createMany(10000);
});
it('should query efficiently with indexes', async () => {
const start = performance.now();
await prisma.user.findMany({
where: { email: { contains: '@example.com' } }
});
const duration = performance.now() - start;
expect(duration).toBeLessThan(100); // 100ms threshold
});
it('should use proper indexes', async () => {
const explain = await prisma.$queryRaw`
EXPLAIN ANALYZE
SELECT * FROM users WHERE email LIKE '%@example.com%'
`;
expect(explain).toContain('Index Scan');
expect(explain).not.toContain('Seq Scan'); // No full table scan
});
});
\`\`\`
### Database Cleanup
\`\`\`javascript
// testSetup.js
beforeEach(async () => {
// Clear all tables in reverse dependency order
await prisma.comment.deleteMany();
await prisma.post.deleteMany();
await prisma.user.deleteMany();
});
afterAll(async () => {
await prisma.$disconnect();
});
\`\`\`
### Test Configuration
\`\`\`javascript
// jest.config.js
module.exports = {
testEnvironment: 'node',
setupFilesAfterEnv: ['./tests/setup.js'],
globalSetup: './tests/globalSetup.js',
globalTeardown: './tests/globalTeardown.js'
};
// globalSetup.js
module.exports = async () => {
// Create test database
execSync('createdb myapp_test');
// Run migrations
process.env.DATABASE_URL = 'postgresql://localhost/myapp_test';
execSync('npx prisma migrate deploy');
};
\`\`\`
### Next Steps
- [ ] Implement test data factories
- [ ] Set up transaction rollback
- [ ] Add database assertions
- [ ] Test migrations
- [ ] Configure test database