@softspark/ai-toolkit 1.0.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.
- package/AGENTS.md +412 -0
- package/CHANGELOG.md +68 -0
- package/LICENSE +21 -0
- package/README.md +632 -0
- package/action.yml +53 -0
- package/app/.claude-plugin/plugin.json +44 -0
- package/app/ARCHITECTURE.md +306 -0
- package/app/CLAUDE.md.template +23 -0
- package/app/agents/ai-engineer.md +128 -0
- package/app/agents/backend-specialist.md +193 -0
- package/app/agents/business-intelligence.md +54 -0
- package/app/agents/chaos-monkey.md +67 -0
- package/app/agents/chief-of-staff.md +51 -0
- package/app/agents/code-archaeologist.md +127 -0
- package/app/agents/code-reviewer.md +184 -0
- package/app/agents/command-expert.md +131 -0
- package/app/agents/data-analyst.md +205 -0
- package/app/agents/data-scientist.md +151 -0
- package/app/agents/database-architect.md +317 -0
- package/app/agents/debugger.md +238 -0
- package/app/agents/devops-implementer.md +194 -0
- package/app/agents/documenter.md +364 -0
- package/app/agents/explorer-agent.md +145 -0
- package/app/agents/fact-checker.md +172 -0
- package/app/agents/frontend-specialist.md +209 -0
- package/app/agents/game-developer.md +216 -0
- package/app/agents/incident-responder.md +226 -0
- package/app/agents/infrastructure-architect.md +127 -0
- package/app/agents/infrastructure-validator.md +247 -0
- package/app/agents/llm-ops-engineer.md +237 -0
- package/app/agents/mcp-expert.md +228 -0
- package/app/agents/mcp-server-architect.md +195 -0
- package/app/agents/mcp-testing-engineer.md +292 -0
- package/app/agents/meta-architect.md +58 -0
- package/app/agents/ml-engineer.md +136 -0
- package/app/agents/mobile-developer.md +190 -0
- package/app/agents/night-watchman.md +55 -0
- package/app/agents/nlp-engineer.md +154 -0
- package/app/agents/orchestrator.md +437 -0
- package/app/agents/performance-optimizer.md +254 -0
- package/app/agents/predictive-analyst.md +57 -0
- package/app/agents/product-manager.md +194 -0
- package/app/agents/project-planner.md +287 -0
- package/app/agents/prompt-engineer.md +103 -0
- package/app/agents/qa-automation-engineer.md +182 -0
- package/app/agents/rag-engineer.md +201 -0
- package/app/agents/research-synthesizer.md +138 -0
- package/app/agents/search-specialist.md +101 -0
- package/app/agents/security-architect.md +62 -0
- package/app/agents/security-auditor.md +293 -0
- package/app/agents/seo-specialist.md +111 -0
- package/app/agents/system-governor.md +57 -0
- package/app/agents/tech-lead.md +62 -0
- package/app/agents/technical-researcher.md +103 -0
- package/app/agents/test-engineer.md +264 -0
- package/app/constitution.md +38 -0
- package/app/hooks/_profile-check.sh +11 -0
- package/app/hooks/guard-destructive.sh +74 -0
- package/app/hooks/guard-path.sh +73 -0
- package/app/hooks/post-tool-use.sh +35 -0
- package/app/hooks/pre-compact.sh +31 -0
- package/app/hooks/quality-check.sh +22 -0
- package/app/hooks/quality-gate.sh +49 -0
- package/app/hooks/save-session.sh +24 -0
- package/app/hooks/session-end.sh +37 -0
- package/app/hooks/session-start.sh +29 -0
- package/app/hooks/subagent-start.sh +16 -0
- package/app/hooks/subagent-stop.sh +16 -0
- package/app/hooks/track-usage.sh +50 -0
- package/app/hooks/user-prompt-submit.sh +25 -0
- package/app/hooks.json +178 -0
- package/app/mcp-defaults.json +23 -0
- package/app/output-styles/golden-rules.md +43 -0
- package/app/plugins/README.md +19 -0
- package/app/plugins/csharp-pack/README.md +11 -0
- package/app/plugins/csharp-pack/plugin.json +18 -0
- package/app/plugins/enterprise-pack/README.md +16 -0
- package/app/plugins/enterprise-pack/hooks/output-style.sh +6 -0
- package/app/plugins/enterprise-pack/hooks/status-line.sh +8 -0
- package/app/plugins/enterprise-pack/plugin.json +24 -0
- package/app/plugins/frontend-pack/README.md +14 -0
- package/app/plugins/frontend-pack/plugin.json +22 -0
- package/app/plugins/java-pack/README.md +11 -0
- package/app/plugins/java-pack/plugin.json +18 -0
- package/app/plugins/kotlin-pack/README.md +11 -0
- package/app/plugins/kotlin-pack/plugin.json +18 -0
- package/app/plugins/memory-pack/README.md +24 -0
- package/app/plugins/memory-pack/hooks/observation-capture.sh +67 -0
- package/app/plugins/memory-pack/hooks/session-summary.sh +71 -0
- package/app/plugins/memory-pack/plugin.json +22 -0
- package/app/plugins/memory-pack/scripts/init_db.py +81 -0
- package/app/plugins/memory-pack/scripts/strip_private.py +22 -0
- package/app/plugins/memory-pack/skills/mem-search/SKILL.md +70 -0
- package/app/plugins/research-pack/README.md +14 -0
- package/app/plugins/research-pack/plugin.json +22 -0
- package/app/plugins/ruby-pack/README.md +11 -0
- package/app/plugins/ruby-pack/plugin.json +18 -0
- package/app/plugins/rust-pack/README.md +11 -0
- package/app/plugins/rust-pack/plugin.json +18 -0
- package/app/plugins/security-pack/README.md +15 -0
- package/app/plugins/security-pack/plugin.json +23 -0
- package/app/plugins/swift-pack/README.md +11 -0
- package/app/plugins/swift-pack/plugin.json +18 -0
- package/app/rules/claude-toolkit-rules.md +21 -0
- package/app/rules/git-conventions.md +5 -0
- package/app/rules/quality-gates.md +10 -0
- package/app/skills/_lib/__init__.py +1 -0
- package/app/skills/_lib/detect_utils.py +150 -0
- package/app/skills/agent-creator/SKILL.md +82 -0
- package/app/skills/analyze/SKILL.md +92 -0
- package/app/skills/analyze/scripts/complexity.py +165 -0
- package/app/skills/api-patterns/SKILL.md +305 -0
- package/app/skills/app-builder/SKILL.md +187 -0
- package/app/skills/architecture-audit/SKILL.md +141 -0
- package/app/skills/architecture-decision/SKILL.md +55 -0
- package/app/skills/architecture-decision/templates/adr-template.md +36 -0
- package/app/skills/biz-scan/SKILL.md +30 -0
- package/app/skills/briefing/SKILL.md +27 -0
- package/app/skills/build/SKILL.md +97 -0
- package/app/skills/build/scripts/detect-build.py +151 -0
- package/app/skills/chaos/SKILL.md +32 -0
- package/app/skills/ci/SKILL.md +77 -0
- package/app/skills/ci/scripts/ci-detect.py +135 -0
- package/app/skills/ci/templates/github-actions-node.yml +38 -0
- package/app/skills/ci/templates/github-actions-python.yml +42 -0
- package/app/skills/ci-cd-patterns/SKILL.md +299 -0
- package/app/skills/clean-code/SKILL.md +110 -0
- package/app/skills/clean-code/reference/dart.md +18 -0
- package/app/skills/clean-code/reference/go.md +23 -0
- package/app/skills/clean-code/reference/php.md +32 -0
- package/app/skills/clean-code/reference/python.md +180 -0
- package/app/skills/clean-code/reference/typescript.md +26 -0
- package/app/skills/command-creator/SKILL.md +83 -0
- package/app/skills/commit/SKILL.md +98 -0
- package/app/skills/commit/scripts/pre-commit-check.py +87 -0
- package/app/skills/commit/templates/conventional-commit.md +52 -0
- package/app/skills/csharp-patterns/SKILL.md +450 -0
- package/app/skills/database-patterns/SKILL.md +297 -0
- package/app/skills/debug/SKILL.md +154 -0
- package/app/skills/debug/scripts/error-parser.py +187 -0
- package/app/skills/debugging-tactics/SKILL.md +136 -0
- package/app/skills/deploy/SKILL.md +130 -0
- package/app/skills/deploy/scripts/pre_deploy_check.py +171 -0
- package/app/skills/deploy/templates/deployment-checklist.md +31 -0
- package/app/skills/design-an-interface/SKILL.md +105 -0
- package/app/skills/design-engineering/SKILL.md +260 -0
- package/app/skills/docker-devops/SKILL.md +303 -0
- package/app/skills/docs/SKILL.md +145 -0
- package/app/skills/docs/scripts/doc-inventory.py +176 -0
- package/app/skills/docs/templates/adr-template.md +36 -0
- package/app/skills/docs/templates/readme-template.md +67 -0
- package/app/skills/documentation-standards/SKILL.md +191 -0
- package/app/skills/ecommerce-patterns/SKILL.md +209 -0
- package/app/skills/evaluate/SKILL.md +132 -0
- package/app/skills/evolve/SKILL.md +27 -0
- package/app/skills/explain/SKILL.md +54 -0
- package/app/skills/explain/scripts/dependency-graph.py +215 -0
- package/app/skills/explore/SKILL.md +112 -0
- package/app/skills/explore/scripts/visualize.py +117 -0
- package/app/skills/fix/SKILL.md +78 -0
- package/app/skills/fix/scripts/error-classifier.py +191 -0
- package/app/skills/flutter-patterns/SKILL.md +254 -0
- package/app/skills/git-mastery/SKILL.md +70 -0
- package/app/skills/grill-me/SKILL.md +38 -0
- package/app/skills/health/SKILL.md +91 -0
- package/app/skills/health/scripts/health_check.py +162 -0
- package/app/skills/hive-mind/SKILL.md +56 -0
- package/app/skills/hook-creator/SKILL.md +107 -0
- package/app/skills/index/SKILL.md +74 -0
- package/app/skills/instinct-review/SKILL.md +77 -0
- package/app/skills/java-patterns/SKILL.md +442 -0
- package/app/skills/kotlin-patterns/SKILL.md +446 -0
- package/app/skills/lint/SKILL.md +103 -0
- package/app/skills/lint/scripts/detect-linters.py +112 -0
- package/app/skills/mcp-patterns/SKILL.md +270 -0
- package/app/skills/mem-search/SKILL.md +70 -0
- package/app/skills/migrate/SKILL.md +90 -0
- package/app/skills/migrate/scripts/migration-status.py +195 -0
- package/app/skills/migration-patterns/SKILL.md +260 -0
- package/app/skills/night-watch/SKILL.md +28 -0
- package/app/skills/observability-patterns/SKILL.md +203 -0
- package/app/skills/onboard/SKILL.md +76 -0
- package/app/skills/orchestrate/SKILL.md +86 -0
- package/app/skills/panic/SKILL.md +30 -0
- package/app/skills/performance-profiling/SKILL.md +59 -0
- package/app/skills/plan/SKILL.md +110 -0
- package/app/skills/plan/templates/plan-template.md +40 -0
- package/app/skills/plan-writing/SKILL.md +201 -0
- package/app/skills/plugin-creator/SKILL.md +78 -0
- package/app/skills/pr/SKILL.md +129 -0
- package/app/skills/pr/scripts/pr-summary.py +175 -0
- package/app/skills/prd-to-issues/SKILL.md +108 -0
- package/app/skills/prd-to-plan/SKILL.md +120 -0
- package/app/skills/predict/SKILL.md +30 -0
- package/app/skills/qa-session/SKILL.md +110 -0
- package/app/skills/rag-patterns/SKILL.md +203 -0
- package/app/skills/refactor/SKILL.md +124 -0
- package/app/skills/refactor/scripts/refactor-scan.py +210 -0
- package/app/skills/refactor-plan/SKILL.md +112 -0
- package/app/skills/repeat/SKILL.md +149 -0
- package/app/skills/research-mastery/SKILL.md +56 -0
- package/app/skills/review/SKILL.md +141 -0
- package/app/skills/review/scripts/diff-analyzer.py +170 -0
- package/app/skills/rollback/SKILL.md +87 -0
- package/app/skills/rollback/scripts/rollback_info.py +149 -0
- package/app/skills/ruby-patterns/SKILL.md +454 -0
- package/app/skills/rust-patterns/SKILL.md +446 -0
- package/app/skills/search/SKILL.md +64 -0
- package/app/skills/security-patterns/SKILL.md +91 -0
- package/app/skills/security-patterns/reference/authentication.md +37 -0
- package/app/skills/security-patterns/reference/authorization.md +22 -0
- package/app/skills/security-patterns/reference/input-validation.md +30 -0
- package/app/skills/security-patterns/reference/oauth-csrf-audit.md +131 -0
- package/app/skills/skill-creator/SKILL.md +154 -0
- package/app/skills/skill-creator/templates/dashboard/index.html +130 -0
- package/app/skills/skill-creator/templates/reasoning-engine/assets/example.json +12 -0
- package/app/skills/skill-creator/templates/reasoning-engine/search.py +110 -0
- package/app/skills/subagent-development/SKILL.md +225 -0
- package/app/skills/subagent-development/reference/code-quality-reviewer-prompt.md +145 -0
- package/app/skills/subagent-development/reference/implementer-prompt.md +118 -0
- package/app/skills/subagent-development/reference/spec-reviewer-prompt.md +100 -0
- package/app/skills/swarm/SKILL.md +81 -0
- package/app/skills/swift-patterns/SKILL.md +500 -0
- package/app/skills/tdd/SKILL.md +174 -0
- package/app/skills/tdd/reference/deep-modules.md +32 -0
- package/app/skills/tdd/reference/interface-design.md +32 -0
- package/app/skills/tdd/reference/mocking.md +52 -0
- package/app/skills/tdd/reference/refactoring.md +10 -0
- package/app/skills/tdd/reference/tests.md +59 -0
- package/app/skills/teams/SKILL.md +101 -0
- package/app/skills/test/SKILL.md +107 -0
- package/app/skills/test/scripts/detect-runner.py +113 -0
- package/app/skills/testing-patterns/SKILL.md +73 -0
- package/app/skills/testing-patterns/reference/flutter-testing.md +33 -0
- package/app/skills/testing-patterns/reference/go-testing.md +52 -0
- package/app/skills/testing-patterns/reference/php-phpunit.md +39 -0
- package/app/skills/testing-patterns/reference/python-pytest.md +228 -0
- package/app/skills/testing-patterns/reference/typescript-vitest.md +50 -0
- package/app/skills/triage-issue/SKILL.md +120 -0
- package/app/skills/typescript-patterns/SKILL.md +256 -0
- package/app/skills/ubiquitous-language/SKILL.md +74 -0
- package/app/skills/verification-before-completion/SKILL.md +108 -0
- package/app/skills/workflow/SKILL.md +250 -0
- package/app/skills/write-a-prd/SKILL.md +129 -0
- package/app/skills/write-a-prd/reference/visual-companion.md +78 -0
- package/app/skills/write-a-prd/scripts/frame-template.html +111 -0
- package/app/skills/write-a-prd/scripts/visual-server.cjs +79 -0
- package/app/templates/skill/generator/SKILL.md.template +40 -0
- package/app/templates/skill/knowledge/SKILL.md.template +52 -0
- package/app/templates/skill/linter/SKILL.md.template +34 -0
- package/app/templates/skill/reviewer/SKILL.md.template +51 -0
- package/app/templates/skill/workflow/SKILL.md.template +49 -0
- package/benchmarks/README.md +111 -0
- package/benchmarks/ecosystem-dashboard.json +148 -0
- package/benchmarks/ecosystem-harvest.json +148 -0
- package/benchmarks/results.json +38 -0
- package/benchmarks/run.py +351 -0
- package/bin/ai-toolkit.js +345 -0
- package/kb/best-practices/README.md +11 -0
- package/kb/howto/README.md +11 -0
- package/kb/procedures/maintenance-sop.md +306 -0
- package/kb/reference/agents-catalog.md +124 -0
- package/kb/reference/anti-pattern-registry-format.md +221 -0
- package/kb/reference/architecture-overview.md +232 -0
- package/kb/reference/benchmark-config.md +62 -0
- package/kb/reference/ci-integration.md +66 -0
- package/kb/reference/claude-ecosystem-benchmark-snapshot.md +80 -0
- package/kb/reference/claude-ecosystem-expansion-foundations.md +102 -0
- package/kb/reference/commands-catalog.md +21 -0
- package/kb/reference/distribution-model.md +63 -0
- package/kb/reference/global-install-model.md +56 -0
- package/kb/reference/hierarchical-override-pattern.md +200 -0
- package/kb/reference/hooks-catalog.md +306 -0
- package/kb/reference/integrations.md +88 -0
- package/kb/reference/language-packs.md +52 -0
- package/kb/reference/merge-friendly-install-model.md +58 -0
- package/kb/reference/plugin-pack-conventions.md +151 -0
- package/kb/reference/quick-wins-implementation-summary.md +70 -0
- package/kb/reference/skill-templates.md +50 -0
- package/kb/reference/skills-catalog.md +215 -0
- package/kb/reference/skills-unification.md +57 -0
- package/kb/reference/stats.md +69 -0
- package/kb/reference/sync.md +76 -0
- package/kb/troubleshooting/README.md +11 -0
- package/llms-full.txt +3068 -0
- package/llms.txt +39 -0
- package/package.json +75 -0
- package/scripts/_common.py +160 -0
- package/scripts/add_rule.py +50 -0
- package/scripts/benchmark_config.py +127 -0
- package/scripts/benchmark_ecosystem.py +288 -0
- package/scripts/check_deps.py +260 -0
- package/scripts/create_skill.py +118 -0
- package/scripts/doctor.py +504 -0
- package/scripts/eject.py +113 -0
- package/scripts/emission.py +256 -0
- package/scripts/evaluate_skills.py +260 -0
- package/scripts/frontmatter.py +58 -0
- package/scripts/generate_agents_md.py +91 -0
- package/scripts/generate_aider_conf.py +51 -0
- package/scripts/generate_cline.py +35 -0
- package/scripts/generate_copilot.py +30 -0
- package/scripts/generate_cursor_rules.py +35 -0
- package/scripts/generate_gemini.py +28 -0
- package/scripts/generate_llms_txt.py +164 -0
- package/scripts/generate_roo_modes.py +80 -0
- package/scripts/generate_windsurf.py +35 -0
- package/scripts/generator_base.py +140 -0
- package/scripts/harvest_ecosystem.py +50 -0
- package/scripts/inject_rule_cli.py +101 -0
- package/scripts/inject_section_cli.py +47 -0
- package/scripts/injection.py +180 -0
- package/scripts/install.py +236 -0
- package/scripts/install_git_hooks.py +71 -0
- package/scripts/install_steps/__init__.py +5 -0
- package/scripts/install_steps/ai_tools.py +261 -0
- package/scripts/install_steps/hooks.py +90 -0
- package/scripts/install_steps/markers.py +79 -0
- package/scripts/install_steps/symlinks.py +87 -0
- package/scripts/merge-hooks.py +192 -0
- package/scripts/plugin.py +642 -0
- package/scripts/plugin_schema.py +138 -0
- package/scripts/remove_rule.py +58 -0
- package/scripts/stats.py +81 -0
- package/scripts/sync.py +215 -0
- package/scripts/uninstall.py +292 -0
- package/scripts/validate.py +700 -0
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# Interface Design for Testability
|
|
2
|
+
|
|
3
|
+
Good interfaces make testing natural:
|
|
4
|
+
|
|
5
|
+
## 1. Accept dependencies, don't create them
|
|
6
|
+
|
|
7
|
+
```typescript
|
|
8
|
+
// Testable
|
|
9
|
+
function processOrder(order, paymentGateway) {}
|
|
10
|
+
|
|
11
|
+
// Hard to test
|
|
12
|
+
function processOrder(order) {
|
|
13
|
+
const gateway = new StripeGateway();
|
|
14
|
+
}
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## 2. Return results, don't produce side effects
|
|
18
|
+
|
|
19
|
+
```typescript
|
|
20
|
+
// Testable
|
|
21
|
+
function calculateDiscount(cart): Discount {}
|
|
22
|
+
|
|
23
|
+
// Hard to test
|
|
24
|
+
function applyDiscount(cart): void {
|
|
25
|
+
cart.total -= discount;
|
|
26
|
+
}
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
## 3. Small surface area
|
|
30
|
+
|
|
31
|
+
- Fewer methods = fewer tests needed
|
|
32
|
+
- Fewer params = simpler test setup
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
# When to Mock
|
|
2
|
+
|
|
3
|
+
Mock at **system boundaries** only:
|
|
4
|
+
|
|
5
|
+
- External APIs (payment, email, etc.)
|
|
6
|
+
- Databases (sometimes — prefer test DB)
|
|
7
|
+
- Time/randomness
|
|
8
|
+
- File system (sometimes)
|
|
9
|
+
|
|
10
|
+
Don't mock:
|
|
11
|
+
- Your own classes/modules
|
|
12
|
+
- Internal collaborators
|
|
13
|
+
- Anything you control
|
|
14
|
+
|
|
15
|
+
## Designing for Mockability
|
|
16
|
+
|
|
17
|
+
### 1. Use dependency injection
|
|
18
|
+
|
|
19
|
+
```typescript
|
|
20
|
+
// Easy to mock
|
|
21
|
+
function processPayment(order, paymentClient) {
|
|
22
|
+
return paymentClient.charge(order.total);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
// Hard to mock
|
|
26
|
+
function processPayment(order) {
|
|
27
|
+
const client = new StripeClient(process.env.STRIPE_KEY);
|
|
28
|
+
return client.charge(order.total);
|
|
29
|
+
}
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
### 2. Prefer SDK-style interfaces over generic fetchers
|
|
33
|
+
|
|
34
|
+
```typescript
|
|
35
|
+
// GOOD: Each function is independently mockable
|
|
36
|
+
const api = {
|
|
37
|
+
getUser: (id) => fetch(`/users/${id}`),
|
|
38
|
+
getOrders: (userId) => fetch(`/users/${userId}/orders`),
|
|
39
|
+
createOrder: (data) => fetch('/orders', { method: 'POST', body: data }),
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
// BAD: Mocking requires conditional logic inside the mock
|
|
43
|
+
const api = {
|
|
44
|
+
fetch: (endpoint, options) => fetch(endpoint, options),
|
|
45
|
+
};
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
The SDK approach means:
|
|
49
|
+
- Each mock returns one specific shape
|
|
50
|
+
- No conditional logic in test setup
|
|
51
|
+
- Easier to see which endpoints a test exercises
|
|
52
|
+
- Type safety per endpoint
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
# Refactor Candidates
|
|
2
|
+
|
|
3
|
+
After TDD cycle, look for:
|
|
4
|
+
|
|
5
|
+
- **Duplication** — Extract function/class
|
|
6
|
+
- **Long methods** — Break into private helpers (keep tests on public interface)
|
|
7
|
+
- **Shallow modules** — Combine or deepen
|
|
8
|
+
- **Feature envy** — Move logic to where data lives
|
|
9
|
+
- **Primitive obsession** — Introduce value objects
|
|
10
|
+
- **Existing code** the new code reveals as problematic
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
# Good and Bad Tests
|
|
2
|
+
|
|
3
|
+
## Good Tests
|
|
4
|
+
|
|
5
|
+
**Integration-style**: Test through real interfaces, not mocks of internal parts.
|
|
6
|
+
|
|
7
|
+
```typescript
|
|
8
|
+
// GOOD: Tests observable behavior
|
|
9
|
+
test("user can checkout with valid cart", async () => {
|
|
10
|
+
const cart = createCart();
|
|
11
|
+
cart.add(product);
|
|
12
|
+
const result = await checkout(cart, paymentMethod);
|
|
13
|
+
expect(result.status).toBe("confirmed");
|
|
14
|
+
});
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
Characteristics:
|
|
18
|
+
- Tests behavior users/callers care about
|
|
19
|
+
- Uses public API only
|
|
20
|
+
- Survives internal refactors
|
|
21
|
+
- Describes WHAT, not HOW
|
|
22
|
+
- One logical assertion per test
|
|
23
|
+
|
|
24
|
+
## Bad Tests
|
|
25
|
+
|
|
26
|
+
**Implementation-detail tests**: Coupled to internal structure.
|
|
27
|
+
|
|
28
|
+
```typescript
|
|
29
|
+
// BAD: Tests implementation details
|
|
30
|
+
test("checkout calls paymentService.process", async () => {
|
|
31
|
+
const mockPayment = jest.mock(paymentService);
|
|
32
|
+
await checkout(cart, payment);
|
|
33
|
+
expect(mockPayment.process).toHaveBeenCalledWith(cart.total);
|
|
34
|
+
});
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
Red flags:
|
|
38
|
+
- Mocking internal collaborators
|
|
39
|
+
- Testing private methods
|
|
40
|
+
- Asserting on call counts/order
|
|
41
|
+
- Test breaks when refactoring without behavior change
|
|
42
|
+
- Test name describes HOW not WHAT
|
|
43
|
+
- Verifying through external means instead of interface
|
|
44
|
+
|
|
45
|
+
```typescript
|
|
46
|
+
// BAD: Bypasses interface to verify
|
|
47
|
+
test("createUser saves to database", async () => {
|
|
48
|
+
await createUser({ name: "Alice" });
|
|
49
|
+
const row = await db.query("SELECT * FROM users WHERE name = ?", ["Alice"]);
|
|
50
|
+
expect(row).toBeDefined();
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
// GOOD: Verifies through interface
|
|
54
|
+
test("createUser makes user retrievable", async () => {
|
|
55
|
+
const user = await createUser({ name: "Alice" });
|
|
56
|
+
const retrieved = await getUser(user.id);
|
|
57
|
+
expect(retrieved.name).toBe("Alice");
|
|
58
|
+
});
|
|
59
|
+
```
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: teams
|
|
3
|
+
description: "Launch pre-configured Agent Teams for common workflows"
|
|
4
|
+
effort: max
|
|
5
|
+
user-invocable: true
|
|
6
|
+
argument-hint: "<preset> [task-description]"
|
|
7
|
+
allowed-tools: Bash, Read, Write, Edit, Glob, Grep
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
# /teams - Agent Teams Presets
|
|
11
|
+
|
|
12
|
+
$ARGUMENTS
|
|
13
|
+
|
|
14
|
+
## What This Does
|
|
15
|
+
|
|
16
|
+
Launches a pre-configured Agent Teams composition for your task.
|
|
17
|
+
|
|
18
|
+
Requires: `CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS=1`
|
|
19
|
+
|
|
20
|
+
## Available Presets
|
|
21
|
+
|
|
22
|
+
| Preset | Agents | Use Case |
|
|
23
|
+
|--------|--------|----------|
|
|
24
|
+
| `review` | code-reviewer, security-auditor, performance-optimizer | PR code review |
|
|
25
|
+
| `debug` | debugger, backend-specialist, incident-responder | Multi-file bug investigation |
|
|
26
|
+
| `feature` | orchestrator, backend-specialist, frontend-specialist, test-engineer | Full feature implementation |
|
|
27
|
+
| `fullstack` | backend-specialist, frontend-specialist, database-architect, devops-implementer | Full-stack task |
|
|
28
|
+
| `research` | technical-researcher, data-analyst, prompt-engineer | Deep research task |
|
|
29
|
+
| `security` | security-architect, security-auditor, backend-specialist | Security audit |
|
|
30
|
+
| `migration` | database-architect, backend-specialist, devops-implementer | Database migration |
|
|
31
|
+
|
|
32
|
+
## Usage Examples
|
|
33
|
+
|
|
34
|
+
```
|
|
35
|
+
/teams review # Launch review team on current changes
|
|
36
|
+
/teams debug # Launch debug team for current issue
|
|
37
|
+
/teams feature # Launch feature team for new feature
|
|
38
|
+
/teams security # Launch security audit team
|
|
39
|
+
/teams migration # Launch migration team
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
## Preset Definitions
|
|
43
|
+
|
|
44
|
+
### review
|
|
45
|
+
- **Agents**: code-reviewer (lead), security-auditor, performance-optimizer
|
|
46
|
+
- **Ownership**: code-reviewer owns review summary; others own their domain reports
|
|
47
|
+
- **Aggregation**: consensus — flag issues found by 2+ agents as high priority
|
|
48
|
+
- **Output**: `REVIEW.md` with severity-ranked findings
|
|
49
|
+
|
|
50
|
+
### debug
|
|
51
|
+
- **Agents**: debugger (lead), backend-specialist, incident-responder
|
|
52
|
+
- **Ownership**: debugger owns root-cause analysis; others own hypothesis testing
|
|
53
|
+
- **Aggregation**: relay — debugger synthesizes findings from others
|
|
54
|
+
- **Output**: `DEBUG_REPORT.md` with root cause and fix
|
|
55
|
+
|
|
56
|
+
### feature
|
|
57
|
+
- **Agents**: orchestrator (lead), backend-specialist, frontend-specialist, test-engineer
|
|
58
|
+
- **Ownership**: orchestrator owns plan; specialists own their files; test-engineer owns tests
|
|
59
|
+
- **Aggregation**: map-reduce — orchestrator integrates all outputs
|
|
60
|
+
- **Output**: implemented feature + tests
|
|
61
|
+
|
|
62
|
+
### fullstack
|
|
63
|
+
- **Agents**: backend-specialist, frontend-specialist, database-architect, devops-implementer
|
|
64
|
+
- **Ownership**: each agent owns their layer (API, UI, DB, infra)
|
|
65
|
+
- **Aggregation**: relay — backend-specialist synthesizes integration
|
|
66
|
+
- **Output**: full stack implementation
|
|
67
|
+
|
|
68
|
+
### research
|
|
69
|
+
- **Agents**: technical-researcher (lead), data-analyst, prompt-engineer
|
|
70
|
+
- **Ownership**: technical-researcher owns synthesis; others own domain findings
|
|
71
|
+
- **Aggregation**: consensus — areas of agreement highlighted
|
|
72
|
+
- **Output**: `RESEARCH.md` with findings and recommendations
|
|
73
|
+
|
|
74
|
+
### security
|
|
75
|
+
- **Agents**: security-architect (lead), security-auditor, backend-specialist
|
|
76
|
+
- **Ownership**: security-architect owns threat model; auditor owns findings; backend owns remediation
|
|
77
|
+
- **Aggregation**: relay — security-architect integrates all
|
|
78
|
+
- **Output**: `SECURITY_AUDIT.md` with CVSS-scored findings
|
|
79
|
+
|
|
80
|
+
### migration
|
|
81
|
+
- **Agents**: database-architect (lead), backend-specialist, devops-implementer
|
|
82
|
+
- **Ownership**: database-architect owns schema; backend owns code changes; devops owns deployment
|
|
83
|
+
- **Aggregation**: relay — database-architect coordinates sequence
|
|
84
|
+
- **Output**: migration scripts + rollback plan + deployment runbook
|
|
85
|
+
|
|
86
|
+
## Steps
|
|
87
|
+
|
|
88
|
+
1. Parse `$ARGUMENTS` to extract `<preset>` and optional `[task-description]`
|
|
89
|
+
2. Validate preset is one of: review, debug, feature, fullstack, research, security, migration
|
|
90
|
+
3. Check `CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS` is set; warn if not
|
|
91
|
+
4. Display the team composition and ownership rules
|
|
92
|
+
5. Ask user to confirm before launching
|
|
93
|
+
6. Launch the appropriate agents using the Agent tool with the task description
|
|
94
|
+
7. Apply the aggregation strategy to synthesize results
|
|
95
|
+
8. Produce the defined output document
|
|
96
|
+
|
|
97
|
+
## Environment
|
|
98
|
+
|
|
99
|
+
```bash
|
|
100
|
+
export CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS=1
|
|
101
|
+
```
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: test
|
|
3
|
+
description: "Run tests with coverage analysis and reporting"
|
|
4
|
+
effort: medium
|
|
5
|
+
disable-model-invocation: true
|
|
6
|
+
argument-hint: "[file or pattern]"
|
|
7
|
+
allowed-tools: Bash, Read, Grep
|
|
8
|
+
hooks:
|
|
9
|
+
PostToolUse:
|
|
10
|
+
- matcher: "Bash"
|
|
11
|
+
hooks:
|
|
12
|
+
- type: command
|
|
13
|
+
command: "echo 'Reminder: check test coverage meets threshold (>70%)'"
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+
# Test Runner
|
|
17
|
+
|
|
18
|
+
$ARGUMENTS
|
|
19
|
+
|
|
20
|
+
Run tests based on detected project type.
|
|
21
|
+
|
|
22
|
+
## Project context
|
|
23
|
+
|
|
24
|
+
- Project config: !`cat package.json 2>/dev/null || cat pyproject.toml 2>/dev/null || cat pubspec.yaml 2>/dev/null || echo "unknown"`
|
|
25
|
+
|
|
26
|
+
## Auto-Detection
|
|
27
|
+
|
|
28
|
+
Run the bundled script to detect test framework:
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
python3 ${CLAUDE_SKILL_DIR}/scripts/detect-runner.py .
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
| File Found | Runner | Command |
|
|
35
|
+
|------------|--------|---------|
|
|
36
|
+
| `pyproject.toml` / `setup.py` | pytest | `pytest --cov=src --cov-report=term-missing tests/` |
|
|
37
|
+
| `package.json` (vitest) | vitest | `npx vitest run --coverage` |
|
|
38
|
+
| `package.json` (jest) | jest | `npx jest --coverage` |
|
|
39
|
+
| `pubspec.yaml` | flutter test | `flutter test --coverage` |
|
|
40
|
+
| `go.mod` | go test | `go test -cover ./...` |
|
|
41
|
+
| `Cargo.toml` | cargo test | `cargo test` |
|
|
42
|
+
| `composer.json` | phpunit | `./vendor/bin/phpunit --coverage-text` |
|
|
43
|
+
|
|
44
|
+
## Usage
|
|
45
|
+
|
|
46
|
+
```
|
|
47
|
+
/test # Run all tests
|
|
48
|
+
/test path/to/test_file # Run specific test file
|
|
49
|
+
/test -k "test_name" # Run tests matching pattern
|
|
50
|
+
/test --coverage # Run with coverage report
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
## Common Options by Runner
|
|
54
|
+
|
|
55
|
+
### Python (pytest)
|
|
56
|
+
```bash
|
|
57
|
+
pytest tests/ # All tests
|
|
58
|
+
pytest tests/unit/test_example.py # Specific file
|
|
59
|
+
pytest -k "test_search" # Pattern match
|
|
60
|
+
pytest --lf # Last failed only
|
|
61
|
+
pytest -v # Verbose
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
### JavaScript/TypeScript (vitest/jest)
|
|
65
|
+
```bash
|
|
66
|
+
npx vitest run # All tests
|
|
67
|
+
npx vitest run src/utils.test.ts # Specific file
|
|
68
|
+
npx vitest run --reporter=verbose # Verbose
|
|
69
|
+
npx jest --testPathPattern=utils # Pattern match
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
### PHP (phpunit)
|
|
73
|
+
```bash
|
|
74
|
+
./vendor/bin/phpunit # All tests
|
|
75
|
+
./vendor/bin/phpunit tests/Unit/ExampleTest.php # Specific
|
|
76
|
+
./vendor/bin/phpunit --filter testName # Pattern match
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
### Flutter/Dart
|
|
80
|
+
```bash
|
|
81
|
+
flutter test # All tests
|
|
82
|
+
flutter test test/widget_test.dart # Specific file
|
|
83
|
+
dart test --name="pattern" # Pattern match
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
### Go
|
|
87
|
+
```bash
|
|
88
|
+
go test ./... # All tests
|
|
89
|
+
go test ./pkg/utils/ # Specific package
|
|
90
|
+
go test -run TestName ./... # Pattern match
|
|
91
|
+
go test -v ./... # Verbose
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
## Coverage Targets
|
|
95
|
+
|
|
96
|
+
- Overall: >70%
|
|
97
|
+
- Core modules: >80%
|
|
98
|
+
- New code: 100% (for PRs)
|
|
99
|
+
|
|
100
|
+
## Test Structure Convention
|
|
101
|
+
|
|
102
|
+
```
|
|
103
|
+
tests/ # or test/, spec/, __tests__/
|
|
104
|
+
├── unit/ # Fast, isolated tests
|
|
105
|
+
├── integration/ # Tests with external dependencies
|
|
106
|
+
└── e2e/ # End-to-end tests
|
|
107
|
+
```
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""Auto-detect test framework and runner from project configuration files.
|
|
3
|
+
|
|
4
|
+
Scans a project directory for well-known config files (pyproject.toml,
|
|
5
|
+
package.json, pubspec.yaml, go.mod, Cargo.toml, composer.json) and
|
|
6
|
+
returns a JSON object describing the detected test runner, suggested
|
|
7
|
+
command, test directories, estimated test-file count, and whether
|
|
8
|
+
coverage reporting is configured.
|
|
9
|
+
|
|
10
|
+
Usage::
|
|
11
|
+
|
|
12
|
+
python3 detect-runner.py [project_directory]
|
|
13
|
+
"""
|
|
14
|
+
from __future__ import annotations
|
|
15
|
+
|
|
16
|
+
import sys
|
|
17
|
+
from pathlib import Path
|
|
18
|
+
from typing import Any
|
|
19
|
+
|
|
20
|
+
sys.path.insert(0, str(Path(__file__).resolve().parent.parent.parent))
|
|
21
|
+
from _lib.detect_utils import count_files, read_json, read_text, run_detector
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def detect(project_dir: Path) -> dict[str, Any]:
|
|
25
|
+
"""Detect the test runner for the given project directory."""
|
|
26
|
+
result: dict[str, Any] = {
|
|
27
|
+
"runner": None, "command": None, "test_dirs": [],
|
|
28
|
+
"test_count_estimate": 0, "coverage_enabled": False,
|
|
29
|
+
"detected_from": None
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
# Python: pyproject.toml / setup.py
|
|
33
|
+
pyproject = read_text(project_dir / "pyproject.toml")
|
|
34
|
+
if pyproject or (project_dir / "setup.py").exists():
|
|
35
|
+
result["runner"] = "pytest"
|
|
36
|
+
result["command"] = "pytest --cov=src --cov-report=term-missing tests/"
|
|
37
|
+
result["detected_from"] = "pyproject.toml" if pyproject else "setup.py"
|
|
38
|
+
if pyproject and "pytest" in pyproject:
|
|
39
|
+
result["coverage_enabled"] = "cov" in pyproject
|
|
40
|
+
for d in ["tests", "test"]:
|
|
41
|
+
if (project_dir / d).is_dir():
|
|
42
|
+
result["test_dirs"].append(d)
|
|
43
|
+
result["test_count_estimate"] = count_files(project_dir, [r'test_.*\.py$', r'.*_test\.py$'])
|
|
44
|
+
return result
|
|
45
|
+
|
|
46
|
+
# Node.js: package.json
|
|
47
|
+
pkg = read_json(project_dir / "package.json")
|
|
48
|
+
if pkg:
|
|
49
|
+
dev_deps = {**pkg.get("devDependencies", {}), **pkg.get("dependencies", {})}
|
|
50
|
+
scripts = pkg.get("scripts", {})
|
|
51
|
+
test_cmd = scripts.get("test", "")
|
|
52
|
+
|
|
53
|
+
if "vitest" in dev_deps or "vitest" in test_cmd:
|
|
54
|
+
result["runner"] = "vitest"
|
|
55
|
+
result["command"] = "npx vitest run --coverage"
|
|
56
|
+
elif "jest" in dev_deps or "jest" in test_cmd:
|
|
57
|
+
result["runner"] = "jest"
|
|
58
|
+
result["command"] = "npx jest --coverage"
|
|
59
|
+
elif "mocha" in dev_deps or "mocha" in test_cmd:
|
|
60
|
+
result["runner"] = "mocha"
|
|
61
|
+
result["command"] = "npx mocha"
|
|
62
|
+
else:
|
|
63
|
+
result["runner"] = "npm-test"
|
|
64
|
+
result["command"] = "npm test"
|
|
65
|
+
|
|
66
|
+
result["detected_from"] = "package.json"
|
|
67
|
+
result["coverage_enabled"] = "coverage" in test_cmd or "c8" in dev_deps or "istanbul" in str(dev_deps)
|
|
68
|
+
for d in ["__tests__", "test", "tests", "spec"]:
|
|
69
|
+
if (project_dir / d).is_dir():
|
|
70
|
+
result["test_dirs"].append(d)
|
|
71
|
+
result["test_count_estimate"] = count_files(project_dir, [r'\.test\.[jt]sx?$', r'\.spec\.[jt]sx?$', r'test_.*\.[jt]s$'])
|
|
72
|
+
return result
|
|
73
|
+
|
|
74
|
+
# Flutter/Dart
|
|
75
|
+
if (project_dir / "pubspec.yaml").exists():
|
|
76
|
+
result.update(runner="flutter", command="flutter test --coverage",
|
|
77
|
+
detected_from="pubspec.yaml", coverage_enabled=True)
|
|
78
|
+
if (project_dir / "test").is_dir():
|
|
79
|
+
result["test_dirs"].append("test")
|
|
80
|
+
result["test_count_estimate"] = count_files(project_dir, [r'_test\.dart$'])
|
|
81
|
+
return result
|
|
82
|
+
|
|
83
|
+
# Go
|
|
84
|
+
if (project_dir / "go.mod").exists():
|
|
85
|
+
result.update(runner="go", command="go test -cover ./...",
|
|
86
|
+
detected_from="go.mod", coverage_enabled=True)
|
|
87
|
+
result["test_count_estimate"] = count_files(project_dir, [r'_test\.go$'])
|
|
88
|
+
return result
|
|
89
|
+
|
|
90
|
+
# Rust
|
|
91
|
+
if (project_dir / "Cargo.toml").exists():
|
|
92
|
+
result.update(runner="cargo", command="cargo test", detected_from="Cargo.toml")
|
|
93
|
+
result["test_count_estimate"] = count_files(project_dir, [r'\.rs$'])
|
|
94
|
+
return result
|
|
95
|
+
|
|
96
|
+
# PHP
|
|
97
|
+
if (project_dir / "composer.json").exists():
|
|
98
|
+
result.update(runner="phpunit", command="./vendor/bin/phpunit --coverage-text",
|
|
99
|
+
detected_from="composer.json")
|
|
100
|
+
for d in ["tests", "test"]:
|
|
101
|
+
if (project_dir / d).is_dir():
|
|
102
|
+
result["test_dirs"].append(d)
|
|
103
|
+
result["test_count_estimate"] = count_files(project_dir, [r'Test\.php$', r'test_.*\.php$'])
|
|
104
|
+
return result
|
|
105
|
+
|
|
106
|
+
result["runner"] = "unknown"
|
|
107
|
+
result["command"] = None
|
|
108
|
+
result["detected_from"] = None
|
|
109
|
+
return result
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
if __name__ == "__main__":
|
|
113
|
+
run_detector(detect)
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: testing-patterns
|
|
3
|
+
description: "Loaded when user asks about testing strategy, fixtures, or mocking"
|
|
4
|
+
effort: medium
|
|
5
|
+
user-invocable: false
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# Testing Patterns Skill
|
|
9
|
+
|
|
10
|
+
## Test Structure (AAA Pattern)
|
|
11
|
+
|
|
12
|
+
```python
|
|
13
|
+
def test_function_does_expected_thing():
|
|
14
|
+
"""Test description explaining what and why."""
|
|
15
|
+
# Arrange - Set up test data and preconditions
|
|
16
|
+
input_data = {"key": "value"}
|
|
17
|
+
expected = "result"
|
|
18
|
+
|
|
19
|
+
# Act - Execute the code under test
|
|
20
|
+
result = function_under_test(input_data)
|
|
21
|
+
|
|
22
|
+
# Assert - Verify the outcome
|
|
23
|
+
assert result == expected
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
---
|
|
27
|
+
|
|
28
|
+
## Test Organization
|
|
29
|
+
|
|
30
|
+
```
|
|
31
|
+
tests/
|
|
32
|
+
├── conftest.py # Shared fixtures
|
|
33
|
+
├── unit/ # Unit tests (isolated)
|
|
34
|
+
│ ├── test_search_core.py
|
|
35
|
+
│ └── test_utils.py
|
|
36
|
+
├── integration/ # Integration tests
|
|
37
|
+
│ └── test_api.py
|
|
38
|
+
└── e2e/ # End-to-end tests
|
|
39
|
+
└── test_workflow.py
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
---
|
|
43
|
+
|
|
44
|
+
## Quality Targets
|
|
45
|
+
|
|
46
|
+
| Metric | Target |
|
|
47
|
+
|--------|--------|
|
|
48
|
+
| Coverage | >70% overall |
|
|
49
|
+
| New code | 100% |
|
|
50
|
+
| Core modules | >80% |
|
|
51
|
+
| No flaky tests | 0 |
|
|
52
|
+
|
|
53
|
+
---
|
|
54
|
+
|
|
55
|
+
## Language-Specific References
|
|
56
|
+
|
|
57
|
+
| Language | Reference | Key Topics |
|
|
58
|
+
|----------|-----------|------------|
|
|
59
|
+
| Python | [reference/python-pytest.md](reference/python-pytest.md) | Fixtures, mocking, parametrize, markers, conftest, running tests |
|
|
60
|
+
| TypeScript | [reference/typescript-vitest.md](reference/typescript-vitest.md) | Vitest/Jest, React Testing Library, mocking, running tests |
|
|
61
|
+
| PHP | [reference/php-phpunit.md](reference/php-phpunit.md) | PHPUnit test cases, mocking, running tests |
|
|
62
|
+
| Go | [reference/go-testing.md](reference/go-testing.md) | Table-driven tests, testify mocking, running tests |
|
|
63
|
+
| Flutter/Dart | [reference/flutter-testing.md](reference/flutter-testing.md) | Widget tests, unit tests, running tests |
|
|
64
|
+
|
|
65
|
+
For Python pytest patterns, see [reference/python-pytest.md](reference/python-pytest.md).
|
|
66
|
+
|
|
67
|
+
For TypeScript Vitest/Jest patterns, see [reference/typescript-vitest.md](reference/typescript-vitest.md).
|
|
68
|
+
|
|
69
|
+
For PHP PHPUnit patterns, see [reference/php-phpunit.md](reference/php-phpunit.md).
|
|
70
|
+
|
|
71
|
+
For Go testing patterns, see [reference/go-testing.md](reference/go-testing.md).
|
|
72
|
+
|
|
73
|
+
For Flutter/Dart testing patterns, see [reference/flutter-testing.md](reference/flutter-testing.md).
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# Flutter/Dart Testing Patterns
|
|
2
|
+
|
|
3
|
+
## Widget Test
|
|
4
|
+
|
|
5
|
+
```dart
|
|
6
|
+
testWidgets('Counter increments', (WidgetTester tester) async {
|
|
7
|
+
await tester.pumpWidget(const MyApp());
|
|
8
|
+
expect(find.text('0'), findsOneWidget);
|
|
9
|
+
await tester.tap(find.byIcon(Icons.add));
|
|
10
|
+
await tester.pump();
|
|
11
|
+
expect(find.text('1'), findsOneWidget);
|
|
12
|
+
});
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
## Unit Test
|
|
16
|
+
|
|
17
|
+
```dart
|
|
18
|
+
test('User model parses JSON', () {
|
|
19
|
+
final json = {'name': 'Test', 'email': 'test@test.com'};
|
|
20
|
+
final user = User.fromJson(json);
|
|
21
|
+
expect(user.name, equals('Test'));
|
|
22
|
+
expect(user.email, equals('test@test.com'));
|
|
23
|
+
});
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
## Running
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
flutter test # All tests
|
|
30
|
+
flutter test --coverage # With coverage
|
|
31
|
+
flutter test test/widget_test.dart # Specific file
|
|
32
|
+
dart test --name="pattern" # Pattern match
|
|
33
|
+
```
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
# Go Testing Patterns
|
|
2
|
+
|
|
3
|
+
## Table-Driven Tests
|
|
4
|
+
|
|
5
|
+
```go
|
|
6
|
+
func TestAdd(t *testing.T) {
|
|
7
|
+
tests := []struct {
|
|
8
|
+
name string
|
|
9
|
+
a, b int
|
|
10
|
+
expected int
|
|
11
|
+
}{
|
|
12
|
+
{"positive", 1, 2, 3},
|
|
13
|
+
{"negative", -1, -2, -3},
|
|
14
|
+
{"zero", 0, 0, 0},
|
|
15
|
+
}
|
|
16
|
+
for _, tt := range tests {
|
|
17
|
+
t.Run(tt.name, func(t *testing.T) {
|
|
18
|
+
result := Add(tt.a, tt.b)
|
|
19
|
+
if result != tt.expected {
|
|
20
|
+
t.Errorf("Add(%d, %d) = %d, want %d", tt.a, tt.b, result, tt.expected)
|
|
21
|
+
}
|
|
22
|
+
})
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
## Mocking (testify)
|
|
28
|
+
|
|
29
|
+
```go
|
|
30
|
+
type MockRepo struct { mock.Mock }
|
|
31
|
+
func (m *MockRepo) Find(id string) (*User, error) {
|
|
32
|
+
args := m.Called(id)
|
|
33
|
+
return args.Get(0).(*User), args.Error(1)
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
func TestService(t *testing.T) {
|
|
37
|
+
repo := new(MockRepo)
|
|
38
|
+
repo.On("Find", "1").Return(&User{Name: "Test"}, nil)
|
|
39
|
+
svc := NewService(repo)
|
|
40
|
+
user, _ := svc.GetUser("1")
|
|
41
|
+
assert.Equal(t, "Test", user.Name)
|
|
42
|
+
}
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
## Running
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
go test ./... # All tests
|
|
49
|
+
go test -cover ./... # With coverage
|
|
50
|
+
go test -run TestAdd ./pkg/ # Specific test
|
|
51
|
+
go test -v ./... # Verbose
|
|
52
|
+
```
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# PHP PHPUnit Patterns
|
|
2
|
+
|
|
3
|
+
## Basic Test
|
|
4
|
+
|
|
5
|
+
```php
|
|
6
|
+
class UserServiceTest extends TestCase
|
|
7
|
+
{
|
|
8
|
+
public function test_creates_user_with_valid_data(): void
|
|
9
|
+
{
|
|
10
|
+
$service = new UserService();
|
|
11
|
+
$user = $service->create(['name' => 'Test', 'email' => 't@t.com']);
|
|
12
|
+
$this->assertEquals('Test', $user->name);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
public function test_throws_on_invalid_email(): void
|
|
16
|
+
{
|
|
17
|
+
$this->expectException(ValidationException::class);
|
|
18
|
+
$service = new UserService();
|
|
19
|
+
$service->create(['name' => 'Test', 'email' => 'invalid']);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
## Mocking
|
|
25
|
+
|
|
26
|
+
```php
|
|
27
|
+
$mock = $this->createMock(Repository::class);
|
|
28
|
+
$mock->method('find')->willReturn(new User('Test'));
|
|
29
|
+
$service = new UserService($mock);
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
## Running
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
./vendor/bin/phpunit # All tests
|
|
36
|
+
./vendor/bin/phpunit --coverage-text # With coverage
|
|
37
|
+
./vendor/bin/phpunit tests/Unit/UserTest.php # Specific file
|
|
38
|
+
./vendor/bin/phpunit --filter testName # Pattern match
|
|
39
|
+
```
|