code-abyss 1.6.16 → 1.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (92) hide show
  1. package/package.json +2 -2
  2. package/skills/SKILL.md +24 -16
  3. package/skills/domains/ai/SKILL.md +2 -2
  4. package/skills/domains/ai/prompt-and-eval.md +279 -0
  5. package/skills/domains/architecture/SKILL.md +2 -3
  6. package/skills/domains/architecture/security-arch.md +87 -0
  7. package/skills/domains/data-engineering/SKILL.md +188 -26
  8. package/skills/domains/development/SKILL.md +1 -4
  9. package/skills/domains/devops/SKILL.md +3 -5
  10. package/skills/domains/devops/performance.md +63 -0
  11. package/skills/domains/devops/testing.md +97 -0
  12. package/skills/domains/frontend-design/SKILL.md +12 -3
  13. package/skills/domains/frontend-design/claymorphism/SKILL.md +117 -0
  14. package/skills/domains/frontend-design/claymorphism/references/tokens.css +52 -0
  15. package/skills/domains/frontend-design/engineering.md +287 -0
  16. package/skills/domains/frontend-design/glassmorphism/SKILL.md +138 -0
  17. package/skills/domains/frontend-design/glassmorphism/references/tokens.css +32 -0
  18. package/skills/domains/frontend-design/liquid-glass/SKILL.md +135 -0
  19. package/skills/domains/frontend-design/liquid-glass/references/tokens.css +81 -0
  20. package/skills/domains/frontend-design/neubrutalism/SKILL.md +141 -0
  21. package/skills/domains/frontend-design/neubrutalism/references/tokens.css +44 -0
  22. package/skills/domains/infrastructure/SKILL.md +174 -34
  23. package/skills/domains/mobile/SKILL.md +211 -21
  24. package/skills/domains/orchestration/SKILL.md +1 -0
  25. package/skills/domains/security/SKILL.md +4 -6
  26. package/skills/domains/security/blue-team.md +57 -0
  27. package/skills/domains/security/red-team.md +54 -0
  28. package/skills/domains/security/threat-intel.md +50 -0
  29. package/skills/orchestration/multi-agent/SKILL.md +195 -46
  30. package/skills/run_skill.js +134 -0
  31. package/skills/tools/gen-docs/SKILL.md +6 -4
  32. package/skills/tools/gen-docs/scripts/doc_generator.js +349 -0
  33. package/skills/tools/verify-change/SKILL.md +8 -6
  34. package/skills/tools/verify-change/scripts/change_analyzer.js +270 -0
  35. package/skills/tools/verify-module/SKILL.md +6 -4
  36. package/skills/tools/verify-module/scripts/module_scanner.js +145 -0
  37. package/skills/tools/verify-quality/SKILL.md +5 -3
  38. package/skills/tools/verify-quality/scripts/quality_checker.js +276 -0
  39. package/skills/tools/verify-security/SKILL.md +7 -5
  40. package/skills/tools/verify-security/scripts/security_scanner.js +133 -0
  41. package/skills/__pycache__/run_skill.cpython-312.pyc +0 -0
  42. package/skills/domains/COVERAGE_PLAN.md +0 -232
  43. package/skills/domains/ai/model-evaluation.md +0 -790
  44. package/skills/domains/ai/prompt-engineering.md +0 -703
  45. package/skills/domains/architecture/compliance.md +0 -299
  46. package/skills/domains/architecture/data-security.md +0 -184
  47. package/skills/domains/data-engineering/data-pipeline.md +0 -762
  48. package/skills/domains/data-engineering/data-quality.md +0 -894
  49. package/skills/domains/data-engineering/stream-processing.md +0 -791
  50. package/skills/domains/development/dart.md +0 -963
  51. package/skills/domains/development/kotlin.md +0 -834
  52. package/skills/domains/development/php.md +0 -659
  53. package/skills/domains/development/swift.md +0 -755
  54. package/skills/domains/devops/e2e-testing.md +0 -914
  55. package/skills/domains/devops/performance-testing.md +0 -734
  56. package/skills/domains/devops/testing-strategy.md +0 -667
  57. package/skills/domains/frontend-design/build-tools.md +0 -743
  58. package/skills/domains/frontend-design/performance.md +0 -734
  59. package/skills/domains/frontend-design/testing.md +0 -699
  60. package/skills/domains/infrastructure/gitops.md +0 -735
  61. package/skills/domains/infrastructure/iac.md +0 -855
  62. package/skills/domains/infrastructure/kubernetes.md +0 -1018
  63. package/skills/domains/mobile/android-dev.md +0 -979
  64. package/skills/domains/mobile/cross-platform.md +0 -795
  65. package/skills/domains/mobile/ios-dev.md +0 -931
  66. package/skills/domains/security/secrets-management.md +0 -834
  67. package/skills/domains/security/supply-chain.md +0 -931
  68. package/skills/domains/security/threat-modeling.md +0 -828
  69. package/skills/run_skill.py +0 -153
  70. package/skills/tests/README.md +0 -225
  71. package/skills/tests/SUMMARY.md +0 -362
  72. package/skills/tests/__init__.py +0 -3
  73. package/skills/tests/__pycache__/test_change_analyzer.cpython-312.pyc +0 -0
  74. package/skills/tests/__pycache__/test_doc_generator.cpython-312.pyc +0 -0
  75. package/skills/tests/__pycache__/test_module_scanner.cpython-312.pyc +0 -0
  76. package/skills/tests/__pycache__/test_quality_checker.cpython-312.pyc +0 -0
  77. package/skills/tests/__pycache__/test_security_scanner.cpython-312.pyc +0 -0
  78. package/skills/tests/test_change_analyzer.py +0 -558
  79. package/skills/tests/test_doc_generator.py +0 -538
  80. package/skills/tests/test_module_scanner.py +0 -376
  81. package/skills/tests/test_quality_checker.py +0 -516
  82. package/skills/tests/test_security_scanner.py +0 -426
  83. package/skills/tools/gen-docs/scripts/__pycache__/doc_generator.cpython-312.pyc +0 -0
  84. package/skills/tools/gen-docs/scripts/doc_generator.py +0 -520
  85. package/skills/tools/verify-change/scripts/__pycache__/change_analyzer.cpython-312.pyc +0 -0
  86. package/skills/tools/verify-change/scripts/change_analyzer.py +0 -529
  87. package/skills/tools/verify-module/scripts/__pycache__/module_scanner.cpython-312.pyc +0 -0
  88. package/skills/tools/verify-module/scripts/module_scanner.py +0 -321
  89. package/skills/tools/verify-quality/scripts/__pycache__/quality_checker.cpython-312.pyc +0 -0
  90. package/skills/tools/verify-quality/scripts/quality_checker.py +0 -481
  91. package/skills/tools/verify-security/scripts/__pycache__/security_scanner.cpython-312.pyc +0 -0
  92. package/skills/tools/verify-security/scripts/security_scanner.py +0 -374
