Używamy cookies, żeby zwiększyć Twoje doświadczenia na stronie
CodeWorlds

PROJEKT: Kompleksowe testowanie systemu zarządzania legionami

Witaj, dowódco testowania! Konsul Caesar.js powierza Ci najpoważniejsze zadanie - stworzenie kompleksowego systemu testowania dla całej armii rzymskich legionów. To będzie Twój test mistrzowski, który pokaże, czy jesteś gotowy/a dowodzić własnymi oddziałami!

Specyfikacja Projektu Testowego

System do przetestowania: Legionary Legion Management

Twój system zarządzania legionami składa się z następujących komponentów:

  1. Legion Management - zarządzanie legionami i oddziałami
  2. Legion Assignment - przypisywanie legionistów do kohort
  3. Expedition Planning - planowanie wypraw
  4. Battle System - system bitew lądowych
  5. Tribute Tracking - śledzenie tributów
  6. Weather Integration - integracja z systemem pogodowym
  7. Real-time Communication - komunikacja w czasie rzeczywistym
  8. Analytics Dashboard - dashboard analityczny

Wymagania testowe

  • Unit Tests: 95% coverage dla logiki biznesowej
  • Integration Tests: Pełny flow każdego użycia
  • E2E Tests: Kluczowe scenariusze użytkownika
  • Performance Tests: Testy obciążeniowe i wydajności
  • Security Tests: Testy bezpieczeństwa
  • API Tests: Kompletne testowanie API
  • Database Tests: Testy spójności danych
  • Real-time Tests: Testy WebSocketów

Struktura Projektu Testowego

1legionariusze-legion-management/
2├── src/
3│ ├── legion/
4│ │ ├── legion.service.ts
5│ │ ├── legion.controller.ts
6│ │ ├── legion.module.ts
7│ │ └── entities/
8│ ├── legion/
9│ ├── expeditions/
10│ ├── battles/
11│ ├── tributes/
12│ ├── weather/
13│ ├── websockets/
14│ └── analytics/
15├── test/
16│ ├── unit/
17│ │ ├── legion/
18│ │ ├── legion/
19│ │ └──
20│ ├── integration/
21│ │ ├── legion-management.integration.spec.ts
22│ │ ├── expedition-flow.integration.spec.ts
23│ │ └──
24│ ├── e2e/
25│ │ ├── legion-operations.e2e.spec.ts
26│ │ ├── battle-scenarios.e2e.spec.ts
27│ │ └──
28│ ├── performance/
29│ │ ├── load-tests.spec.ts
30│ │ ├── stress-tests.spec.ts
31│ │ └──
32│ ├── security/
33│ │ ├── auth-tests.spec.ts
34│ │ ├── authorization-tests.spec.ts
35│ │ └──
36│ ├── helpers/
37│ │ ├── test-data-factory.ts
38│ │ ├── mock-factory.ts
39│ │ └── test-utils.ts
40│ └── fixtures/
41│ ├── legions.json
42│ ├── legions.json
43│ └── expeditions.json

Implementacja - Unit Tests

Legion Service Tests

