December 20, 2024 β’ 15 min read
Quality isn't just about writing testsβit's about building a culture and infrastructure that prevents bugs from reaching production. After implementing comprehensive quality engineering practices across multiple production systems, I've learned that the best testing strategies combine automated testing, static analysis, and continuous integration into a seamless development workflow.
The testing pyramid ensures maximum coverage with optimal execution speed and maintainability.
Effective unit tests should be fast, isolated, and provide clear feedback. Here's how we structure unit tests for complex business logic:
// PaymentProcessor.test.js - Comprehensive unit testing example
import PaymentProcessor from '../PaymentProcessor';
import { mockPaymentGateway, mockAuditLogger } from '../__mocks__';
describe('PaymentProcessor', () => {
let paymentProcessor;
let mockGateway;
let mockLogger;
beforeEach(() => {
mockGateway = mockPaymentGateway();
mockLogger = mockAuditLogger();
paymentProcessor = new PaymentProcessor(mockGateway, mockLogger);
});
describe('processPayment', () => {
it('should successfully process a valid payment', async () => {
// Arrange
const paymentRequest = {
amount: 99.99,
currency: 'AUD',
cardToken: 'tok_1234567890',
customerId: 'cus_test123'
};
mockGateway.charge.mockResolvedValue({
id: 'charge_test123',
status: 'succeeded',
amount: 9999
});
// Act
const result = await paymentProcessor.processPayment(paymentRequest);
// Assert
expect(result.success).toBe(true);
expect(result.chargeId).toBe('charge_test123');
expect(mockLogger.logPaymentSuccess).toHaveBeenCalled();
});
it('should handle payment failures gracefully', async () => {
mockGateway.charge.mockRejectedValue({
type: 'card_error',
code: 'card_declined'
});
const result = await paymentProcessor.processPayment({
amount: 50.00,
currency: 'AUD'
});
expect(result.success).toBe(false);
expect(result.error.type).toBe('card_error');
});
});
});End-to-end tests validate complete user journeys. Here's how we implement robust E2E testing:
// cypress/e2e/checkout-flow.cy.js
describe('E-commerce Checkout Flow', () => {
beforeEach(() => {
cy.task('db:seed');
cy.intercept('POST', '/api/payments/process', {
fixture: 'payment-success.json'
}).as('processPayment');
});
it('completes full purchase journey', () => {
cy.visit('/products/wireless-headphones');
cy.get('[data-testid="add-to-cart-btn"]').click();
cy.get('[data-testid="checkout-btn"]').click();
// Fill shipping information
cy.get('input[name="email"]').type('test@example.com');
cy.get('input[name="address"]').type('123 Test Street');
// Fill payment information
cy.get('input[name="cardNumber"]').type('4242424242424242');
cy.get('input[name="expiryDate"]').type('12/25');
cy.get('[data-testid="complete-purchase-btn"]').click();
cy.wait('@processPayment');
cy.url().should('include', '/order-confirmation');
cy.get('[data-testid="order-confirmation"]')
.should('contain', 'Order Confirmed');
});
});Automated quality checks prevent poor code from entering the repository:
# .husky/pre-commit
#!/usr/bin/env sh
echo "π Running pre-commit checks..."
# Lint staged files
npx lint-staged
# Type checking
npx tsc --noEmit
# Security audit
npm audit --audit-level moderate
echo "β
Pre-commit checks completed!"
# package.json scripts
{
"scripts": {
"test:unit": "jest --testPathPattern=__tests__/unit",
"test:integration": "jest --testPathPattern=__tests__/integration",
"test:e2e": "cypress run",
"lint": "eslint . --ext .js,.jsx,.ts,.tsx --fix",
"prepare": "husky install"
}
}
# lint-staged.config.js
module.exports = {
'*.{js,jsx,ts,tsx}': [
'eslint --fix',
'prettier --write',
'jest --findRelatedTests --passWithNoTests'
]
};# sonar-project.properties
sonar.projectKey=quality-engineering-example
sonar.organization=handy-hasan
sonar.sources=src
sonar.tests=src
sonar.test.inclusions=**/*.test.js,**/*.spec.js
sonar.javascript.lcov.reportPaths=coverage/lcov.info
# GitHub Actions Quality Pipeline
name: Quality Analysis
on: [push, pull_request]
jobs:
quality:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Setup Node.js
uses: actions/setup-node@v3
with:
node-version: '18'
- name: Install dependencies
run: npm ci
- name: Run tests with coverage
run: npm run test:coverage
- name: SonarCloud Scan
uses: SonarSource/sonarcloud-github-action@master
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}Quality engineering transformed how we ship software at The Good Guys. Our comprehensive testing strategy reduced production bugs by 85% and increased developer confidence. The upfront investment in quality infrastructure pays dividends in faster delivery and fewer production issues.