@@ -1,667 +0,0 @@
1
- ---
2
- name: testing-strategy
3
- description: 测试策略与架构。测试金字塔、测试左移、契约测试、覆盖率策略、测试分层。当用户提到测试策略、测试金字塔、测试左移、契约测试、测试分层、测试覆盖率时使用。
4
- ---
5
-
6
- # 🎯 测试金字塔 · Testing Strategy
7
-
8
- ## 测试金字塔 (Test Pyramid)
9
-
10
- ```
11
- /\
12
- /E2E\ 10% - 慢、脆弱、昂贵
13
- /------\
14
- / 集成 \ 20% - 中速、稳定
15
- /----------\
16
- / 单元 \ 70% - 快、稳定、便宜
17
- /--------------\
18
- ```
19
-
20
- ### 层级比例
21
- | 层级 | 占比 | 执行时间 | 成本 | 维护性 |
22
- |------|------|----------|------|--------|
23
- | 单元测试 | 70% | <1s | 低 | 高 |
24
- | 集成测试 | 20% | 1-10s | 中 | 中 |
25
- | E2E测试 | 10% | 10s-5m | 高 | 低 |
26
-
27
- ### 反模式:冰淇淋锥
28
- ```
29
- /--------------\
30
- / E2E \ 大量 E2E - 慢、不稳定
31
- /----------------\
32
- / 集成 \ 少量集成
33
- /--------------------\
34
- / 单元 \ 极少单元 - 反模式!
35
- ```
36
-
37
- ## 测试左移 (Shift-Left Testing)
38
-
39
- ```
40
- 传统流程:
41
- 需求 → 开发 → 测试 → 部署
42
-
43
- 测试介入晚
44
-
45
- 左移流程:
46
- 需求 → 开发 → 部署
47
- ↓ ↓ ↓
48
- 测试 测试 测试
49
-
50
- 测试全程参与
51
- ```
52
-
53
- ### 左移实践
54
- ```yaml
55
- # 需求阶段
56
- - 可测试性评审
57
- - 验收标准定义
58
- - 测试用例设计
59
-
60
- # 开发阶段
61
- - TDD (测试驱动开发)
62
- - 单元测试同步编写
63
- - 代码审查包含测试
64
-
65
- # 提交阶段
66
- - Pre-commit Hook
67
- - 本地测试必过
68
- - 静态分析
69
-
70
- # CI 阶段
71
- - 自动化测试
72
- - 覆盖率门禁
73
- - 性能基准测试
74
- ```
75
-
76
- ## 契约测试 (Contract Testing)
77
-
78
- ### 消费者驱动契约 (CDC)
79
- ```
80
- Provider API ←→ Contract ←→ Consumer
81
- ↓ ↓
82
- 验证契约 验证契约
83
- ```
84
-
85
- ### Pact 示例
86
- ```javascript
87
- // Consumer 端
88
- const { Pact } = require('@pact-foundation/pact');
89
-
90
- const provider = new Pact({
91
- consumer: 'UserService',
92
- provider: 'OrderService'
93
- });
94
-
95
- describe('Order API', () => {
96
- beforeAll(() => provider.setup());
97
- afterAll(() => provider.finalize());
98
-
99
- it('获取订单列表', async () => {
100
- await provider.addInteraction({
101
- state: '有3个订单',
102
- uponReceiving: '获取订单请求',
103
- withRequest: {
104
- method: 'GET',
105
- path: '/orders',
106
- headers: { Accept: 'application/json' }
107
- },
108
- willRespondWith: {
109
- status: 200,
110
- headers: { 'Content-Type': 'application/json' },
111
- body: [
112
- { id: 1, status: 'pending' },
113
- { id: 2, status: 'completed' }
114
- ]
115
- }
116
- });
117
-
118
- const response = await fetch('http://localhost:1234/orders');
119
- expect(response.status).toBe(200);
120
- });
121
- });
122
- ```
123
-
124
- ### Provider 验证
125
- ```javascript
126
- // Provider 端
127
- const { Verifier } = require('@pact-foundation/pact');
128
-
129
- new Verifier({
130
- provider: 'OrderService',
131
- providerBaseUrl: 'http://localhost:8080',
132
- pactUrls: ['./pacts/userservice-orderservice.json'],
133
- stateHandlers: {
134
- '有3个订单': async () => {
135
- // 准备测试数据
136
- await db.seed(['order1', 'order2', 'order3']);
137
- }
138
- }
139
- }).verifyProvider();
140
- ```
141
-
142
- ### Spring Cloud Contract
143
- ```groovy
144
- // Contract DSL
145
- Contract.make {
146
- request {
147
- method 'GET'
148
- url '/api/users/1'
149
- }
150
- response {
151
- status 200
152
- body([
153
- id: 1,
154
- name: 'Alice',
155
- email: 'alice@example.com'
156
- ])
157
- headers {
158
- contentType(applicationJson())
159
- }
160
- }
161
- }
162
- ```
163
-
164
- ```java
165
- // Provider 测试
166
- @SpringBootTest
167
- @AutoConfigureStubRunner(
168
- ids = "com.example:user-service:+:stubs:8080",
169
- stubsMode = StubRunnerProperties.StubsMode.LOCAL
170
- )
171
- class ContractTest {
172
- @Test
173
- void shouldReturnUser() {
174
- ResponseEntity<User> response = restTemplate
175
- .getForEntity("http://localhost:8080/api/users/1", User.class);
176
-
177
- assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK);
178
- assertThat(response.getBody().getName()).isEqualTo("Alice");
179
- }
180
- }
181
- ```
182
-
183
- ## 测试分层策略
184
-
185
- ### 单元测试
186
- ```python
187
- # 纯函数测试
188
- def test_calculate_discount():
189
- assert calculate_discount(100, 0.1) == 90
190
- assert calculate_discount(100, 0) == 100
191
- assert calculate_discount(0, 0.5) == 0
192
-
193
- # Mock 外部依赖
194
- from unittest.mock import Mock, patch
195
-
196
- def test_user_service():
197
- mock_db = Mock()
198
- mock_db.find_user.return_value = {'id': 1, 'name': 'Alice'}
199
-
200
- service = UserService(mock_db)
201
- user = service.get_user(1)
202
-
203
- assert user['name'] == 'Alice'
204
- mock_db.find_user.assert_called_once_with(1)
205
-
206
- # 参数化测试
207
- import pytest
208
-
209
- @pytest.mark.parametrize("input,expected", [
210
- ("hello", "HELLO"),
211
- ("World", "WORLD"),
212
- ("", ""),
213
- ])
214
- def test_uppercase(input, expected):
215
- assert input.upper() == expected
216
- ```
217
-
218
- ### 集成测试
219
- ```java
220
- @SpringBootTest
221
- @Testcontainers
222
- class OrderServiceIntegrationTest {
223
-
224
- @Container
225
- static PostgreSQLContainer<?> postgres = new PostgreSQLContainer<>("postgres:15")
226
- .withDatabaseName("testdb");
227
-
228
- @Autowired
229
- private OrderService orderService;
230
-
231
- @Test
232
- void shouldCreateOrder() {
233
- Order order = new Order("user123", List.of("item1", "item2"));
234
- Order saved = orderService.create(order);
235
-
236
- assertThat(saved.getId()).isNotNull();
237
- assertThat(saved.getStatus()).isEqualTo(OrderStatus.PENDING);
238
- }
239
-
240
- @Test
241
- void shouldHandleTransaction() {
242
- assertThrows(InsufficientStockException.class, () -> {
243
- orderService.createWithInsufficientStock();
244
- });
245
-
246
- // 验证事务回滚
247
- assertThat(orderRepository.count()).isEqualTo(0);
248
- }
249
- }
250
- ```
251
-
252
- ### 组件测试
253
- ```typescript
254
- // API 组件测试
255
- import request from 'supertest';
256
- import { app } from '../src/app';
257
-
258
- describe('User API', () => {
259
- it('POST /users - 创建用户', async () => {
260
- const response = await request(app)
261
- .post('/users')
262
- .send({ name: 'Alice', email: 'alice@example.com' })
263
- .expect(201);
264
-
265
- expect(response.body).toMatchObject({
266
- name: 'Alice',
267
- email: 'alice@example.com'
268
- });
269
- });
270
-
271
- it('GET /users/:id - 获取用户', async () => {
272
- const response = await request(app)
273
- .get('/users/1')
274
- .expect(200);
275
-
276
- expect(response.body.id).toBe(1);
277
- });
278
- });
279
- ```
280
-
281
- ## 测试覆盖率策略
282
-
283
- ### 覆盖率类型
284
- ```
285
- 行覆盖率 (Line Coverage) - 代码行是否执行
286
- 分支覆盖率 (Branch Coverage) - 条件分支是否覆盖
287
- 函数覆盖率 (Function Coverage) - 函数是否调用
288
- 语句覆盖率 (Statement Coverage) - 语句是否执行
289
- ```
290
-
291
- ### 覆盖率配置
292
- ```javascript
293
- // Jest 配置
294
- module.exports = {
295
- collectCoverage: true,
296
- coverageThreshold: {
297
- global: {
298
- branches: 80,
299
- functions: 80,
300
- lines: 80,
301
- statements: 80
302
- },
303
- './src/core/': {
304
- branches: 90,
305
- functions: 95,
306
- lines: 95,
307
- statements: 95
308
- }
309
- },
310
- coveragePathIgnorePatterns: [
311
- '/node_modules/',
312
- '/test/',
313
- '.*\\.config\\.js'
314
- ]
315
- };
316
- ```
317
-
318
- ```python
319
- # pytest-cov 配置
320
- [tool.pytest.ini_options]
321
- addopts = """
322
- --cov=src
323
- --cov-report=html
324
- --cov-report=term-missing
325
- --cov-fail-under=80
326
- """
327
-
328
- [tool.coverage.run]
329
- omit = [
330
- "*/tests/*",
331
- "*/migrations/*",
332
- "*/__init__.py"
333
- ]
334
-
335
- [tool.coverage.report]
336
- exclude_lines = [
337
- "pragma: no cover",
338
- "def __repr__",
339
- "raise NotImplementedError",
340
- "if TYPE_CHECKING:"
341
- ]
342
- ```
343
-
344
- ### 覆盖率门禁
345
- ```yaml
346
- # GitHub Actions
347
- - name: Test with coverage
348
- run: npm test -- --coverage
349
-
350
- - name: Coverage check
351
- run: |
352
- COVERAGE=$(cat coverage/coverage-summary.json | jq '.total.lines.pct')
353
- if (( $(echo "$COVERAGE < 80" | bc -l) )); then
354
- echo "Coverage $COVERAGE% is below 80%"
355
- exit 1
356
- fi
357
- ```
358
-
359
- ## TDD (测试驱动开发)
360
-
361
- ### Red-Green-Refactor
362
- ```
363
- 1. Red - 写失败的测试
364
- 2. Green - 写最少代码让测试通过
365
- 3. Refactor - 重构代码
366
- ```
367
-
368
- ### TDD 示例
369
- ```python
370
- # 1. Red - 写测试
371
- def test_fizzbuzz():
372
- assert fizzbuzz(3) == "Fizz"
373
- assert fizzbuzz(5) == "Buzz"
374
- assert fizzbuzz(15) == "FizzBuzz"
375
- assert fizzbuzz(7) == "7"
376
-
377
- # 2. Green - 实现
378
- def fizzbuzz(n):
379
- if n % 15 == 0:
380
- return "FizzBuzz"
381
- if n % 3 == 0:
382
- return "Fizz"
383
- if n % 5 == 0:
384
- return "Buzz"
385
- return str(n)
386
-
387
- # 3. Refactor - 优化
388
- def fizzbuzz(n):
389
- result = ""
390
- if n % 3 == 0:
391
- result += "Fizz"
392
- if n % 5 == 0:
393
- result += "Buzz"
394
- return result or str(n)
395
- ```
396
-
397
- ## BDD (行为驱动开发)
398
-
399
- ### Gherkin 语法
400
- ```gherkin
401
- Feature: 用户登录
402
- 作为一个用户
403
- 我想要登录系统
404
- 以便访问我的账户
405
-
406
- Scenario: 成功登录
407
- Given 用户已注册
408
- When 用户输入正确的用户名和密码
409
- Then 用户应该看到欢迎页面
410
-
411
- Scenario: 密码错误
412
- Given 用户已注册
413
- When 用户输入错误的密码
414
- Then 用户应该看到错误提示
415
- ```
416
-
417
- ### Cucumber 实现
418
- ```javascript
419
- const { Given, When, Then } = require('@cucumber/cucumber');
420
- const { expect } = require('chai');
421
-
422
- Given('用户已注册', async function() {
423
- await this.db.createUser({
424
- username: 'alice',
425
- password: 'password123'
426
- });
427
- });
428
-
429
- When('用户输入正确的用户名和密码', async function() {
430
- this.response = await this.api.login('alice', 'password123');
431
- });
432
-
433
- Then('用户应该看到欢迎页面', function() {
434
- expect(this.response.status).to.equal(200);
435
- expect(this.response.body.message).to.include('欢迎');
436
- });
437
- ```
438
-
439
- ## 测试数据管理
440
-
441
- ### Fixture 模式
442
- ```python
443
- import pytest
444
-
445
- @pytest.fixture
446
- def sample_user():
447
- return {
448
- 'id': 1,
449
- 'name': 'Alice',
450
- 'email': 'alice@example.com'
451
- }
452
-
453
- @pytest.fixture
454
- def db_session():
455
- session = create_session()
456
- yield session
457
- session.rollback()
458
- session.close()
459
-
460
- def test_create_user(db_session, sample_user):
461
- user = User(**sample_user)
462
- db_session.add(user)
463
- db_session.commit()
464
-
465
- assert user.id is not None
466
- ```
467
-
468
- ### Factory 模式
469
- ```javascript
470
- // Factory Bot
471
- const { Factory } = require('rosie');
472
-
473
- Factory.define('user')
474
- .sequence('id')
475
- .attr('name', () => faker.name.findName())
476
- .attr('email', () => faker.internet.email())
477
- .attr('createdAt', () => new Date());
478
-
479
- // 使用
480
- const user = Factory.build('user');
481
- const users = Factory.buildList('user', 10);
482
- const savedUser = await Factory.create('user'); // 保存到数据库
483
- ```
484
-
485
- ### 测试数据隔离
486
- ```java
487
- @TestInstance(TestInstance.Lifecycle.PER_CLASS)
488
- class UserServiceTest {
489
-
490
- @BeforeEach
491
- void setUp() {
492
- // 每个测试前清理
493
- userRepository.deleteAll();
494
- }
495
-
496
- @Test
497
- @Transactional
498
- void testCreateUser() {
499
- // 测试结束自动回滚
500
- }
501
-
502
- @Test
503
- @Sql("/test-data/users.sql")
504
- void testWithSqlData() {
505
- // 使用 SQL 脚本准备数据
506
- }
507
- }
508
- ```
509
-
510
- ## 测试隔离与并行
511
-
512
- ### 并行执行
513
- ```javascript
514
- // Jest 并行配置
515
- module.exports = {
516
- maxWorkers: '50%', // 使用 50% CPU
517
- testTimeout: 10000,
518
- bail: 1, // 首次失败即停止
519
- };
520
- ```
521
-
522
- ```python
523
- # pytest 并行
524
- pytest -n auto # 自动检测 CPU 核心数
525
- pytest -n 4 # 使用 4 个进程
526
- ```
527
-
528
- ### 测试隔离
529
- ```typescript
530
- describe('Order Service', () => {
531
- let service: OrderService;
532
- let mockDb: jest.Mocked<Database>;
533
-
534
- beforeEach(() => {
535
- // 每个测试独立实例
536
- mockDb = createMockDatabase();
537
- service = new OrderService(mockDb);
538
- });
539
-
540
- afterEach(() => {
541
- jest.clearAllMocks();
542
- });
543
-
544
- it('should create order', () => {
545
- // 测试逻辑
546
- });
547
- });
548
- ```
549
-
550
- ## 快照测试
551
-
552
- ### Jest 快照
553
- ```javascript
554
- test('renders correctly', () => {
555
- const tree = renderer.create(
556
- <UserProfile user={{ name: 'Alice', age: 30 }} />
557
- ).toJSON();
558
-
559
- expect(tree).toMatchSnapshot();
560
- });
561
-
562
- // 更新快照
563
- // npm test -- -u
564
- ```
565
-
566
- ### API 响应快照
567
- ```python
568
- def test_api_response(snapshot):
569
- response = client.get('/api/users/1')
570
- snapshot.assert_match(response.json(), 'user_response.json')
571
- ```
572
-
573
- ## 变异测试 (Mutation Testing)
574
-
575
- ### Stryker 配置
576
- ```javascript
577
- // stryker.conf.js
578
- module.exports = {
579
- mutate: ['src/**/*.ts', '!src/**/*.spec.ts'],
580
- testRunner: 'jest',
581
- reporters: ['html', 'clear-text', 'progress'],
582
- coverageAnalysis: 'perTest',
583
- thresholds: { high: 80, low: 60, break: 50 }
584
- };
585
- ```
586
-
587
- ### 变异示例
588
- ```javascript
589
- // 原始代码
590
- function isAdult(age) {
591
- return age >= 18;
592
- }
593
-
594
- // 变异体
595
- function isAdult(age) {
596
- return age > 18; // >= 变为 >
597
- }
598
-
599
- // 如果测试没有覆盖边界值 18,变异体存活
600
- // 说明测试不够充分
601
- ```
602
-
603
- ## 测试最佳实践
604
-
605
- ### AAA 模式
606
- ```python
607
- def test_user_registration():
608
- # Arrange - 准备
609
- user_data = {'username': 'alice', 'email': 'alice@example.com'}
610
-
611
- # Act - 执行
612
- result = register_user(user_data)
613
-
614
- # Assert - 断言
615
- assert result.success is True
616
- assert result.user.username == 'alice'
617
- ```
618
-
619
- ### 测试命名
620
- ```javascript
621
- // ❌ 不好
622
- test('test1', () => {});
623
-
624
- // ✅ 好
625
- test('should return 404 when user not found', () => {});
626
- test('should create order with valid items', () => {});
627
- test('should throw error when stock insufficient', () => {});
628
- ```
629
-
630
- ### 单一职责
631
- ```python
632
- # ❌ 测试多个功能
633
- def test_user_operations():
634
- user = create_user()
635
- update_user(user)
636
- delete_user(user)
637
-
638
- # ✅ 拆分测试
639
- def test_create_user():
640
- user = create_user()
641
- assert user.id is not None
642
-
643
- def test_update_user():
644
- user = create_user()
645
- updated = update_user(user, {'name': 'Bob'})
646
- assert updated.name == 'Bob'
647
-
648
- def test_delete_user():
649
- user = create_user()
650
- delete_user(user)
651
- assert find_user(user.id) is None
652
- ```
653
-
654
- ## 工具清单
655
-
656
- | 工具 | 用途 | 语言 |
657
- |------|------|------|
658
- | Jest | 单元/集成测试 | JavaScript |
659
- | Pytest | 单元/集成测试 | Python |
660
- | JUnit 5 | 单元/集成测试 | Java |
661
- | Pact | 契约测试 | 多语言 |
662
- | Testcontainers | 集成测试 | Java/Go/Python |
663
- | Stryker | 变异测试 | JavaScript |
664
- | Pitest | 变异测试 | Java |
665
- | Faker | 测试数据生成 | 多语言 |
666
-
667
- ---