1// test/unit/legion/legion.service.spec.ts
2import { Test, TestingModule } from '@nestjs/testing';
3import { LegionService } from '../../../src/legion/legion.service';
4import { getRepositoryToken } from '@nestjs/typeorm';
5import { Legion } from '../../../src/legion/entities/legion.entity';
6import { Cohort } from '../../../src/legion/entities/cohort.entity';
7import { WeatherService } from '../../../src/weather/weather.service';
8import { MockFactory } from '../../helpers/mock-factory';
9
10describe('LegionService', () => {
11 let service: LegionService;
12 let legionRepository: jest.Mocked<any>;
13 let cohortRepository: jest.Mocked<any>;
14 let legionService: jest.Mocked<LegionService>;
15 let weatherService: jest.Mocked<WeatherService>;
16
17 beforeEach(async () => {
18 const module: TestingModule = await Test.createTestingModule({
19 providers: [
20 LegionService,
21 {
22 provide: getRepositoryToken(Legion),
23 useValue: MockFactory.createMockRepository(),
24 },
25 {
26 provide: getRepositoryToken(Cohort),
27 useValue: MockFactory.createMockRepository(),
28 },
29 {
30 provide: LegionService,
31 useValue: MockFactory.createMockLegionService(),
32 },
33 {
34 provide: WeatherService,
35 useValue: MockFactory.createMockWeatherService(),
36 },
37 ],
38 }).compile();
39
40 service = module.get<LegionService>(LegionService);
41 legionRepository = module.get(getRepositoryToken(Legion));
42 cohortRepository = module.get(getRepositoryToken(Cohort));
43 legionService = module.get(LegionService);
44 weatherService = module.get(WeatherService);
45 });
46
47 describe('Legion Formation', () => {
48 it('should create a balanced legion formation', async () => {
49 // Arrange
50 const availableLegions = MockFactory.createMockLegions(10);
51 const expeditionRequirements = {
52 minLegions: 3,
53 maxLegions: 5,
54 minFirepower: 100,
55 requiredSpecialties: ['Navigation', 'Combat', 'Medical']
56 };
57
58 cohortRepository.find.mockResolvedValue(availableLegions);
59 legionService.findAvailableLegion.mockResolvedValue(MockFactory.createMockLegionMembers(50));
60
61 // Act
62 const formation = await service.createLegionFormation(expeditionRequirements);
63
64 // Assert
65 expect(formation.cohorts).toHaveLength.toBeGreaterThanOrEqual(3);
66 expect(formation.cohorts).toHaveLength.toBeLessThanOrEqual(5);
67 expect(formation.totalFirepower).toBeGreaterThanOrEqual(100);
68 expect(formation.specialties).toEqual(
69 expect.arrayContaining(['Navigation', 'Combat', 'Medical'])
70 );
71 expect(formation.readinessScore).toBeGreaterThan(0.8);
72 });
73
74 it('should throw error when insufficient cohorts available', async () => {
75 // Arrange
76 const insufficientLegions = MockFactory.createMockLegions(2);
77 const requirements = { minLegions: 5, maxLegions: 10 };
78
79 cohortRepository.find.mockResolvedValue(insufficientLegions);
80
81 // Act & Assert
82 await expect(service.createLegionFormation(requirements))
83 .rejects.toThrow('Insufficient cohorts available for legion formation');
84 });
85
86 it('should optimize legion for specific mission types', async () => {
87 // Test different mission types
88 const missionTypes = ['tribute_hunt', 'land_battle', 'exploration', 'rescue'];
89 
90 for (const missionType of missionTypes) {
91 const formation = await service.optimizeLegionForMission(missionType);
92 
93 switch (missionType) {
94 case 'tribute_hunt':
95 expect(formation.cohorts.some(s => s.specialties.includes('Tribute_Detection'))).toBe(true);
96 break;
97 case 'land_battle':
98 expect(formation.totalFirepower).toBeGreaterThan(200);
99 break;
100 case 'exploration':
101 expect(formation.cohorts.some(s => s.specialties.includes('Navigation'))).toBe(true);
102 break;
103 case 'rescue':
104 expect(formation.cohorts.some(s => s.specialties.includes('Medical'))).toBe(true);
105 break;
106 }
107 }
108 });
109 });
110
111 describe('Weather-based Legion Management', () => {
112 it('should adjust legion composition based on weather forecast', async () => {
113 // Arrange
114 const stormyWeather = {
115 condition: 'severe_storm',
116 windSpeed: 60,
117 waveHeight: 8,
118 visibility: 'poor'
119 };
120 
121 weatherService.getForecast.mockResolvedValue(stormyWeather);
122
123 // Act
124 const adjustedLegion = await service.adjustLegionForWeather('expedition-123');
125
126 // Assert
127 expect(adjustedLegion.cohorts.every(s => s.stormResistance >= 8)).toBe(true);
128 expect(adjustedLegion.recommendedAction).toBe('postpone_or_shelter');
129 });
130
131 it('should calculate optimal marching windows', async () => {
132 // Arrange
133 const weatherForecast = MockFactory.createWeatherForecast(7); // 7 days
134 weatherService.getExtendedForecast.mockResolvedValue(weatherForecast);
135
136 // Act
137 const marchingWindows = await service.calculateOptimalMarchingWindows();
138
139 // Assert
140 expect(marchingWindows).toHaveLength.toBeGreaterThan(0);
141 marchingWindows.forEach(window => {
142 expect(window.riskLevel).toBeLessThanOrEqual(3); // Max acceptable risk
143 expect(window.duration).toBeGreaterThan(4); // Min 4 hours window
144 });
145 });
146 });
147
148 describe('Performance Optimization', () => {
149 it('should handle large legion operations efficiently', async () => {
150 // Arrange
151 const largeLegion = MockFactory.createMockLegions(100);
152 legionRepository.find.mockResolvedValue(largeLegion);
153
154 // Act
155 const startTime = Date.now();
156 const result = await service.optimizeLegionPositions(largeLegion);
157 const endTime = Date.now();
158
159 // Assert
160 expect(endTime - startTime).toBeLessThan(1000); // Should complete in <1s
161 expect(result.optimizedPositions).toHaveLength(100);
162 expect(result.efficiencyGain).toBeGreaterThan(0.15); // 15% improvement
163 });
164
165 it('should maintain performance under concurrent operations', async () => {
166 // Arrange
167 const concurrentOperations = 50;
168 const operations = Array.from({ length: concurrentOperations }, (_, i) => 
169 service.processLegionUpdate(`legion-${i}`, MockFactory.createLegionUpdate())
170 );
171
172 // Act
173 const startTime = Date.now();
174 const results = await Promise.allSettled(operations);
175 const endTime = Date.now();
176
177 // Assert
178 const successfulOperations = results.filter(r => r.status === 'fulfilled').length;
179 expect(successfulOperations).toBeGreaterThan(45); // 90% success rate
180 expect(endTime - startTime).toBeLessThan(5000); // Complete in <5s
181 });
182 });
183
184 describe('Error Handling and Edge Cases', () => {
185 it('should handle database connection failures gracefully', async () => {
186 // Arrange
187 legionRepository.find.mockRejectedValue(new Error('Database connection failed'));
188
189 // Act & Assert
190 await expect(service.getAllLegions())
191 .rejects.toThrow('Unable to retrieve legion data');
192 
193 // Verify retry logic was attempted
194 expect(legionRepository.find).toHaveBeenCalledTimes(3); // Original + 2 retries
195 });
196
197 it('should validate legion data integrity', async () => {
198 // Test with corrupted data
199 const corruptedLegionData = {
200 id: 'legion-1',
201 cohorts: [
202 { id: 'cohort-1', health: -50 }, // Invalid health
203 { id: 'cohort-2', legion: null }, // Missing legion
204 { id: 'cohort-3', position: { lat: 91, lng: 181 } } // Invalid coordinates
205 ]
206 };
207
208 await expect(service.validateLegionData(corruptedLegionData))
209 .rejects.toThrow('Legion data validation failed');
210 });
211
212 it('should handle resource constraints', async () => {
213 // Arrange - simulate low resources
214 const limitedResources = {
215 availableLegion: 5,
216 availableLegions: 2,
217 maxBudget: 1000
218 };
219
220 // Act
221 const formation = await service.createLegionWithConstraints(limitedResources);
222
223 // Assert
224 expect(formation.cohorts).toHaveLength.toBeLessThanOrEqual(2);
225 expect(formation.totalCost).toBeLessThanOrEqual(1000);
226 expect(formation.feasible).toBe(true);
227 });
228 });
229});

