Testing Strategies Unit Integration E2E Testing
Chiến lược testing toàn diện cho ứng dụng JavaScript với Jest React Testing Library và Cypress
Testing Strategies: Unit, Integration và E2E Testing
Một testing strategy hiệu quả là essential cho bất kỳ application nào. Bài viết này sẽ cover unit tests, integration tests, và E2E tests với practical examples.
Testing Pyramid
/\
/ \ E2E Tests (Few)
/____\
/ \
/________\ Integration Tests (Some)
|________| Unit Tests (Many)
Test Distribution Strategy
Unit Tests: 70% - Fast, Isolated, Cheap
Integration Tests: 20% - Medium speed, Component interaction
E2E Tests: 10% - Slow, Real user scenarios, Expensive
Unit Testing với Jest
Setup và Configuration
// jest.config.js
module.exports = {
testEnvironment: 'jsdom',
setupFilesAfterEnv: ['<rootDir>/src/setupTests.js'],
moduleNameMapping: {
'\\.(css|less|scss|sass)$': 'identity-obj-proxy',
'\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$':
'<rootDir>/__mocks__/fileMock.js',
},
collectCoverageFrom: [
'src/**/*.{js,jsx,ts,tsx}',
'!src/**/*.d.ts',
'!src/index.js',
'!src/serviceWorker.js',
],
coverageThreshold: {
global: {
branches: 80,
functions: 80,
lines: 80,
statements: 80,
},
},
};
// src/setupTests.js
import '@testing-library/jest-dom';
import 'jest-canvas-mock';
// Mock localStorage
const localStorageMock = {
getItem: jest.fn(),
setItem: jest.fn(),
removeItem: jest.fn(),
clear: jest.fn(),
};
global.localStorage = localStorageMock;
// Mock window.matchMedia
Object.defineProperty(window, 'matchMedia', {
writable: true,
value: jest.fn().mockImplementation(query => ({
matches: false,
media: query,
onchange: null,
addListener: jest.fn(),
removeListener: jest.fn(),
addEventListener: jest.fn(),
removeEventListener: jest.fn(),
dispatchEvent: jest.fn(),
})),
});
Integration Testing
Testing Component Integration
// src/components/__tests__/UserProfile.integration.test.jsx
import { render, screen, waitFor, fireEvent } from '@/@/utils/test-utils';
import UserProfile from '@/UserProfile';
import { rest } from 'msw';
import { setupServer } from 'msw/node';
const server = setupServer(
rest.get('/api/users/:id', (req, res, ctx) => {
return res(
ctx.json({
id: req.params.id,
name: 'John Doe',
email: 'john@example.com',
avatar: 'https://example.com/avatar.jpg',
bio: 'Software developer',
})
);
})
);
beforeAll(() => server.listen());
afterEach(() => server.resetHandlers());
afterAll(() => server.close());
describe('UserProfile Integration', () => {
it('loads and displays user data', async () => {
render(<UserProfile userId="123" />);
expect(screen.getByText('Loading...')).toBeInTheDocument();
await waitFor(() => {
expect(screen.getByText('John Doe')).toBeInTheDocument();
expect(screen.getByText('john@example.com')).toBeInTheDocument();
});
});
});
End-to-End Testing với Cypress
Setup và Configuration
// cypress.config.js
const { defineConfig } = require('cypress');
module.exports = defineConfig({
e2e: {
baseUrl: 'http://localhost:3000',
viewportWidth: 1280,
viewportHeight: 720,
video: false,
screenshotOnRunFailure: true,
defaultCommandTimeout: 10000,
requestTimeout: 10000,
responseTimeout: 10000,
},
});
E2E Test Examples
// cypress/e2e/auth.cy.js
describe('Authentication', () => {
beforeEach(() => {
cy.visit('/');
});
it('allows user to log in', () => {
cy.get('[data-testid="login-link"]').click();
cy.url().should('include', '/login');
cy.get('[data-testid="email-input"]').type('user@example.com');
cy.get('[data-testid="password-input"]').type('password123');
cy.get('[data-testid="login-button"]').click();
cy.url().should('eq', Cypress.config().baseUrl + '/');
cy.get('[data-testid="user-menu"]').should('contain', 'user@example.com');
});
});
Testing Best Practices
Test Organization
// src/utils/__tests__/validation.test.js
describe('Validation Utils', () => {
describe('email validation', () => {
it('validates correct email format', () => {
expect(isValidEmail('user@example.com')).toBe(true);
});
it('rejects invalid email format', () => {
expect(isValidEmail('invalid-email')).toBe(false);
});
});
});
Kết luận
Một testing strategy hiệu quả cần:
- Unit Tests: Cover individual functions và components
- Integration Tests: Test component interactions và API calls
- E2E Tests: Verify complete user workflows
- Continuous Integration: Automated testing on every commit
- Performance Monitoring: Track test execution time và coverage
Bài viết này là phần đầu tiên trong series về Testing. Trong các bài tiếp theo, chúng ta sẽ explore Performance Testing và Security Testing.