Strategic architecture, tactical design, and testable code principles (SOLID, Clean Architecture, Design Patterns, Testable Design)
97
97%
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Passed
No known issues
Each architectural layer should be testable independently. Domain tests need no infrastructure. Use case tests need no web framework. This enables fast, focused testing.
Incorrect (everything tested through API):
// All tests go through HTTP - slow, imprecise failures
describe('Order API', () => {
let app: Express
let db: Database
beforeEach(async () => {
db = await Database.connect()
await db.migrate()
await db.seed()
app = createApp(db)
})
afterEach(async () => {
await db.clean()
await db.close()
})
it('rejects order with insufficient inventory', async () => {
// 500ms+ per test
const response = await request(app)
.post('/orders')
.send({ items: [{ productId: 'p1', quantity: 1000 }] })
expect(response.status).toBe(400)
expect(response.body.error).toBe('Insufficient inventory')
})
// 50 more tests like this - test suite takes 5 minutes
// When one fails, unclear if it's domain, use case, or HTTP issue
})Correct (layered testing):
// Domain layer tests - instant, no dependencies
describe('Order', () => {
it('calculates total from items', () => {
const order = new Order()
order.addItem(new Product('p1', Money.dollars(10)), 2)
order.addItem(new Product('p2', Money.dollars(5)), 1)
expect(order.total).toEqual(Money.dollars(25))
})
it('prevents adding item with zero quantity', () => {
const order = new Order()
expect(() => order.addItem(product, 0)).toThrow(InvalidQuantityError)
})
})
// Use case tests - fast, test doubles for ports
describe('PlaceOrderUseCase', () => {
it('rejects order when inventory insufficient', () => {
const orders = new InMemoryOrderRepository()
const inventory = new FakeInventory({ 'p1': 5 }) // Only 5 in stock
const useCase = new PlaceOrderUseCase(orders, inventory)
const result = useCase.execute({
items: [{ productId: 'p1', quantity: 10 }] // Want 10
})
expect(result.isFailure).toBe(true)
expect(result.error).toBe('INSUFFICIENT_INVENTORY')
})
})
// Infrastructure tests - verify adapters work correctly
describe('PostgresOrderRepository', () => {
it('persists and retrieves order', async () => {
const repo = new PostgresOrderRepository(testDb)
const order = createTestOrder()
await repo.save(order)
const retrieved = await repo.findById(order.id)
expect(retrieved).toEqual(order)
})
})
// API tests - few, verify wiring only
describe('POST /orders', () => {
it('returns 201 when order placed successfully', async () => {
// Most logic tested above; this verifies HTTP wiring
const response = await request(app)
.post('/orders')
.send(validOrderPayload)
expect(response.status).toBe(201)
expect(response.body).toHaveProperty('orderId')
})
})Test pyramid:
/\
/ \ E2E: ~5 tests (slow, expensive)
/----\
/ \ Integration: ~20 tests (medium)
/--------\
/ \ Unit: ~200 tests (fast, cheap)
/____________\Reference: The Test Pyramid
clean-architecture
evals
references
design-patterns
solid-principles
testable-design