Integration Tests

Legion-Expedition Integration

1// test/integration/legion-expedition.integration.spec.ts
2describe('Legion-Expedition Integration', () => {
3 let app: TestingModule;
4 let legionService: LegionService;
5 let expeditionService: ExpeditionService;
6 let dataSource: DataSource;
7
8 beforeEach(async () => {
9 app = await Test.createTestingModule({
10 imports: [
11 TypeOrmModule.forRoot(testDatabaseConfig),
12 LegionModule,
13 ExpeditionModule,
14 LegionModule,
15 WeatherModule
16 ],
17 }).compile();
18
19 legionService = app.get<LegionService>(LegionService);
20 expeditionService = app.get<ExpeditionService>(ExpeditionService);
21 dataSource = app.get<DataSource>(DataSource);
22
23 await seedTestData(dataSource);
24 });
25
26 afterEach(async () => {
27 await cleanupTestData(dataSource);
28 await app.close();
29 });
30
31 describe('Complete Expedition Lifecycle', () => {
32 it('should handle full expedition from planning to completion', async () => {
33 // Phase 1: Plan Expedition
34 const expeditionPlan = {
35 destination: { lat: 25.7617, lng: -80.1918 },
36 objectives: ['tribute_hunt', 'mapping'],
37 maxDuration: 14, // days
38 riskTolerance: 'medium'
39 };
40
41 const plannedExpedition = await expeditionService.planExpedition(expeditionPlan);
42 expect(plannedExpedition.feasible).toBe(true);
43 expect(plannedExpedition.estimatedDuration).toBeLessThanOrEqual(14);
44
45 // Phase 2: Assign Legion
46 const assignedLegion = await legionService.assignLegionToExpedition(
47 plannedExpedition.id,
48 plannedExpedition.recommendedLegionSize
49 );
50 
51 expect(assignedLegion.cohorts).toHaveLength.toBeGreaterThan(0);
52 expect(assignedLegion.totalLegion).toBeGreaterThan(plannedExpedition.minLegionRequired);
53
54 // Phase 3: Pre-departure Checks
55 const readinessCheck = await legionService.performReadinessCheck(assignedLegion.id);
56 expect(readinessCheck.ready).toBe(true);
57 expect(readinessCheck.issues).toHaveLength(0);
58
59 // Phase 4: Launch Expedition
60 const launchedExpedition = await expeditionService.launchExpedition(
61 plannedExpedition.id,
62 assignedLegion.id
63 );
64 
65 expect(launchedExpedition.status).toBe('active');
66 expect(launchedExpedition.departureTime).toBeDefined();
67
68 // Phase 5: Track Progress (simulate)
69 const progressUpdates = await expeditionService.simulateExpeditionProgress(
70 launchedExpedition.id,
71 { simulationSpeed: 1000 } // 1000x speed
72 );
73
74 expect(progressUpdates).toHaveLength.toBeGreaterThan(0);
75 
76 // Phase 6: Complete Expedition
77 const completedExpedition = await expeditionService.completeExpedition(
78 launchedExpedition.id
79 );
80
81 expect(completedExpedition.status).toBe('completed');
82 expect(completedExpedition.results.tributesFound).toBeDefined();
83 expect(completedExpedition.results.mapDataCollected).toBeDefined();
84
85 // Phase 7: Return Legion
86 const returnedLegion = await legionService.processLegionReturn(
87 assignedLegion.id,
88 completedExpedition.results
89 );
90
91 expect(returnedLegion.status).toBe('available');
92 expect(returnedLegion.experience).toBeGreaterThan(assignedLegion.experience);
93 });
94
95 it('should handle expedition failures and legion recovery', async () => {
96 // Simulate failed expedition
97 const riskyExpedition = {
98 destination: { lat: 0, lng: 0 }, // Dangerous waters
99 riskTolerance: 'high',
100 forceWeatherIgnore: true
101 };
102
103 const expedition = await expeditionService.planExpedition(riskyExpedition);
104 const legion = await legionService.assignLegionToExpedition(expedition.id);
105 
106 // Force failure
107 const failedExpedition = await expeditionService.simulateExpeditionFailure(
108 expedition.id,
109 'severe_storm'
110 );
111
112 expect(failedExpedition.status).toBe('failed');
113 expect(failedExpedition.failureReason).toBe('severe_storm');
114
115 // Test recovery
116 const recoveryOperation = await legionService.initiateLegionRecovery(
117 legion.id,
118 failedExpedition.lastKnownPosition
119 );
120
121 expect(recoveryOperation.status).toBe('in_progress');
122 expect(recoveryOperation.rescueLegion).toBeDefined();
123 });
124 });
125
126 describe('Cross-service Data Consistency', () => {
127 it('should maintain data consistency across legion and expedition services', async () => {
128 // Create expedition with legion
129 const expedition = await expeditionService.create({
130 name: 'Test Expedition',
131 destination: { lat: 30, lng: -90 }
132 });
133
134 const legion = await legionService.create({
135 name: 'Test Legion',
136 expeditionId: expedition.id
137 });
138
139 // Verify bidirectional relationship
140 const expeditionWithLegion = await expeditionService.findWithLegion(expedition.id);
141 const legionWithExpedition = await legionService.findWithExpedition(legion.id);
142
143 expect(expeditionWithLegion.legion.id).toBe(legion.id);
144 expect(legionWithExpedition.expedition.id).toBe(expedition.id);
145
146 // Test transactional update
147 await expeditionService.updateExpeditionAndLegion(
148 expedition.id,
149 { status: 'active' },
150 { status: 'deployed' }
151 );
152
153 const updatedExpedition = await expeditionService.findById(expedition.id);
154 const updatedLegion = await legionService.findById(legion.id);
155
156 expect(updatedExpedition.status).toBe('active');
157 expect(updatedLegion.status).toBe('deployed');
158 });
159
160 it('should handle concurrent modifications correctly', async () => {
161 const legion = await legionService.create({ name: 'Concurrent Test Legion' });
162
163 // Simulate concurrent updates
164 const updates = [
165 legionService.updateLegionPosition(legion.id, { lat: 25, lng: -80 }),
166 legionService.updateLegionStatus(legion.id, 'moving'),
167 legionService.addCohortToLegion(legion.id, 'new-cohort-123'),
168 legionService.updateLegionSupplies(legion.id, { food: 500, water: 300 })
169 ];
170
171 const results = await Promise.allSettled(updates);
172 const successfulUpdates = results.filter(r => r.status === 'fulfilled');
173
174 expect(successfulUpdates.length).toBeGreaterThan(2); // At least 2 should succeed
175
176 // Verify final state is consistent
177 const finalLegion = await legionService.findById(legion.id);
178 expect(finalLegion).toBeDefined();
179 expect(finalLegion.version).toBeGreaterThan(legion.version); // Optimistic locking
180 });
181 });
182});

