Initial commit: Telegram Management System
Some checks failed
Deploy / deploy (push) Has been cancelled
Some checks failed
Deploy / deploy (push) Has been cancelled
Full-stack web application for Telegram management - Frontend: Vue 3 + Vben Admin - Backend: NestJS - Features: User management, group broadcast, statistics 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
449
marketing-agent/docs/TESTING.md
Normal file
449
marketing-agent/docs/TESTING.md
Normal file
@@ -0,0 +1,449 @@
|
||||
# Testing Documentation
|
||||
|
||||
Comprehensive testing guide for the Telegram Marketing Agent System.
|
||||
|
||||
## Table of Contents
|
||||
|
||||
- [Testing Strategy](#testing-strategy)
|
||||
- [Test Types](#test-types)
|
||||
- [Running Tests](#running-tests)
|
||||
- [Writing Tests](#writing-tests)
|
||||
- [CI/CD Integration](#cicd-integration)
|
||||
- [Coverage Goals](#coverage-goals)
|
||||
- [Best Practices](#best-practices)
|
||||
|
||||
## Testing Strategy
|
||||
|
||||
Our testing strategy follows the Testing Pyramid approach:
|
||||
|
||||
```
|
||||
/\
|
||||
/E2E\ (5-10%)
|
||||
/------\
|
||||
/Integration\ (20-30%)
|
||||
/------------\
|
||||
/ Unit Tests \ (60-70%)
|
||||
/-----------------\
|
||||
```
|
||||
|
||||
### Test Categories
|
||||
|
||||
1. **Unit Tests**: Test individual functions, methods, and components in isolation
|
||||
2. **Integration Tests**: Test interactions between components and services
|
||||
3. **End-to-End Tests**: Test complete user workflows and scenarios
|
||||
|
||||
## Test Types
|
||||
|
||||
### Unit Tests
|
||||
|
||||
Located in `tests/unit/`, these tests cover:
|
||||
- Service methods
|
||||
- Utility functions
|
||||
- Middleware logic
|
||||
- Model validations
|
||||
- Helper functions
|
||||
|
||||
Example structure:
|
||||
```
|
||||
tests/unit/
|
||||
├── services/
|
||||
│ ├── api-gateway/
|
||||
│ │ ├── middleware/
|
||||
│ │ │ ├── auth.test.js
|
||||
│ │ │ └── rateLimiter.test.js
|
||||
│ │ └── utils/
|
||||
│ └── orchestrator/
|
||||
│ └── campaignService.test.js
|
||||
└── utils/
|
||||
```
|
||||
|
||||
### Integration Tests
|
||||
|
||||
Located in `tests/integration/`, these tests cover:
|
||||
- API endpoint functionality
|
||||
- Database operations
|
||||
- Service interactions
|
||||
- External API mocking
|
||||
|
||||
Example structure:
|
||||
```
|
||||
tests/integration/
|
||||
├── api/
|
||||
│ ├── auth.test.js
|
||||
│ ├── campaigns.test.js
|
||||
│ └── users.test.js
|
||||
└── services/
|
||||
```
|
||||
|
||||
### End-to-End Tests
|
||||
|
||||
Located in `tests/e2e/`, these tests cover:
|
||||
- Complete user workflows
|
||||
- Multi-service interactions
|
||||
- Real-world scenarios
|
||||
|
||||
Example structure:
|
||||
```
|
||||
tests/e2e/
|
||||
├── campaigns/
|
||||
│ └── campaignWorkflow.test.js
|
||||
└── users/
|
||||
└── userOnboarding.test.js
|
||||
```
|
||||
|
||||
## Running Tests
|
||||
|
||||
### Prerequisites
|
||||
|
||||
```bash
|
||||
# Install dependencies
|
||||
npm install
|
||||
|
||||
# For each service
|
||||
cd services/<service-name>
|
||||
npm install
|
||||
```
|
||||
|
||||
### All Tests
|
||||
```bash
|
||||
npm test
|
||||
```
|
||||
|
||||
### Unit Tests Only
|
||||
```bash
|
||||
npm run test:unit
|
||||
```
|
||||
|
||||
### Integration Tests Only
|
||||
```bash
|
||||
npm run test:integration
|
||||
```
|
||||
|
||||
### E2E Tests Only
|
||||
```bash
|
||||
npm run test:e2e
|
||||
```
|
||||
|
||||
### Watch Mode (for development)
|
||||
```bash
|
||||
npm run test:watch
|
||||
```
|
||||
|
||||
### Coverage Report
|
||||
```bash
|
||||
npm run test:coverage
|
||||
```
|
||||
|
||||
### Specific Test File
|
||||
```bash
|
||||
npx jest tests/unit/services/orchestrator/campaignService.test.js
|
||||
```
|
||||
|
||||
### Test Pattern
|
||||
```bash
|
||||
npx jest --testNamePattern="should create campaign"
|
||||
```
|
||||
|
||||
## Writing Tests
|
||||
|
||||
### Unit Test Example
|
||||
|
||||
```javascript
|
||||
import { jest } from '@jest/globals';
|
||||
import CampaignService from '../../../../services/orchestrator/src/services/campaignService.js';
|
||||
import { createCampaign } from '../../../helpers/factories.js';
|
||||
|
||||
describe('CampaignService', () => {
|
||||
let campaignService;
|
||||
let mockDependency;
|
||||
|
||||
beforeEach(() => {
|
||||
// Setup mocks
|
||||
mockDependency = {
|
||||
method: jest.fn()
|
||||
};
|
||||
|
||||
campaignService = new CampaignService(mockDependency);
|
||||
jest.clearAllMocks();
|
||||
});
|
||||
|
||||
describe('createCampaign', () => {
|
||||
it('should create a new campaign', async () => {
|
||||
// Arrange
|
||||
const campaignData = createCampaign();
|
||||
mockDependency.method.mockResolvedValue({ success: true });
|
||||
|
||||
// Act
|
||||
const result = await campaignService.createCampaign(campaignData);
|
||||
|
||||
// Assert
|
||||
expect(result).toHaveProperty('id');
|
||||
expect(mockDependency.method).toHaveBeenCalledWith(expect.any(Object));
|
||||
});
|
||||
|
||||
it('should handle errors gracefully', async () => {
|
||||
// Arrange
|
||||
mockDependency.method.mockRejectedValue(new Error('Database error'));
|
||||
|
||||
// Act & Assert
|
||||
await expect(campaignService.createCampaign({}))
|
||||
.rejects.toThrow('Database error');
|
||||
});
|
||||
});
|
||||
});
|
||||
```
|
||||
|
||||
### Integration Test Example
|
||||
|
||||
```javascript
|
||||
import request from 'supertest';
|
||||
import app from '../../../services/api-gateway/src/app.js';
|
||||
import { connectDatabase, closeDatabase, clearDatabase } from '../../helpers/database.js';
|
||||
|
||||
describe('Campaigns API', () => {
|
||||
let authToken;
|
||||
|
||||
beforeAll(async () => {
|
||||
await connectDatabase();
|
||||
authToken = await getAuthToken();
|
||||
});
|
||||
|
||||
afterEach(async () => {
|
||||
await clearDatabase();
|
||||
});
|
||||
|
||||
afterAll(async () => {
|
||||
await closeDatabase();
|
||||
});
|
||||
|
||||
describe('POST /api/v1/campaigns', () => {
|
||||
it('should create campaign', async () => {
|
||||
const response = await request(app)
|
||||
.post('/api/v1/campaigns')
|
||||
.set('Authorization', `Bearer ${authToken}`)
|
||||
.send({
|
||||
name: 'Test Campaign',
|
||||
type: 'message'
|
||||
});
|
||||
|
||||
expect(response.status).toBe(201);
|
||||
expect(response.body.success).toBe(true);
|
||||
expect(response.body.data.campaign).toHaveProperty('id');
|
||||
});
|
||||
});
|
||||
});
|
||||
```
|
||||
|
||||
### E2E Test Example
|
||||
|
||||
```javascript
|
||||
describe('Campaign Workflow', () => {
|
||||
it('should complete full campaign lifecycle', async () => {
|
||||
// 1. Create template
|
||||
const template = await createTemplate();
|
||||
|
||||
// 2. Import users
|
||||
const users = await importUsers();
|
||||
|
||||
// 3. Create segment
|
||||
const segment = await createSegment();
|
||||
|
||||
// 4. Create campaign
|
||||
const campaign = await createCampaign({
|
||||
templateId: template.id,
|
||||
segmentId: segment.id
|
||||
});
|
||||
|
||||
// 5. Execute campaign
|
||||
const execution = await executeCampaign(campaign.id);
|
||||
|
||||
// 6. Verify results
|
||||
expect(execution.status).toBe('completed');
|
||||
expect(execution.messagesSent).toBe(users.length);
|
||||
});
|
||||
});
|
||||
```
|
||||
|
||||
## Test Helpers and Utilities
|
||||
|
||||
### Database Helpers
|
||||
```javascript
|
||||
import { connectDatabase, closeDatabase, clearDatabase } from './helpers/database.js';
|
||||
```
|
||||
|
||||
### Factory Functions
|
||||
```javascript
|
||||
import {
|
||||
createUser,
|
||||
createCampaign,
|
||||
createTemplate
|
||||
} from './helpers/factories.js';
|
||||
```
|
||||
|
||||
### Authentication Helpers
|
||||
```javascript
|
||||
import { generateAuthToken, createAuthenticatedRequest } from './helpers/auth.js';
|
||||
```
|
||||
|
||||
## CI/CD Integration
|
||||
|
||||
Tests run automatically on:
|
||||
- Pull requests
|
||||
- Commits to main/develop branches
|
||||
- Before deployments
|
||||
|
||||
### GitHub Actions Workflow
|
||||
|
||||
See `.github/workflows/test.yml` for the complete CI configuration.
|
||||
|
||||
Key features:
|
||||
- Matrix testing (Node.js 18.x, 20.x)
|
||||
- Multiple database versions
|
||||
- Parallel test execution
|
||||
- Coverage reporting
|
||||
- Test result artifacts
|
||||
|
||||
### Pre-commit Hooks
|
||||
|
||||
```bash
|
||||
# Install husky
|
||||
npm prepare
|
||||
|
||||
# Pre-commit hook runs:
|
||||
- Linting
|
||||
- Unit tests for changed files
|
||||
- Commit message validation
|
||||
```
|
||||
|
||||
## Coverage Goals
|
||||
|
||||
### Overall Coverage Targets
|
||||
- **Statements**: 80%
|
||||
- **Branches**: 70%
|
||||
- **Functions**: 70%
|
||||
- **Lines**: 80%
|
||||
|
||||
### Service-Specific Targets
|
||||
- **API Gateway**: 85% (critical path)
|
||||
- **Orchestrator**: 80%
|
||||
- **Analytics**: 75%
|
||||
- **User Management**: 80%
|
||||
- **Scheduler**: 75%
|
||||
|
||||
### Viewing Coverage
|
||||
|
||||
```bash
|
||||
# Generate HTML coverage report
|
||||
npm run test:coverage
|
||||
|
||||
# Open in browser
|
||||
open coverage/lcov-report/index.html
|
||||
```
|
||||
|
||||
## Best Practices
|
||||
|
||||
### General Guidelines
|
||||
|
||||
1. **Test Naming**: Use descriptive test names that explain what is being tested
|
||||
```javascript
|
||||
// Good
|
||||
it('should return 404 when campaign does not exist')
|
||||
|
||||
// Bad
|
||||
it('test campaign')
|
||||
```
|
||||
|
||||
2. **Arrange-Act-Assert**: Structure tests clearly
|
||||
```javascript
|
||||
it('should calculate discount correctly', () => {
|
||||
// Arrange
|
||||
const price = 100;
|
||||
const discountRate = 0.2;
|
||||
|
||||
// Act
|
||||
const result = calculateDiscount(price, discountRate);
|
||||
|
||||
// Assert
|
||||
expect(result).toBe(80);
|
||||
});
|
||||
```
|
||||
|
||||
3. **Isolation**: Each test should be independent
|
||||
- Use `beforeEach` and `afterEach` for setup/cleanup
|
||||
- Don't rely on test execution order
|
||||
- Clear mocks between tests
|
||||
|
||||
4. **Mocking**: Mock external dependencies
|
||||
```javascript
|
||||
jest.mock('axios');
|
||||
axios.get.mockResolvedValue({ data: mockData });
|
||||
```
|
||||
|
||||
5. **Async Testing**: Handle promises properly
|
||||
```javascript
|
||||
// Good
|
||||
it('should handle async operation', async () => {
|
||||
await expect(asyncFunction()).resolves.toBe(expected);
|
||||
});
|
||||
|
||||
// Also good
|
||||
it('should handle async operation', () => {
|
||||
return expect(asyncFunction()).resolves.toBe(expected);
|
||||
});
|
||||
```
|
||||
|
||||
6. **Error Testing**: Test error cases thoroughly
|
||||
```javascript
|
||||
it('should throw error for invalid input', async () => {
|
||||
await expect(functionUnderTest(null))
|
||||
.rejects.toThrow('Input cannot be null');
|
||||
});
|
||||
```
|
||||
|
||||
### Performance Considerations
|
||||
|
||||
1. **Use Test Databases**: MongoDB Memory Server for unit tests
|
||||
2. **Parallel Execution**: Run independent tests in parallel
|
||||
3. **Selective Testing**: Use `--watch` mode during development
|
||||
4. **Mock Heavy Operations**: Mock file I/O, network calls
|
||||
|
||||
### Security Testing
|
||||
|
||||
1. **Authentication**: Test all auth scenarios
|
||||
2. **Authorization**: Verify role-based access
|
||||
3. **Input Validation**: Test with malicious inputs
|
||||
4. **Rate Limiting**: Verify limits are enforced
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Common Issues
|
||||
|
||||
1. **Timeout Errors**
|
||||
```javascript
|
||||
// Increase timeout for specific test
|
||||
it('should handle long operation', async () => {
|
||||
// test code
|
||||
}, 10000); // 10 second timeout
|
||||
```
|
||||
|
||||
2. **Database Connection Issues**
|
||||
- Ensure MongoDB/Redis are running
|
||||
- Check connection strings in test environment
|
||||
- Clear test database between runs
|
||||
|
||||
3. **Flaky Tests**
|
||||
- Add proper waits for async operations
|
||||
- Mock time-dependent functions
|
||||
- Use stable test data
|
||||
|
||||
4. **Memory Leaks**
|
||||
- Close all connections in `afterAll`
|
||||
- Clear large data structures
|
||||
- Use `--detectLeaks` flag
|
||||
|
||||
## Additional Resources
|
||||
|
||||
- [Jest Documentation](https://jestjs.io/docs/getting-started)
|
||||
- [Supertest Documentation](https://github.com/visionmedia/supertest)
|
||||
- [MongoDB Memory Server](https://github.com/nodkz/mongodb-memory-server)
|
||||
- [Testing Best Practices](https://github.com/goldbergyoni/javascript-testing-best-practices)
|
||||
Reference in New Issue
Block a user