E2E Tests

Complete Legion Operations E2E

1// test/e2e/legion-operations.e2e.spec.ts
2describe('Legion Operations E2E', () => {
3 let app: INestApplication;
4 let authToken: string;
5
6 beforeAll(async () => {
7 app = await createE2ETestApp();
8 authToken = await getAuthToken('legion-legate');
9 });
10
11 afterAll(async () => {
12 await app.close();
13 });
14
15 describe('Legate Legion Management Workflow', () => {
16 it('should complete full legion management scenario', async () => {
17 // Step 1: Legate logs in and views legion dashboard
18 const dashboardResponse = await request(app.getHttpServer())
19 .get('/api/legion/dashboard')
20 .set('Authorization', `Bearer ${authToken}`)
21 .expect(200);
22
23 expect(dashboardResponse.body.legions).toBeDefined();
24 expect(dashboardResponse.body.availableLegions).toBeGreaterThan(0);
25
26 // Step 2: Create new legion for expedition
27 const createLegionResponse = await request(app.getHttpServer())
28 .post('/api/legion')
29 .set('Authorization', `Bearer ${authToken}`)
30 .send({
31 name: 'E2E Test Legion',
32 purpose: 'tribute_expedition',
33 maxLegions: 5
34 })
35 .expect(201);
36
37 const legionId = createLegionResponse.body.id;
38
39 // Step 3: Add cohorts to legion
40 const availableLegions = await request(app.getHttpServer())
41 .get('/api/cohorts/available')
42 .set('Authorization', `Bearer ${authToken}`)
43 .expect(200);
44
45 const selectedLegions = availableLegions.body.slice(0, 3);
46 
47 for (const cohort of selectedLegions) {
48 await request(app.getHttpServer())
49 .post(`/api/legion/${legionId}/cohorts`)
50 .set('Authorization', `Bearer ${authToken}`)
51 .send({ cohortId: cohort.id })
52 .expect(201);
53 }
54
55 // Step 4: Assign legion to cohorts
56 const availableLegion = await request(app.getHttpServer())
57 .get('/api/legion/available')
58 .set('Authorization', `Bearer ${authToken}`)
59 .expect(200);
60
61 for (const cohort of selectedLegions) {
62 const legionForLegion = availableLegion.body
63 .filter(c => c.skills.includes('Marching'))
64 .slice(0, 10);
65
66 await request(app.getHttpServer())
67 .post(`/api/cohorts/${cohort.id}/legion`)
68 .set('Authorization', `Bearer ${authToken}`)
69 .send({ legionIds: legionForLegion.map(c => c.id) })
70 .expect(201);
71 }
72
73 // Step 5: Plan expedition
74 const expeditionResponse = await request(app.getHttpServer())
75 .post('/api/expeditions')
76 .set('Authorization', `Bearer ${authToken}`)
77 .send({
78 name: 'E2E Tribute Hunt',
79 destination: {
80 name: 'Tribute Island',
81 coordinates: { lat: 25.7617, lng: -80.1918 }
82 },
83 objectives: ['tribute_hunt'],
84 legionId: legionId,
85 maxDuration: 7
86 })
87 .expect(201);
88
89 const expeditionId = expeditionResponse.body.id;
90
91 // Step 6: Perform pre-departure checks
92 const readinessCheck = await request(app.getHttpServer())
93 .post(`/api/legion/${legionId}/readiness-check`)
94 .set('Authorization', `Bearer ${authToken}`)
95 .expect(200);
96
97 expect(readinessCheck.body.ready).toBe(true);
98 expect(readinessCheck.body.issues).toHaveLength(0);
99
100 // Step 7: Launch expedition
101 const launchResponse = await request(app.getHttpServer())
102 .post(`/api/expeditions/${expeditionId}/launch`)
103 .set('Authorization', `Bearer ${authToken}`)
104 .expect(200);
105
106 expect(launchResponse.body.status).toBe('active');
107 expect(launchResponse.body.departureTime).toBeDefined();
108
109 // Step 8: Monitor expedition progress
110 const progressResponse = await request(app.getHttpServer())
111 .get(`/api/expeditions/${expeditionId}/progress`)
112 .set('Authorization', `Bearer ${authToken}`)
113 .expect(200);
114
115 expect(progressResponse.body.currentPosition).toBeDefined();
116 expect(progressResponse.body.estimatedArrival).toBeDefined();
117
118 // Step 9: Simulate completion (accelerated)
119 await request(app.getHttpServer())
120 .post(`/api/expeditions/${expeditionId}/simulate-completion`)
121 .set('Authorization', `Bearer ${authToken}`)
122 .send({ accelerated: true })
123 .expect(200);
124
125 // Step 10: Check expedition results
126 const resultsResponse = await request(app.getHttpServer())
127 .get(`/api/expeditions/${expeditionId}/results`)
128 .set('Authorization', `Bearer ${authToken}`)
129 .expect(200);
130
131 expect(resultsResponse.body.status).toBe('completed');
132 expect(resultsResponse.body.tributesFound).toBeGreaterThan(0);
133 expect(resultsResponse.body.experienceGained).toBeGreaterThan(0);
134
135 // Step 11: Process legion return
136 const returnResponse = await request(app.getHttpServer())
137 .post(`/api/legion/${legionId}/process-return`)
138 .set('Authorization', `Bearer ${authToken}`)
139 .send({ expeditionId })
140 .expect(200);
141
142 expect(returnResponse.body.status).toBe('available');
143
144 // Step 12: Verify updated dashboard
145 const updatedDashboard = await request(app.getHttpServer())
146 .get('/api/legion/dashboard')
147 .set('Authorization', `Bearer ${authToken}`)
148 .expect(200);
149
150 expect(updatedDashboard.body.completedExpeditions)
151 .toBeGreaterThan(dashboardResponse.body.completedExpeditions);
152 });
153
154 it('should handle emergency scenarios', async () => {
155 // Create legion in dangerous situation
156 const emergencyLegion = await createTestLegion('Emergency Legion');
157 
158 // Simulate emergency (storm, attack, etc.)
159 await request(app.getHttpServer())
160 .post(`/api/legion/${emergencyLegion.id}/emergency`)
161 .set('Authorization', `Bearer ${authToken}`)
162 .send({
163 type: 'severe_storm',
164 severity: 'critical',
165 position: { lat: 25, lng: -80 }
166 })
167 .expect(200);
168
169 // Check emergency response
170 const emergencyResponse = await request(app.getHttpServer())
171 .get(`/api/legion/${emergencyLegion.id}/emergency-status`)
172 .set('Authorization', `Bearer ${authToken}`)
173 .expect(200);
174
175 expect(emergencyResponse.body.status).toBe('emergency');
176 expect(emergencyResponse.body.actionsTaken).toHaveLength.toBeGreaterThan(0);
177
178 // Launch rescue operation
179 const rescueResponse = await request(app.getHttpServer())
180 .post('/api/legion/rescue')
181 .set('Authorization', `Bearer ${authToken}`)
182 .send({
183 targetLegionId: emergencyLegion.id,
184 rescueType: 'weather_emergency'
185 })
186 .expect(201);
187
188 expect(rescueResponse.body.rescueLegion).toBeDefined();
189 expect(rescueResponse.body.estimatedArrival).toBeDefined();
190 });
191 });
192});

Performance Tests

1// test/performance/legion-load-test.spec.ts
2describe('Legion Performance Tests', () => {
3 let app: INestApplication;
4
5 beforeAll(async () => {
6 app = await createPerformanceTestApp();
7 });
8
9 describe('High Load Scenarios', () => {
10 it('should handle 1000 concurrent legion status requests', async () => {
11 const concurrentRequests = 1000;
12 const requestPromises = [];
13
14 for (let i = 0; i < concurrentRequests; i++) {
15 requestPromises.push(
16 request(app.getHttpServer())
17 .get('/api/legion/status')
18 .set('Authorization', `Bearer ${await getTestToken()}`)
19 );
20 }
21
22 const startTime = Date.now();
23 const results = await Promise.allSettled(requestPromises);
24 const endTime = Date.now();
25
26 const successfulRequests = results.filter(r => r.status === 'fulfilled').length;
27 const averageResponseTime = (endTime - startTime) / concurrentRequests;
28
29 expect(successfulRequests).toBeGreaterThan(950); // 95% success rate
30 expect(averageResponseTime).toBeLessThan(50); // < 50ms average
31 expect(endTime - startTime).toBeLessThan(10000); // Complete in < 10s
32 });
33
34 it('should maintain performance with large legion sizes', async () => {
35 // Create large legion (100 cohorts)
36 const largeLegion = await createLargeTestLegion(100);
37
38 const operations = [
39 'GET /api/legion/' + largeLegion.id,
40 'GET /api/legion/' + largeLegion.id + '/cohorts',
41 'GET /api/legion/' + largeLegion.id + '/analytics',
42 'POST /api/legion/' + largeLegion.id + '/optimize',
43 'GET /api/legion/' + largeLegion.id + '/formation'
44 ];
45
46 const results = [];
47
48 for (const operation of operations) {
49 const [method, path] = operation.split(' ');
50 const startTime = Date.now();
51 
52 await request(app.getHttpServer())
53 [method.toLowerCase()](path)
54 .set('Authorization', `Bearer ${await getTestToken()}`)
55 .expect(200);
56 
57 const endTime = Date.now();
58 results.push({ operation, duration: endTime - startTime });
59 }
60
61 // All operations should complete in reasonable time
62 results.forEach(result => {
63 expect(result.duration).toBeLessThan(2000); // < 2s per operation
64 });
65 });
66 });
67
68 describe('Memory Usage Tests', () => {
69 it('should not create memory leaks during legion operations', async () => {
70 const initialMemory = process.memoryUsage().heapUsed;
71 
72 // Perform intensive legion operations
73 for (let cycle = 0; cycle < 100; cycle++) {
74 const legion = await createTestLegion(`Memory Test Legion ${cycle}`);
75 await performLegionOperations(legion.id);
76 await deleteTestLegion(legion.id);
77 
78 if (cycle % 10 === 0) {
79 global.gc?.(); // Force garbage collection
80 }
81 }
82
83 global.gc?.(); // Final cleanup
84 const finalMemory = process.memoryUsage().heapUsed;
85 const memoryIncrease = finalMemory - initialMemory;
86
87 expect(memoryIncrease).toBeLessThan(50 * 1024 * 1024); // < 50MB increase
88 });
89 });
90});

Automated Test Execution Strategy

Test Execution Plan

1// test/automation/test-execution-plan.ts
2export class TestExecutionPlan {
3 static getTestPlan(): TestPlan {
4 return {
5 phases: [
6 {
7 name: 'Unit Tests',
8 parallel: true,
9 timeout: 300000, // 5 minutes
10 requiredCoverage: 95,
11 failFast: true,
12 tests: [
13 'test/unit/**/*.spec.ts'
14 ]
15 },
16 {
17 name: 'Integration Tests',
18 parallel: false,
19 timeout: 600000, // 10 minutes
20 dependsOn: ['Unit Tests'],
21 tests: [
22 'test/integration/**/*.spec.ts'
23 ]
24 },
25 {
26 name: 'E2E Tests',
27 parallel: false,
28 timeout: 1800000, // 30 minutes
29 dependsOn: ['Integration Tests'],
30 environment: 'e2e',
31 tests: [
32 'test/e2e/**/*.spec.ts'
33 ]
34 },
35 {
36 name: 'Performance Tests',
37 parallel: false,
38 timeout: 3600000, // 1 hour
39 dependsOn: ['E2E Tests'],
40 environment: 'performance',
41 runOn: ['nightly', 'release'],
42 tests: [
43 'test/performance/**/*.spec.ts'
44 ]
45 }
46 ],
47 reporting: {
48 formats: ['junit', 'coverage', 'performance'],
49 destinations: ['ci', 'slack', 'dashboard']
50 },
51 notifications: {
52 onFailure: ['email', 'slack'],
53 onSuccess: ['dashboard']
54 }
55 };
56 }
57}

Deliverables projektu

1. Test Suite (3-4 dni)

  • Kompletsowy set unit testów (95% coverage)
  • Integration testy dla wszystkich modułów
  • E2E testy kluczowych scenariuszy
  • Performance testy obciążeniowe

2. Test Infrastructure (2 dni)

  • CI/CD pipeline z automatycznymi testami
  • Test data factories i fixtures
  • Mock libraries i test utilities
  • Performance monitoring

3. Documentation (1 dzień)

  • Test strategy documentation
  • Test execution guidelines
  • Performance benchmarks
  • Troubleshooting guide

4. Quality Gates (1 dzień)

  • Automated quality checks
  • Coverage requirements
  • Performance thresholds
  • Security scan integration

Kryteria oceny

Test Coverage: Minimum 95% statement coverage dla logiki biznesowej ✅ Test Quality: Meaningful tests z proper assertions ✅ Performance: Wszystkie testy wydajnościowe przechodzą w wyznaczonych progach ✅ Integration: Pełne pokrycie integration flow ✅ E2E Scenarios: Kluczowe user journeys przetestowane ✅ Automation: W pełni zautomatyzowany CI/CD pipeline ✅ Documentation: Kompletna dokumentacja strategii testowej ✅ Code Quality: Clean, maintainable test code

Powodzenia, legacie! Ten projekt pokaże, czy jesteś gotowy/a dowodzić legionem najlepszych legionistów-testerów na polach bitew programowania!

Przejdź do CodeWorlds