moai-adk 0.35.1__py3-none-any.whl
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.
Potentially problematic release.
This version of moai-adk might be problematic. Click here for more details.
- moai_adk/__init__.py +10 -0
- moai_adk/__main__.py +199 -0
- moai_adk/cli/__init__.py +6 -0
- moai_adk/cli/commands/__init__.py +17 -0
- moai_adk/cli/commands/analyze.py +116 -0
- moai_adk/cli/commands/doctor.py +272 -0
- moai_adk/cli/commands/init.py +372 -0
- moai_adk/cli/commands/language.py +248 -0
- moai_adk/cli/commands/status.py +104 -0
- moai_adk/cli/commands/update.py +2686 -0
- moai_adk/cli/main.py +13 -0
- moai_adk/cli/prompts/__init__.py +5 -0
- moai_adk/cli/prompts/init_prompts.py +219 -0
- moai_adk/cli/spec_status.py +263 -0
- moai_adk/cli/ui/__init__.py +44 -0
- moai_adk/cli/ui/progress.py +422 -0
- moai_adk/cli/ui/prompts.py +389 -0
- moai_adk/cli/ui/theme.py +129 -0
- moai_adk/cli/worktree/__init__.py +27 -0
- moai_adk/cli/worktree/__main__.py +31 -0
- moai_adk/cli/worktree/cli.py +683 -0
- moai_adk/cli/worktree/exceptions.py +89 -0
- moai_adk/cli/worktree/manager.py +493 -0
- moai_adk/cli/worktree/models.py +65 -0
- moai_adk/cli/worktree/registry.py +422 -0
- moai_adk/core/PHASE2_OPTIMIZATIONS.md +467 -0
- moai_adk/core/__init__.py +1 -0
- moai_adk/core/analysis/__init__.py +9 -0
- moai_adk/core/analysis/session_analyzer.py +400 -0
- moai_adk/core/claude_integration.py +393 -0
- moai_adk/core/command_helpers.py +270 -0
- moai_adk/core/comprehensive_monitoring_system.py +1183 -0
- moai_adk/core/config/__init__.py +19 -0
- moai_adk/core/config/auto_spec_config.py +340 -0
- moai_adk/core/config/migration.py +244 -0
- moai_adk/core/config/unified.py +436 -0
- moai_adk/core/context_manager.py +273 -0
- moai_adk/core/diagnostics/__init__.py +19 -0
- moai_adk/core/diagnostics/slash_commands.py +159 -0
- moai_adk/core/enterprise_features.py +1404 -0
- moai_adk/core/error_recovery_system.py +1902 -0
- moai_adk/core/event_driven_hook_system.py +1371 -0
- moai_adk/core/git/__init__.py +31 -0
- moai_adk/core/git/branch.py +25 -0
- moai_adk/core/git/branch_manager.py +129 -0
- moai_adk/core/git/checkpoint.py +134 -0
- moai_adk/core/git/commit.py +67 -0
- moai_adk/core/git/conflict_detector.py +413 -0
- moai_adk/core/git/event_detector.py +79 -0
- moai_adk/core/git/manager.py +216 -0
- moai_adk/core/hooks/post_tool_auto_spec_completion.py +901 -0
- moai_adk/core/input_validation_middleware.py +1006 -0
- moai_adk/core/integration/__init__.py +22 -0
- moai_adk/core/integration/engine.py +157 -0
- moai_adk/core/integration/integration_tester.py +226 -0
- moai_adk/core/integration/models.py +88 -0
- moai_adk/core/integration/utils.py +211 -0
- moai_adk/core/issue_creator.py +305 -0
- moai_adk/core/jit_context_loader.py +956 -0
- moai_adk/core/jit_enhanced_hook_manager.py +1987 -0
- moai_adk/core/language_config.py +202 -0
- moai_adk/core/language_config_resolver.py +572 -0
- moai_adk/core/language_validator.py +543 -0
- moai_adk/core/mcp/setup.py +116 -0
- moai_adk/core/merge/__init__.py +9 -0
- moai_adk/core/merge/analyzer.py +605 -0
- moai_adk/core/migration/__init__.py +18 -0
- moai_adk/core/migration/alfred_to_moai_migrator.py +383 -0
- moai_adk/core/migration/backup_manager.py +277 -0
- moai_adk/core/migration/custom_element_scanner.py +358 -0
- moai_adk/core/migration/file_migrator.py +209 -0
- moai_adk/core/migration/interactive_checkbox_ui.py +488 -0
- moai_adk/core/migration/selective_restorer.py +470 -0
- moai_adk/core/migration/template_utils.py +74 -0
- moai_adk/core/migration/user_selection_ui.py +338 -0
- moai_adk/core/migration/version_detector.py +139 -0
- moai_adk/core/migration/version_migrator.py +228 -0
- moai_adk/core/performance/__init__.py +6 -0
- moai_adk/core/performance/cache_system.py +316 -0
- moai_adk/core/performance/parallel_processor.py +116 -0
- moai_adk/core/phase_optimized_hook_scheduler.py +879 -0
- moai_adk/core/project/__init__.py +1 -0
- moai_adk/core/project/backup_utils.py +70 -0
- moai_adk/core/project/checker.py +300 -0
- moai_adk/core/project/detector.py +293 -0
- moai_adk/core/project/initializer.py +387 -0
- moai_adk/core/project/phase_executor.py +716 -0
- moai_adk/core/project/validator.py +139 -0
- moai_adk/core/quality/__init__.py +6 -0
- moai_adk/core/quality/trust_checker.py +377 -0
- moai_adk/core/quality/validators/__init__.py +6 -0
- moai_adk/core/quality/validators/base_validator.py +19 -0
- moai_adk/core/realtime_monitoring_dashboard.py +1724 -0
- moai_adk/core/robust_json_parser.py +611 -0
- moai_adk/core/rollback_manager.py +918 -0
- moai_adk/core/session_manager.py +651 -0
- moai_adk/core/skill_loading_system.py +579 -0
- moai_adk/core/spec/confidence_scoring.py +680 -0
- moai_adk/core/spec/ears_template_engine.py +1247 -0
- moai_adk/core/spec/quality_validator.py +687 -0
- moai_adk/core/spec_status_manager.py +478 -0
- moai_adk/core/template/__init__.py +7 -0
- moai_adk/core/template/backup.py +174 -0
- moai_adk/core/template/config.py +191 -0
- moai_adk/core/template/languages.py +43 -0
- moai_adk/core/template/merger.py +233 -0
- moai_adk/core/template/processor.py +1200 -0
- moai_adk/core/template_engine.py +310 -0
- moai_adk/core/template_variable_synchronizer.py +417 -0
- moai_adk/core/unified_permission_manager.py +745 -0
- moai_adk/core/user_behavior_analytics.py +851 -0
- moai_adk/core/version_sync.py +429 -0
- moai_adk/foundation/__init__.py +56 -0
- moai_adk/foundation/backend.py +1027 -0
- moai_adk/foundation/database.py +1115 -0
- moai_adk/foundation/devops.py +1585 -0
- moai_adk/foundation/ears.py +431 -0
- moai_adk/foundation/frontend.py +870 -0
- moai_adk/foundation/git/commit_templates.py +557 -0
- moai_adk/foundation/git.py +376 -0
- moai_adk/foundation/langs.py +484 -0
- moai_adk/foundation/ml_ops.py +1162 -0
- moai_adk/foundation/testing.py +1524 -0
- moai_adk/foundation/trust/trust_principles.py +676 -0
- moai_adk/foundation/trust/validation_checklist.py +1573 -0
- moai_adk/project/__init__.py +0 -0
- moai_adk/project/configuration.py +1084 -0
- moai_adk/project/documentation.py +566 -0
- moai_adk/project/schema.py +447 -0
- moai_adk/statusline/__init__.py +38 -0
- moai_adk/statusline/alfred_detector.py +105 -0
- moai_adk/statusline/config.py +376 -0
- moai_adk/statusline/enhanced_output_style_detector.py +372 -0
- moai_adk/statusline/git_collector.py +190 -0
- moai_adk/statusline/main.py +322 -0
- moai_adk/statusline/metrics_tracker.py +78 -0
- moai_adk/statusline/renderer.py +343 -0
- moai_adk/statusline/update_checker.py +129 -0
- moai_adk/statusline/version_reader.py +741 -0
- moai_adk/templates/.claude/agents/moai/ai-nano-banana.md +714 -0
- moai_adk/templates/.claude/agents/moai/builder-agent.md +474 -0
- moai_adk/templates/.claude/agents/moai/builder-command.md +1172 -0
- moai_adk/templates/.claude/agents/moai/builder-plugin.md +637 -0
- moai_adk/templates/.claude/agents/moai/builder-skill.md +666 -0
- moai_adk/templates/.claude/agents/moai/expert-backend.md +899 -0
- moai_adk/templates/.claude/agents/moai/expert-database.md +777 -0
- moai_adk/templates/.claude/agents/moai/expert-debug.md +401 -0
- moai_adk/templates/.claude/agents/moai/expert-devops.md +720 -0
- moai_adk/templates/.claude/agents/moai/expert-frontend.md +734 -0
- moai_adk/templates/.claude/agents/moai/expert-performance.md +657 -0
- moai_adk/templates/.claude/agents/moai/expert-security.md +513 -0
- moai_adk/templates/.claude/agents/moai/expert-testing.md +733 -0
- moai_adk/templates/.claude/agents/moai/expert-uiux.md +1041 -0
- moai_adk/templates/.claude/agents/moai/manager-claude-code.md +432 -0
- moai_adk/templates/.claude/agents/moai/manager-docs.md +573 -0
- moai_adk/templates/.claude/agents/moai/manager-git.md +1060 -0
- moai_adk/templates/.claude/agents/moai/manager-project.md +891 -0
- moai_adk/templates/.claude/agents/moai/manager-quality.md +624 -0
- moai_adk/templates/.claude/agents/moai/manager-spec.md +809 -0
- moai_adk/templates/.claude/agents/moai/manager-strategy.md +780 -0
- moai_adk/templates/.claude/agents/moai/manager-tdd.md +784 -0
- moai_adk/templates/.claude/agents/moai/mcp-context7.md +458 -0
- moai_adk/templates/.claude/agents/moai/mcp-figma.md +1607 -0
- moai_adk/templates/.claude/agents/moai/mcp-notion.md +789 -0
- moai_adk/templates/.claude/agents/moai/mcp-playwright.md +469 -0
- moai_adk/templates/.claude/agents/moai/mcp-sequential-thinking.md +1032 -0
- moai_adk/templates/.claude/commands/moai/0-project.md +1386 -0
- moai_adk/templates/.claude/commands/moai/1-plan.md +1427 -0
- moai_adk/templates/.claude/commands/moai/2-run.md +943 -0
- moai_adk/templates/.claude/commands/moai/3-sync.md +1324 -0
- moai_adk/templates/.claude/commands/moai/9-feedback.md +314 -0
- moai_adk/templates/.claude/hooks/__init__.py +8 -0
- moai_adk/templates/.claude/hooks/moai/__init__.py +8 -0
- moai_adk/templates/.claude/hooks/moai/lib/__init__.py +85 -0
- moai_adk/templates/.claude/hooks/moai/lib/checkpoint.py +244 -0
- moai_adk/templates/.claude/hooks/moai/lib/common.py +131 -0
- moai_adk/templates/.claude/hooks/moai/lib/config_manager.py +446 -0
- moai_adk/templates/.claude/hooks/moai/lib/config_validator.py +639 -0
- moai_adk/templates/.claude/hooks/moai/lib/example_config.json +104 -0
- moai_adk/templates/.claude/hooks/moai/lib/git_operations_manager.py +590 -0
- moai_adk/templates/.claude/hooks/moai/lib/language_validator.py +317 -0
- moai_adk/templates/.claude/hooks/moai/lib/models.py +102 -0
- moai_adk/templates/.claude/hooks/moai/lib/path_utils.py +28 -0
- moai_adk/templates/.claude/hooks/moai/lib/project.py +768 -0
- moai_adk/templates/.claude/hooks/moai/lib/test_hooks_improvements.py +443 -0
- moai_adk/templates/.claude/hooks/moai/lib/timeout.py +160 -0
- moai_adk/templates/.claude/hooks/moai/lib/unified_timeout_manager.py +530 -0
- moai_adk/templates/.claude/hooks/moai/session_end__auto_cleanup.py +862 -0
- moai_adk/templates/.claude/hooks/moai/session_start__show_project_info.py +1083 -0
- moai_adk/templates/.claude/output-styles/moai/r2d2.md +560 -0
- moai_adk/templates/.claude/output-styles/moai/yoda.md +359 -0
- moai_adk/templates/.claude/settings.json +172 -0
- moai_adk/templates/.claude/skills/moai-ai-nano-banana/SKILL.md +307 -0
- moai_adk/templates/.claude/skills/moai-ai-nano-banana/examples.md +431 -0
- moai_adk/templates/.claude/skills/moai-ai-nano-banana/scripts/batch_generate.py +560 -0
- moai_adk/templates/.claude/skills/moai-ai-nano-banana/scripts/generate_image.py +362 -0
- moai_adk/templates/.claude/skills/moai-docs-generation/SKILL.md +249 -0
- moai_adk/templates/.claude/skills/moai-docs-generation/examples.md +406 -0
- moai_adk/templates/.claude/skills/moai-docs-generation/modules/README.md +44 -0
- moai_adk/templates/.claude/skills/moai-docs-generation/modules/api-documentation.md +130 -0
- moai_adk/templates/.claude/skills/moai-docs-generation/modules/code-documentation.md +152 -0
- moai_adk/templates/.claude/skills/moai-docs-generation/modules/multi-format-output.md +178 -0
- moai_adk/templates/.claude/skills/moai-docs-generation/modules/user-guides.md +147 -0
- moai_adk/templates/.claude/skills/moai-docs-generation/reference.md +328 -0
- moai_adk/templates/.claude/skills/moai-domain-backend/SKILL.md +320 -0
- moai_adk/templates/.claude/skills/moai-domain-backend/examples.md +718 -0
- moai_adk/templates/.claude/skills/moai-domain-backend/reference.md +464 -0
- moai_adk/templates/.claude/skills/moai-domain-database/SKILL.md +323 -0
- moai_adk/templates/.claude/skills/moai-domain-database/examples.md +830 -0
- moai_adk/templates/.claude/skills/moai-domain-database/modules/README.md +53 -0
- moai_adk/templates/.claude/skills/moai-domain-database/modules/mongodb.md +231 -0
- moai_adk/templates/.claude/skills/moai-domain-database/modules/postgresql.md +169 -0
- moai_adk/templates/.claude/skills/moai-domain-database/modules/redis.md +262 -0
- moai_adk/templates/.claude/skills/moai-domain-database/reference.md +545 -0
- moai_adk/templates/.claude/skills/moai-domain-frontend/SKILL.md +497 -0
- moai_adk/templates/.claude/skills/moai-domain-frontend/examples.md +968 -0
- moai_adk/templates/.claude/skills/moai-domain-frontend/reference.md +664 -0
- moai_adk/templates/.claude/skills/moai-domain-uiux/SKILL.md +455 -0
- moai_adk/templates/.claude/skills/moai-domain-uiux/examples.md +560 -0
- moai_adk/templates/.claude/skills/moai-domain-uiux/modules/accessibility-wcag.md +260 -0
- moai_adk/templates/.claude/skills/moai-domain-uiux/modules/component-architecture.md +228 -0
- moai_adk/templates/.claude/skills/moai-domain-uiux/modules/icon-libraries.md +401 -0
- moai_adk/templates/.claude/skills/moai-domain-uiux/modules/theming-system.md +373 -0
- moai_adk/templates/.claude/skills/moai-domain-uiux/reference.md +243 -0
- moai_adk/templates/.claude/skills/moai-formats-data/SKILL.md +492 -0
- moai_adk/templates/.claude/skills/moai-formats-data/examples.md +804 -0
- moai_adk/templates/.claude/skills/moai-formats-data/modules/README.md +98 -0
- moai_adk/templates/.claude/skills/moai-formats-data/modules/SKILL-MODULARIZATION-TEMPLATE.md +278 -0
- moai_adk/templates/.claude/skills/moai-formats-data/modules/caching-performance.md +459 -0
- moai_adk/templates/.claude/skills/moai-formats-data/modules/data-validation.md +485 -0
- moai_adk/templates/.claude/skills/moai-formats-data/modules/json-optimization.md +374 -0
- moai_adk/templates/.claude/skills/moai-formats-data/modules/toon-encoding.md +308 -0
- moai_adk/templates/.claude/skills/moai-formats-data/reference.md +585 -0
- moai_adk/templates/.claude/skills/moai-foundation-claude/SKILL.md +202 -0
- moai_adk/templates/.claude/skills/moai-foundation-claude/examples.md +732 -0
- moai_adk/templates/.claude/skills/moai-foundation-claude/reference/best-practices-checklist.md +616 -0
- moai_adk/templates/.claude/skills/moai-foundation-claude/reference/claude-code-custom-slash-commands-official.md +729 -0
- moai_adk/templates/.claude/skills/moai-foundation-claude/reference/claude-code-hooks-official.md +560 -0
- moai_adk/templates/.claude/skills/moai-foundation-claude/reference/claude-code-iam-official.md +635 -0
- moai_adk/templates/.claude/skills/moai-foundation-claude/reference/claude-code-memory-official.md +543 -0
- moai_adk/templates/.claude/skills/moai-foundation-claude/reference/claude-code-settings-official.md +663 -0
- moai_adk/templates/.claude/skills/moai-foundation-claude/reference/claude-code-skills-official.md +113 -0
- moai_adk/templates/.claude/skills/moai-foundation-claude/reference/claude-code-sub-agents-official.md +238 -0
- moai_adk/templates/.claude/skills/moai-foundation-claude/reference/complete-configuration-guide.md +175 -0
- moai_adk/templates/.claude/skills/moai-foundation-claude/reference/skill-examples.md +1674 -0
- moai_adk/templates/.claude/skills/moai-foundation-claude/reference/skill-formatting-guide.md +729 -0
- moai_adk/templates/.claude/skills/moai-foundation-claude/reference/sub-agents/sub-agent-examples.md +1513 -0
- moai_adk/templates/.claude/skills/moai-foundation-claude/reference/sub-agents/sub-agent-formatting-guide.md +1086 -0
- moai_adk/templates/.claude/skills/moai-foundation-claude/reference/sub-agents/sub-agent-integration-patterns.md +1100 -0
- moai_adk/templates/.claude/skills/moai-foundation-claude/reference.md +209 -0
- moai_adk/templates/.claude/skills/moai-foundation-context/SKILL.md +441 -0
- moai_adk/templates/.claude/skills/moai-foundation-context/examples.md +1048 -0
- moai_adk/templates/.claude/skills/moai-foundation-context/reference.md +246 -0
- moai_adk/templates/.claude/skills/moai-foundation-core/SKILL.md +420 -0
- moai_adk/templates/.claude/skills/moai-foundation-core/examples.md +358 -0
- moai_adk/templates/.claude/skills/moai-foundation-core/modules/README.md +296 -0
- moai_adk/templates/.claude/skills/moai-foundation-core/modules/agents-reference.md +359 -0
- moai_adk/templates/.claude/skills/moai-foundation-core/modules/commands-reference.md +432 -0
- moai_adk/templates/.claude/skills/moai-foundation-core/modules/delegation-patterns.md +757 -0
- moai_adk/templates/.claude/skills/moai-foundation-core/modules/execution-rules.md +687 -0
- moai_adk/templates/.claude/skills/moai-foundation-core/modules/modular-system.md +665 -0
- moai_adk/templates/.claude/skills/moai-foundation-core/modules/progressive-disclosure.md +649 -0
- moai_adk/templates/.claude/skills/moai-foundation-core/modules/spec-first-tdd.md +864 -0
- moai_adk/templates/.claude/skills/moai-foundation-core/modules/token-optimization.md +708 -0
- moai_adk/templates/.claude/skills/moai-foundation-core/modules/trust-5-framework.md +981 -0
- moai_adk/templates/.claude/skills/moai-foundation-core/reference.md +478 -0
- moai_adk/templates/.claude/skills/moai-foundation-philosopher/SKILL.md +315 -0
- moai_adk/templates/.claude/skills/moai-foundation-philosopher/examples.md +228 -0
- moai_adk/templates/.claude/skills/moai-foundation-philosopher/modules/assumption-matrix.md +80 -0
- moai_adk/templates/.claude/skills/moai-foundation-philosopher/modules/cognitive-bias.md +199 -0
- moai_adk/templates/.claude/skills/moai-foundation-philosopher/modules/first-principles.md +140 -0
- moai_adk/templates/.claude/skills/moai-foundation-philosopher/modules/trade-off-analysis.md +154 -0
- moai_adk/templates/.claude/skills/moai-foundation-philosopher/reference.md +157 -0
- moai_adk/templates/.claude/skills/moai-foundation-quality/SKILL.md +364 -0
- moai_adk/templates/.claude/skills/moai-foundation-quality/examples.md +1232 -0
- moai_adk/templates/.claude/skills/moai-foundation-quality/modules/best-practices.md +261 -0
- moai_adk/templates/.claude/skills/moai-foundation-quality/modules/integration-patterns.md +194 -0
- moai_adk/templates/.claude/skills/moai-foundation-quality/modules/proactive-analysis.md +229 -0
- moai_adk/templates/.claude/skills/moai-foundation-quality/modules/trust5-validation.md +169 -0
- moai_adk/templates/.claude/skills/moai-foundation-quality/reference.md +1266 -0
- moai_adk/templates/.claude/skills/moai-foundation-quality/scripts/quality-gate.sh +668 -0
- moai_adk/templates/.claude/skills/moai-foundation-quality/templates/github-actions-quality.yml +481 -0
- moai_adk/templates/.claude/skills/moai-foundation-quality/templates/quality-config.yaml +519 -0
- moai_adk/templates/.claude/skills/moai-lang-cpp/SKILL.md +649 -0
- moai_adk/templates/.claude/skills/moai-lang-csharp/SKILL.md +478 -0
- moai_adk/templates/.claude/skills/moai-lang-elixir/SKILL.md +612 -0
- moai_adk/templates/.claude/skills/moai-lang-flutter/SKILL.md +477 -0
- moai_adk/templates/.claude/skills/moai-lang-flutter/examples.md +1090 -0
- moai_adk/templates/.claude/skills/moai-lang-flutter/reference.md +686 -0
- moai_adk/templates/.claude/skills/moai-lang-go/SKILL.md +376 -0
- moai_adk/templates/.claude/skills/moai-lang-go/examples.md +919 -0
- moai_adk/templates/.claude/skills/moai-lang-go/reference.md +737 -0
- moai_adk/templates/.claude/skills/moai-lang-java/SKILL.md +385 -0
- moai_adk/templates/.claude/skills/moai-lang-java/examples.md +864 -0
- moai_adk/templates/.claude/skills/moai-lang-java/reference.md +291 -0
- moai_adk/templates/.claude/skills/moai-lang-kotlin/SKILL.md +382 -0
- moai_adk/templates/.claude/skills/moai-lang-kotlin/examples.md +1006 -0
- moai_adk/templates/.claude/skills/moai-lang-kotlin/reference.md +562 -0
- moai_adk/templates/.claude/skills/moai-lang-php/SKILL.md +644 -0
- moai_adk/templates/.claude/skills/moai-lang-python/SKILL.md +481 -0
- moai_adk/templates/.claude/skills/moai-lang-python/examples.md +977 -0
- moai_adk/templates/.claude/skills/moai-lang-python/reference.md +804 -0
- moai_adk/templates/.claude/skills/moai-lang-r/SKILL.md +579 -0
- moai_adk/templates/.claude/skills/moai-lang-ruby/SKILL.md +687 -0
- moai_adk/templates/.claude/skills/moai-lang-rust/SKILL.md +372 -0
- moai_adk/templates/.claude/skills/moai-lang-rust/examples.md +659 -0
- moai_adk/templates/.claude/skills/moai-lang-rust/reference.md +504 -0
- moai_adk/templates/.claude/skills/moai-lang-scala/SKILL.md +497 -0
- moai_adk/templates/.claude/skills/moai-lang-scala/examples.md +633 -0
- moai_adk/templates/.claude/skills/moai-lang-scala/reference.md +423 -0
- moai_adk/templates/.claude/skills/moai-lang-swift/SKILL.md +497 -0
- moai_adk/templates/.claude/skills/moai-lang-swift/examples.md +918 -0
- moai_adk/templates/.claude/skills/moai-lang-swift/reference.md +672 -0
- moai_adk/templates/.claude/skills/moai-lang-typescript/SKILL.md +368 -0
- moai_adk/templates/.claude/skills/moai-lang-typescript/examples.md +1089 -0
- moai_adk/templates/.claude/skills/moai-lang-typescript/reference.md +731 -0
- moai_adk/templates/.claude/skills/moai-library-mermaid/SKILL.md +300 -0
- moai_adk/templates/.claude/skills/moai-library-mermaid/advanced-patterns.md +465 -0
- moai_adk/templates/.claude/skills/moai-library-mermaid/examples.md +270 -0
- moai_adk/templates/.claude/skills/moai-library-mermaid/optimization.md +440 -0
- moai_adk/templates/.claude/skills/moai-library-mermaid/reference.md +228 -0
- moai_adk/templates/.claude/skills/moai-library-nextra/SKILL.md +319 -0
- moai_adk/templates/.claude/skills/moai-library-nextra/advanced-patterns.md +336 -0
- moai_adk/templates/.claude/skills/moai-library-nextra/examples.md +592 -0
- moai_adk/templates/.claude/skills/moai-library-nextra/modules/advanced-deployment-patterns.md +182 -0
- moai_adk/templates/.claude/skills/moai-library-nextra/modules/advanced-patterns.md +17 -0
- moai_adk/templates/.claude/skills/moai-library-nextra/modules/configuration.md +57 -0
- moai_adk/templates/.claude/skills/moai-library-nextra/modules/content-architecture-optimization.md +162 -0
- moai_adk/templates/.claude/skills/moai-library-nextra/modules/deployment.md +52 -0
- moai_adk/templates/.claude/skills/moai-library-nextra/modules/framework-core-configuration.md +186 -0
- moai_adk/templates/.claude/skills/moai-library-nextra/modules/i18n-setup.md +55 -0
- moai_adk/templates/.claude/skills/moai-library-nextra/modules/mdx-components.md +52 -0
- moai_adk/templates/.claude/skills/moai-library-nextra/optimization.md +303 -0
- moai_adk/templates/.claude/skills/moai-library-nextra/reference.md +379 -0
- moai_adk/templates/.claude/skills/moai-library-shadcn/SKILL.md +372 -0
- moai_adk/templates/.claude/skills/moai-library-shadcn/examples.md +575 -0
- moai_adk/templates/.claude/skills/moai-library-shadcn/modules/advanced-patterns.md +394 -0
- moai_adk/templates/.claude/skills/moai-library-shadcn/modules/optimization.md +278 -0
- moai_adk/templates/.claude/skills/moai-library-shadcn/modules/shadcn-components.md +457 -0
- moai_adk/templates/.claude/skills/moai-library-shadcn/modules/shadcn-theming.md +373 -0
- moai_adk/templates/.claude/skills/moai-library-shadcn/reference.md +74 -0
- moai_adk/templates/.claude/skills/moai-mcp-figma/SKILL.md +402 -0
- moai_adk/templates/.claude/skills/moai-mcp-figma/advanced-patterns.md +607 -0
- moai_adk/templates/.claude/skills/moai-mcp-notion/SKILL.md +300 -0
- moai_adk/templates/.claude/skills/moai-mcp-notion/advanced-patterns.md +537 -0
- moai_adk/templates/.claude/skills/moai-platform-auth0/SKILL.md +291 -0
- moai_adk/templates/.claude/skills/moai-platform-clerk/SKILL.md +390 -0
- moai_adk/templates/.claude/skills/moai-platform-convex/SKILL.md +398 -0
- moai_adk/templates/.claude/skills/moai-platform-firebase-auth/SKILL.md +379 -0
- moai_adk/templates/.claude/skills/moai-platform-firestore/SKILL.md +358 -0
- moai_adk/templates/.claude/skills/moai-platform-neon/SKILL.md +467 -0
- moai_adk/templates/.claude/skills/moai-platform-railway/SKILL.md +377 -0
- moai_adk/templates/.claude/skills/moai-platform-supabase/SKILL.md +466 -0
- moai_adk/templates/.claude/skills/moai-platform-vercel/SKILL.md +482 -0
- moai_adk/templates/.claude/skills/moai-plugin-builder/SKILL.md +474 -0
- moai_adk/templates/.claude/skills/moai-plugin-builder/examples.md +621 -0
- moai_adk/templates/.claude/skills/moai-plugin-builder/migration.md +341 -0
- moai_adk/templates/.claude/skills/moai-plugin-builder/reference.md +463 -0
- moai_adk/templates/.claude/skills/moai-plugin-builder/validation.md +373 -0
- moai_adk/templates/.claude/skills/moai-security-auth0/SKILL.md +275 -0
- moai_adk/templates/.claude/skills/moai-security-auth0/modules/adaptive-mfa.md +233 -0
- moai_adk/templates/.claude/skills/moai-security-auth0/modules/akamai-integration.md +215 -0
- moai_adk/templates/.claude/skills/moai-security-auth0/modules/application-credentials.md +280 -0
- moai_adk/templates/.claude/skills/moai-security-auth0/modules/attack-protection-log-events.md +225 -0
- moai_adk/templates/.claude/skills/moai-security-auth0/modules/attack-protection-overview.md +140 -0
- moai_adk/templates/.claude/skills/moai-security-auth0/modules/bot-detection.md +144 -0
- moai_adk/templates/.claude/skills/moai-security-auth0/modules/breached-password-detection.md +187 -0
- moai_adk/templates/.claude/skills/moai-security-auth0/modules/brute-force-protection.md +189 -0
- moai_adk/templates/.claude/skills/moai-security-auth0/modules/certifications.md +282 -0
- moai_adk/templates/.claude/skills/moai-security-auth0/modules/compliance-overview.md +263 -0
- moai_adk/templates/.claude/skills/moai-security-auth0/modules/continuous-session-protection.md +307 -0
- moai_adk/templates/.claude/skills/moai-security-auth0/modules/customize-mfa.md +178 -0
- moai_adk/templates/.claude/skills/moai-security-auth0/modules/dpop-implementation.md +283 -0
- moai_adk/templates/.claude/skills/moai-security-auth0/modules/fapi-implementation.md +259 -0
- moai_adk/templates/.claude/skills/moai-security-auth0/modules/gdpr-compliance.md +313 -0
- moai_adk/templates/.claude/skills/moai-security-auth0/modules/guardian-configuration.md +269 -0
- moai_adk/templates/.claude/skills/moai-security-auth0/modules/highly-regulated-identity.md +272 -0
- moai_adk/templates/.claude/skills/moai-security-auth0/modules/jwt-fundamentals.md +248 -0
- moai_adk/templates/.claude/skills/moai-security-auth0/modules/mdl-verification.md +211 -0
- moai_adk/templates/.claude/skills/moai-security-auth0/modules/mfa-api-management.md +278 -0
- moai_adk/templates/.claude/skills/moai-security-auth0/modules/mfa-factors.md +226 -0
- moai_adk/templates/.claude/skills/moai-security-auth0/modules/mfa-overview.md +174 -0
- moai_adk/templates/.claude/skills/moai-security-auth0/modules/mtls-sender-constraining.md +316 -0
- moai_adk/templates/.claude/skills/moai-security-auth0/modules/ropg-flow-mfa.md +217 -0
- moai_adk/templates/.claude/skills/moai-security-auth0/modules/security-center.md +325 -0
- moai_adk/templates/.claude/skills/moai-security-auth0/modules/security-guidance.md +277 -0
- moai_adk/templates/.claude/skills/moai-security-auth0/modules/state-parameters.md +178 -0
- moai_adk/templates/.claude/skills/moai-security-auth0/modules/step-up-authentication.md +251 -0
- moai_adk/templates/.claude/skills/moai-security-auth0/modules/suspicious-ip-throttling.md +240 -0
- moai_adk/templates/.claude/skills/moai-security-auth0/modules/tenant-access-control.md +180 -0
- moai_adk/templates/.claude/skills/moai-security-auth0/modules/webauthn-fido.md +235 -0
- moai_adk/templates/.claude/skills/moai-workflow-jit-docs/SKILL.md +449 -0
- moai_adk/templates/.claude/skills/moai-workflow-jit-docs/advanced-patterns.md +379 -0
- moai_adk/templates/.claude/skills/moai-workflow-jit-docs/examples.md +544 -0
- moai_adk/templates/.claude/skills/moai-workflow-jit-docs/optimization.md +286 -0
- moai_adk/templates/.claude/skills/moai-workflow-jit-docs/reference.md +307 -0
- moai_adk/templates/.claude/skills/moai-workflow-project/README.md +190 -0
- moai_adk/templates/.claude/skills/moai-workflow-project/SKILL.md +390 -0
- moai_adk/templates/.claude/skills/moai-workflow-project/__init__.py +520 -0
- moai_adk/templates/.claude/skills/moai-workflow-project/complete_workflow_demo_fixed.py +574 -0
- moai_adk/templates/.claude/skills/moai-workflow-project/examples/complete_project_setup.py +317 -0
- moai_adk/templates/.claude/skills/moai-workflow-project/examples/complete_workflow_demo.py +663 -0
- moai_adk/templates/.claude/skills/moai-workflow-project/examples/config-migration-example.json +190 -0
- moai_adk/templates/.claude/skills/moai-workflow-project/examples/question-examples.json +175 -0
- moai_adk/templates/.claude/skills/moai-workflow-project/examples/quick_start.py +196 -0
- moai_adk/templates/.claude/skills/moai-workflow-project/examples.md +547 -0
- moai_adk/templates/.claude/skills/moai-workflow-project/modules/__init__.py +17 -0
- moai_adk/templates/.claude/skills/moai-workflow-project/modules/advanced-patterns.md +158 -0
- moai_adk/templates/.claude/skills/moai-workflow-project/modules/ask_user_integration.py +340 -0
- moai_adk/templates/.claude/skills/moai-workflow-project/modules/batch_questions.py +713 -0
- moai_adk/templates/.claude/skills/moai-workflow-project/modules/config_manager.py +538 -0
- moai_adk/templates/.claude/skills/moai-workflow-project/modules/documentation_manager.py +1336 -0
- moai_adk/templates/.claude/skills/moai-workflow-project/modules/language_initializer.py +730 -0
- moai_adk/templates/.claude/skills/moai-workflow-project/modules/migration_manager.py +608 -0
- moai_adk/templates/.claude/skills/moai-workflow-project/modules/template_optimizer.py +1005 -0
- moai_adk/templates/.claude/skills/moai-workflow-project/reference.md +275 -0
- moai_adk/templates/.claude/skills/moai-workflow-project/schemas/config-schema.json +316 -0
- moai_adk/templates/.claude/skills/moai-workflow-project/schemas/tab_schema.json +1434 -0
- moai_adk/templates/.claude/skills/moai-workflow-project/templates/config-template.json +71 -0
- moai_adk/templates/.claude/skills/moai-workflow-project/templates/doc-templates/product-template.md +44 -0
- moai_adk/templates/.claude/skills/moai-workflow-project/templates/doc-templates/structure-template.md +48 -0
- moai_adk/templates/.claude/skills/moai-workflow-project/templates/doc-templates/tech-template.md +92 -0
- moai_adk/templates/.claude/skills/moai-workflow-project/templates/question-templates/config-manager-setup.json +109 -0
- moai_adk/templates/.claude/skills/moai-workflow-project/templates/question-templates/language-initializer.json +228 -0
- moai_adk/templates/.claude/skills/moai-workflow-project/templates/question-templates/menu-project-config.json +130 -0
- moai_adk/templates/.claude/skills/moai-workflow-project/templates/question-templates/project-batch-questions.json +97 -0
- moai_adk/templates/.claude/skills/moai-workflow-project/templates/question-templates/spec-workflow-setup.json +150 -0
- moai_adk/templates/.claude/skills/moai-workflow-project/test_integration_simple.py +436 -0
- moai_adk/templates/.claude/skills/moai-workflow-spec/SKILL.md +534 -0
- moai_adk/templates/.claude/skills/moai-workflow-spec/examples.md +900 -0
- moai_adk/templates/.claude/skills/moai-workflow-spec/reference.md +704 -0
- moai_adk/templates/.claude/skills/moai-workflow-templates/SKILL.md +377 -0
- moai_adk/templates/.claude/skills/moai-workflow-templates/examples.md +552 -0
- moai_adk/templates/.claude/skills/moai-workflow-templates/modules/code-templates.md +124 -0
- moai_adk/templates/.claude/skills/moai-workflow-templates/modules/feedback-templates.md +100 -0
- moai_adk/templates/.claude/skills/moai-workflow-templates/modules/template-optimizer.md +138 -0
- moai_adk/templates/.claude/skills/moai-workflow-templates/reference.md +346 -0
- moai_adk/templates/.claude/skills/moai-workflow-testing/LICENSE.txt +202 -0
- moai_adk/templates/.claude/skills/moai-workflow-testing/SKILL.md +456 -0
- moai_adk/templates/.claude/skills/moai-workflow-testing/advanced-patterns.md +576 -0
- moai_adk/templates/.claude/skills/moai-workflow-testing/examples/ai-powered-testing.py +294 -0
- moai_adk/templates/.claude/skills/moai-workflow-testing/examples/console_logging.py +35 -0
- moai_adk/templates/.claude/skills/moai-workflow-testing/examples/element_discovery.py +40 -0
- moai_adk/templates/.claude/skills/moai-workflow-testing/examples/static_html_automation.py +34 -0
- moai_adk/templates/.claude/skills/moai-workflow-testing/examples.md +672 -0
- moai_adk/templates/.claude/skills/moai-workflow-testing/modules/README.md +220 -0
- moai_adk/templates/.claude/skills/moai-workflow-testing/modules/ai-debugging.md +845 -0
- moai_adk/templates/.claude/skills/moai-workflow-testing/modules/automated-code-review.md +1416 -0
- moai_adk/templates/.claude/skills/moai-workflow-testing/modules/performance-optimization.md +1234 -0
- moai_adk/templates/.claude/skills/moai-workflow-testing/modules/smart-refactoring.md +1243 -0
- moai_adk/templates/.claude/skills/moai-workflow-testing/modules/tdd-context7.md +1260 -0
- moai_adk/templates/.claude/skills/moai-workflow-testing/optimization.md +505 -0
- moai_adk/templates/.claude/skills/moai-workflow-testing/reference/playwright-best-practices.md +57 -0
- moai_adk/templates/.claude/skills/moai-workflow-testing/reference.md +440 -0
- moai_adk/templates/.claude/skills/moai-workflow-testing/scripts/with_server.py +218 -0
- moai_adk/templates/.claude/skills/moai-workflow-testing/templates/alfred-integration.md +376 -0
- moai_adk/templates/.claude/skills/moai-workflow-testing/workflows/enterprise-testing-workflow.py +571 -0
- moai_adk/templates/.claude/skills/moai-worktree/SKILL.md +411 -0
- moai_adk/templates/.claude/skills/moai-worktree/examples.md +606 -0
- moai_adk/templates/.claude/skills/moai-worktree/modules/integration-patterns.md +982 -0
- moai_adk/templates/.claude/skills/moai-worktree/modules/parallel-development.md +778 -0
- moai_adk/templates/.claude/skills/moai-worktree/modules/worktree-commands.md +646 -0
- moai_adk/templates/.claude/skills/moai-worktree/modules/worktree-management.md +782 -0
- moai_adk/templates/.claude/skills/moai-worktree/reference.md +357 -0
- moai_adk/templates/.git-hooks/pre-commit +128 -0
- moai_adk/templates/.git-hooks/pre-push +365 -0
- moai_adk/templates/.github/workflows/ci-universal.yml +513 -0
- moai_adk/templates/.github/workflows/security-secrets-check.yml +179 -0
- moai_adk/templates/.github/workflows/spec-issue-sync.yml +337 -0
- moai_adk/templates/.gitignore +222 -0
- moai_adk/templates/.mcp.json +13 -0
- moai_adk/templates/.moai/config/config.yaml +58 -0
- moai_adk/templates/.moai/config/questions/_schema.yaml +174 -0
- moai_adk/templates/.moai/config/questions/tab0-init.yaml +251 -0
- moai_adk/templates/.moai/config/questions/tab1-user.yaml +107 -0
- moai_adk/templates/.moai/config/questions/tab2-project.yaml +79 -0
- moai_adk/templates/.moai/config/questions/tab3-git.yaml +632 -0
- moai_adk/templates/.moai/config/questions/tab4-quality.yaml +182 -0
- moai_adk/templates/.moai/config/questions/tab5-system.yaml +96 -0
- moai_adk/templates/.moai/config/sections/git-strategy.yaml +116 -0
- moai_adk/templates/.moai/config/sections/language.yaml +11 -0
- moai_adk/templates/.moai/config/sections/project.yaml +13 -0
- moai_adk/templates/.moai/config/sections/quality.yaml +17 -0
- moai_adk/templates/.moai/config/sections/system.yaml +24 -0
- moai_adk/templates/.moai/config/sections/user.yaml +5 -0
- moai_adk/templates/.moai/config/statusline-config.yaml +92 -0
- moai_adk/templates/.moai/scripts/setup-glm.py +136 -0
- moai_adk/templates/CLAUDE.md +642 -0
- moai_adk/utils/__init__.py +30 -0
- moai_adk/utils/banner.py +38 -0
- moai_adk/utils/common.py +294 -0
- moai_adk/utils/link_validator.py +241 -0
- moai_adk/utils/logger.py +147 -0
- moai_adk/utils/safe_file_reader.py +206 -0
- moai_adk/utils/timeout.py +160 -0
- moai_adk/utils/toon_utils.py +256 -0
- moai_adk/version.py +22 -0
- moai_adk-0.35.1.dist-info/METADATA +3018 -0
- moai_adk-0.35.1.dist-info/RECORD +502 -0
- moai_adk-0.35.1.dist-info/WHEEL +4 -0
- moai_adk-0.35.1.dist-info/entry_points.txt +3 -0
- moai_adk-0.35.1.dist-info/licenses/LICENSE +21 -0
|
@@ -0,0 +1,1260 @@
|
|
|
1
|
+
# Test-Driven Development with Context7 Integration
|
|
2
|
+
|
|
3
|
+
> Module: RED-GREEN-REFACTOR TDD cycle with Context7 patterns and AI-powered testing
|
|
4
|
+
> Complexity: Advanced
|
|
5
|
+
> Time: 25+ minutes
|
|
6
|
+
> Dependencies: Python 3.8+, pytest, Context7 MCP, unittest, asyncio
|
|
7
|
+
|
|
8
|
+
## Core Implementation
|
|
9
|
+
|
|
10
|
+
### TDDManager Class
|
|
11
|
+
|
|
12
|
+
```python
|
|
13
|
+
import pytest
|
|
14
|
+
import unittest
|
|
15
|
+
import asyncio
|
|
16
|
+
import subprocess
|
|
17
|
+
import os
|
|
18
|
+
import sys
|
|
19
|
+
import time
|
|
20
|
+
from typing import Dict, List, Optional, Any, Union, Callable
|
|
21
|
+
from dataclasses import dataclass, field
|
|
22
|
+
from enum import Enum
|
|
23
|
+
import ast
|
|
24
|
+
import inspect
|
|
25
|
+
import json
|
|
26
|
+
from pathlib import Path
|
|
27
|
+
|
|
28
|
+
class TDDPhase(Enum):
|
|
29
|
+
"""TDD cycle phases."""
|
|
30
|
+
RED = "red" # Write failing test
|
|
31
|
+
GREEN = "green" # Make test pass
|
|
32
|
+
REFACTOR = "refactor" # Improve code while keeping tests green
|
|
33
|
+
REVIEW = "review" # Review and commit changes
|
|
34
|
+
|
|
35
|
+
class TestType(Enum):
|
|
36
|
+
"""Types of tests in TDD."""
|
|
37
|
+
UNIT = "unit"
|
|
38
|
+
INTEGRATION = "integration"
|
|
39
|
+
ACCEPTANCE = "acceptance"
|
|
40
|
+
PERFORMANCE = "performance"
|
|
41
|
+
SECURITY = "security"
|
|
42
|
+
REGRESSION = "regression"
|
|
43
|
+
|
|
44
|
+
class TestStatus(Enum):
|
|
45
|
+
"""Test execution status."""
|
|
46
|
+
PENDING = "pending"
|
|
47
|
+
RUNNING = "running"
|
|
48
|
+
PASSED = "passed"
|
|
49
|
+
FAILED = "failed"
|
|
50
|
+
SKIPPED = "skipped"
|
|
51
|
+
ERROR = "error"
|
|
52
|
+
|
|
53
|
+
@dataclass
|
|
54
|
+
class TestSpecification:
|
|
55
|
+
"""Specification for a TDD test."""
|
|
56
|
+
name: str
|
|
57
|
+
description: str
|
|
58
|
+
test_type: TestType
|
|
59
|
+
requirements: List[str]
|
|
60
|
+
acceptance_criteria: List[str]
|
|
61
|
+
edge_cases: List[str]
|
|
62
|
+
preconditions: List[str] = field(default_factory=list)
|
|
63
|
+
postconditions: List[str] = field(default_factory=list)
|
|
64
|
+
dependencies: List[str] = field(default_factory=list)
|
|
65
|
+
mock_requirements: Dict[str, Any] = field(default_factory=dict)
|
|
66
|
+
|
|
67
|
+
@dataclass
|
|
68
|
+
class TestCase:
|
|
69
|
+
"""Individual test case with metadata."""
|
|
70
|
+
id: str
|
|
71
|
+
name: str
|
|
72
|
+
file_path: str
|
|
73
|
+
line_number: int
|
|
74
|
+
specification: TestSpecification
|
|
75
|
+
status: TestStatus
|
|
76
|
+
execution_time: float
|
|
77
|
+
error_message: Optional[str] = None
|
|
78
|
+
coverage_data: Dict[str, Any] = field(default_factory=dict)
|
|
79
|
+
|
|
80
|
+
@dataclass
|
|
81
|
+
class TDDSession:
|
|
82
|
+
"""TDD development session with cycle tracking."""
|
|
83
|
+
id: str
|
|
84
|
+
project_path: str
|
|
85
|
+
current_phase: TDDPhase
|
|
86
|
+
test_cases: List[TestCase]
|
|
87
|
+
start_time: float
|
|
88
|
+
context7_patterns: Dict[str, Any] = field(default_factory=dict)
|
|
89
|
+
metrics: Dict[str, Any] = field(default_factory=dict)
|
|
90
|
+
|
|
91
|
+
class Context7TDDIntegration:
|
|
92
|
+
"""Integration with Context7 for TDD patterns and best practices."""
|
|
93
|
+
|
|
94
|
+
def __init__(self, context7_client=None):
|
|
95
|
+
self.context7 = context7_client
|
|
96
|
+
self.pattern_cache = {}
|
|
97
|
+
self.test_generators = {}
|
|
98
|
+
|
|
99
|
+
async def load_tdd_patterns(self, language: str = "python") -> Dict[str, Any]:
|
|
100
|
+
"""Load TDD patterns and best practices from Context7."""
|
|
101
|
+
|
|
102
|
+
cache_key = f"tdd_patterns_{language}"
|
|
103
|
+
if cache_key in self.pattern_cache:
|
|
104
|
+
return self.pattern_cache[cache_key]
|
|
105
|
+
|
|
106
|
+
patterns = {}
|
|
107
|
+
|
|
108
|
+
if self.context7:
|
|
109
|
+
try:
|
|
110
|
+
# Load TDD best practices
|
|
111
|
+
tdd_patterns = await self.context7.get_library_docs(
|
|
112
|
+
context7_library_id="/testing/pytest",
|
|
113
|
+
topic="TDD RED-GREEN-REFACTOR patterns best practices 2025",
|
|
114
|
+
tokens=4000
|
|
115
|
+
)
|
|
116
|
+
patterns['tdd_best_practices'] = tdd_patterns
|
|
117
|
+
|
|
118
|
+
# Load test patterns for specific language
|
|
119
|
+
if language == "python":
|
|
120
|
+
python_patterns = await self.context7.get_library_docs(
|
|
121
|
+
context7_library_id="/python/pytest",
|
|
122
|
+
topic="advanced testing patterns mocking fixtures 2025",
|
|
123
|
+
tokens=3000
|
|
124
|
+
)
|
|
125
|
+
patterns['python_testing'] = python_patterns
|
|
126
|
+
|
|
127
|
+
# Load assertion patterns
|
|
128
|
+
assertion_patterns = await self.context7.get_library_docs(
|
|
129
|
+
context7_library_id="/testing/assertions",
|
|
130
|
+
topic="assertion patterns error messages test design 2025",
|
|
131
|
+
tokens=2000
|
|
132
|
+
)
|
|
133
|
+
patterns['assertions'] = assertion_patterns
|
|
134
|
+
|
|
135
|
+
# Load mocking patterns
|
|
136
|
+
mocking_patterns = await self.context7.get_library_docs(
|
|
137
|
+
context7_library_id="/python/unittest-mock",
|
|
138
|
+
topic="mocking strategies test doubles isolation patterns 2025",
|
|
139
|
+
tokens=3000
|
|
140
|
+
)
|
|
141
|
+
patterns['mocking'] = mocking_patterns
|
|
142
|
+
|
|
143
|
+
except Exception as e:
|
|
144
|
+
print(f"Failed to load Context7 patterns: {e}")
|
|
145
|
+
patterns = self._get_default_patterns()
|
|
146
|
+
else:
|
|
147
|
+
patterns = self._get_default_patterns()
|
|
148
|
+
|
|
149
|
+
self.pattern_cache[cache_key] = patterns
|
|
150
|
+
return patterns
|
|
151
|
+
|
|
152
|
+
def _get_default_patterns(self) -> Dict[str, Any]:
|
|
153
|
+
"""Get default TDD patterns when Context7 is unavailable."""
|
|
154
|
+
return {
|
|
155
|
+
'tdd_best_practices': {
|
|
156
|
+
'red_phase': [
|
|
157
|
+
"Write the simplest possible failing test",
|
|
158
|
+
"Test one specific behavior or requirement",
|
|
159
|
+
"Ensure test clearly expresses intent",
|
|
160
|
+
"Make test fail for the right reason"
|
|
161
|
+
],
|
|
162
|
+
'green_phase': [
|
|
163
|
+
"Write the simplest code to make test pass",
|
|
164
|
+
"Don't worry about code quality yet",
|
|
165
|
+
"Focus on making the test green quickly",
|
|
166
|
+
"Avoid premature optimization"
|
|
167
|
+
],
|
|
168
|
+
'refactor_phase': [
|
|
169
|
+
"Improve code design while keeping tests green",
|
|
170
|
+
"Remove duplication and improve readability",
|
|
171
|
+
"Apply design patterns appropriately",
|
|
172
|
+
"Ensure all tests still pass"
|
|
173
|
+
]
|
|
174
|
+
},
|
|
175
|
+
'python_testing': {
|
|
176
|
+
'pytest_features': [
|
|
177
|
+
"Parametrized tests for multiple scenarios",
|
|
178
|
+
"Fixtures for test setup and teardown",
|
|
179
|
+
"Markers for categorizing tests",
|
|
180
|
+
"Plugins for enhanced functionality"
|
|
181
|
+
],
|
|
182
|
+
'assertions': [
|
|
183
|
+
"Use pytest's assert statements",
|
|
184
|
+
"Provide clear error messages",
|
|
185
|
+
"Test expected exceptions with pytest.raises",
|
|
186
|
+
"Use pytest.approx for floating point comparisons"
|
|
187
|
+
]
|
|
188
|
+
},
|
|
189
|
+
'assertions': {
|
|
190
|
+
'best_practices': [
|
|
191
|
+
"One assertion per test when possible",
|
|
192
|
+
"Clear and descriptive assertion messages",
|
|
193
|
+
"Test both positive and negative cases",
|
|
194
|
+
"Use appropriate assertion methods"
|
|
195
|
+
]
|
|
196
|
+
},
|
|
197
|
+
'mocking': {
|
|
198
|
+
'strategies': [
|
|
199
|
+
"Mock external dependencies",
|
|
200
|
+
"Use dependency injection for testability",
|
|
201
|
+
"Create test doubles for complex objects",
|
|
202
|
+
"Verify interactions with mocks"
|
|
203
|
+
]
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
class TestGenerator:
|
|
208
|
+
"""AI-powered test case generation based on specifications."""
|
|
209
|
+
|
|
210
|
+
def __init__(self, context7_client=None):
|
|
211
|
+
self.context7 = context7_client
|
|
212
|
+
self.templates = self._load_test_templates()
|
|
213
|
+
|
|
214
|
+
def _load_test_templates(self) -> Dict[str, str]:
|
|
215
|
+
"""Load test templates for different scenarios."""
|
|
216
|
+
return {
|
|
217
|
+
'unit_function': '''
|
|
218
|
+
def test_{function_name}_{scenario}():
|
|
219
|
+
"""
|
|
220
|
+
Test {description}
|
|
221
|
+
|
|
222
|
+
Given: {preconditions}
|
|
223
|
+
When: {action}
|
|
224
|
+
Then: {expected_outcome}
|
|
225
|
+
"""
|
|
226
|
+
# Arrange
|
|
227
|
+
{setup_code}
|
|
228
|
+
|
|
229
|
+
# Act
|
|
230
|
+
result = {function_call}
|
|
231
|
+
|
|
232
|
+
# Assert
|
|
233
|
+
assert result == {expected_value}, f"Expected {expected_value}, got {result}"
|
|
234
|
+
''',
|
|
235
|
+
'unit_method': '''
|
|
236
|
+
class Test{ClassName}:
|
|
237
|
+
def test_{method_name}_{scenario}(self):
|
|
238
|
+
"""
|
|
239
|
+
Test {description}
|
|
240
|
+
"""
|
|
241
|
+
# Arrange
|
|
242
|
+
{setup_code}
|
|
243
|
+
instance = {ClassName}({constructor_args})
|
|
244
|
+
|
|
245
|
+
# Act
|
|
246
|
+
result = instance.{method_name}({method_args})
|
|
247
|
+
|
|
248
|
+
# Assert
|
|
249
|
+
{assertions}
|
|
250
|
+
''',
|
|
251
|
+
'integration_test': '''
|
|
252
|
+
def test_{feature_name}_{scenario}():
|
|
253
|
+
"""
|
|
254
|
+
Test integration: {description}
|
|
255
|
+
"""
|
|
256
|
+
# Arrange
|
|
257
|
+
{setup_code}
|
|
258
|
+
|
|
259
|
+
# Act
|
|
260
|
+
result = {action}
|
|
261
|
+
|
|
262
|
+
# Assert
|
|
263
|
+
{assertions}
|
|
264
|
+
|
|
265
|
+
# Cleanup
|
|
266
|
+
{cleanup_code}
|
|
267
|
+
''',
|
|
268
|
+
'exception_test': '''
|
|
269
|
+
def test_{function_name}_raises_{exception}_{scenario}():
|
|
270
|
+
"""
|
|
271
|
+
Test that {function_name} raises {exception} when {condition}
|
|
272
|
+
"""
|
|
273
|
+
# Arrange
|
|
274
|
+
{setup_code}
|
|
275
|
+
|
|
276
|
+
# Act & Assert
|
|
277
|
+
with pytest.raises({exception}) as exc_info:
|
|
278
|
+
{function_call}
|
|
279
|
+
|
|
280
|
+
assert "{expected_message}" in str(exc_info.value)
|
|
281
|
+
''',
|
|
282
|
+
'parameterized_test': '''
|
|
283
|
+
@pytest.mark.parametrize("{param_names}", {test_values})
|
|
284
|
+
def test_{function_name}_{scenario}({param_names}):
|
|
285
|
+
"""
|
|
286
|
+
Test {function_name} with different inputs: {description}
|
|
287
|
+
"""
|
|
288
|
+
# Arrange
|
|
289
|
+
{setup_code}
|
|
290
|
+
|
|
291
|
+
# Act
|
|
292
|
+
result = {function_call}
|
|
293
|
+
|
|
294
|
+
# Assert
|
|
295
|
+
assert result == {expected_value}, f"For {param_names}={{param_names}}, expected {expected_value}, got {{result}}"
|
|
296
|
+
'''
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
async def generate_test_case(
|
|
300
|
+
self, specification: TestSpecification,
|
|
301
|
+
context7_patterns: Dict[str, Any] = None
|
|
302
|
+
) -> str:
|
|
303
|
+
"""Generate test code based on specification."""
|
|
304
|
+
|
|
305
|
+
if self.context7 and context7_patterns:
|
|
306
|
+
try:
|
|
307
|
+
# Use Context7 to enhance test generation
|
|
308
|
+
enhanced_spec = await self._enhance_specification_with_context7(
|
|
309
|
+
specification, context7_patterns
|
|
310
|
+
)
|
|
311
|
+
return self._generate_test_from_enhanced_spec(enhanced_spec)
|
|
312
|
+
except Exception as e:
|
|
313
|
+
print(f"Context7 test generation failed: {e}")
|
|
314
|
+
|
|
315
|
+
return self._generate_test_from_specification(specification)
|
|
316
|
+
|
|
317
|
+
async def _enhance_specification_with_context7(
|
|
318
|
+
self, specification: TestSpecification,
|
|
319
|
+
context7_patterns: Dict[str, Any]
|
|
320
|
+
) -> TestSpecification:
|
|
321
|
+
"""Enhance test specification using Context7 patterns."""
|
|
322
|
+
|
|
323
|
+
# Add additional edge cases based on Context7 patterns
|
|
324
|
+
additional_edge_cases = []
|
|
325
|
+
|
|
326
|
+
testing_patterns = context7_patterns.get('python_testing', {})
|
|
327
|
+
if testing_patterns:
|
|
328
|
+
# Add common edge cases for different data types
|
|
329
|
+
if any('number' in str(req).lower() for req in specification.requirements):
|
|
330
|
+
additional_edge_cases.extend([
|
|
331
|
+
"Test with zero value",
|
|
332
|
+
"Test with negative value",
|
|
333
|
+
"Test with maximum/minimum values",
|
|
334
|
+
"Test with floating point edge cases"
|
|
335
|
+
])
|
|
336
|
+
|
|
337
|
+
if any('string' in str(req).lower() for req in specification.requirements):
|
|
338
|
+
additional_edge_cases.extend([
|
|
339
|
+
"Test with empty string",
|
|
340
|
+
"Test with very long string",
|
|
341
|
+
"Test with special characters",
|
|
342
|
+
"Test with unicode characters"
|
|
343
|
+
])
|
|
344
|
+
|
|
345
|
+
if any('list' in str(req).lower() or 'array' in str(req).lower() for req in specification.requirements):
|
|
346
|
+
additional_edge_cases.extend([
|
|
347
|
+
"Test with empty list",
|
|
348
|
+
"Test with single element",
|
|
349
|
+
"Test with large list",
|
|
350
|
+
"Test with duplicate elements"
|
|
351
|
+
])
|
|
352
|
+
|
|
353
|
+
# Combine original and additional edge cases
|
|
354
|
+
combined_edge_cases = list(set(specification.edge_cases + additional_edge_cases))
|
|
355
|
+
|
|
356
|
+
return TestSpecification(
|
|
357
|
+
name=specification.name,
|
|
358
|
+
description=specification.description,
|
|
359
|
+
test_type=specification.test_type,
|
|
360
|
+
requirements=specification.requirements,
|
|
361
|
+
acceptance_criteria=specification.acceptance_criteria,
|
|
362
|
+
edge_cases=combined_edge_cases,
|
|
363
|
+
preconditions=specification.preconditions,
|
|
364
|
+
postconditions=specification.postconditions,
|
|
365
|
+
dependencies=specification.dependencies,
|
|
366
|
+
mock_requirements=specification.mock_requirements
|
|
367
|
+
)
|
|
368
|
+
|
|
369
|
+
def _generate_test_from_enhanced_spec(self, spec: TestSpecification) -> str:
|
|
370
|
+
"""Generate test code from enhanced specification."""
|
|
371
|
+
return self._generate_test_from_specification(spec)
|
|
372
|
+
|
|
373
|
+
def _generate_test_from_specification(self, spec: TestSpecification) -> str:
|
|
374
|
+
"""Generate test code from specification."""
|
|
375
|
+
|
|
376
|
+
# Determine appropriate template based on test type and requirements
|
|
377
|
+
if spec.test_type == TestType.UNIT:
|
|
378
|
+
return self._generate_unit_test(spec)
|
|
379
|
+
elif spec.test_type == TestType.INTEGRATION:
|
|
380
|
+
return self._generate_integration_test(spec)
|
|
381
|
+
else:
|
|
382
|
+
return self._generate_generic_test(spec)
|
|
383
|
+
|
|
384
|
+
def _generate_unit_test(self, spec: TestSpecification) -> str:
|
|
385
|
+
"""Generate unit test code."""
|
|
386
|
+
|
|
387
|
+
# Extract function/class information from specification name
|
|
388
|
+
function_name = spec.name.lower().replace('test_', '').replace('_test', '')
|
|
389
|
+
|
|
390
|
+
# Check if this is an exception test
|
|
391
|
+
if any('error' in criterion.lower() or 'exception' in criterion.lower()
|
|
392
|
+
for criterion in spec.acceptance_criteria):
|
|
393
|
+
return self._generate_exception_test(spec, function_name)
|
|
394
|
+
|
|
395
|
+
# Check if this requires parameterization
|
|
396
|
+
if len(spec.acceptance_criteria) > 1 or len(spec.edge_cases) > 2:
|
|
397
|
+
return self._generate_parameterized_test(spec, function_name)
|
|
398
|
+
|
|
399
|
+
# Generate standard unit test
|
|
400
|
+
return self._generate_standard_unit_test(spec, function_name)
|
|
401
|
+
|
|
402
|
+
def _generate_standard_unit_test(self, spec: TestSpecification, function_name: str) -> str:
|
|
403
|
+
"""Generate standard unit test."""
|
|
404
|
+
|
|
405
|
+
template = self.templates['unit_function']
|
|
406
|
+
|
|
407
|
+
# Fill template with specification details
|
|
408
|
+
setup_code = self._generate_setup_code(spec)
|
|
409
|
+
function_call = self._generate_function_call(function_name, spec)
|
|
410
|
+
assertions = self._generate_assertions(spec)
|
|
411
|
+
|
|
412
|
+
return template.format(
|
|
413
|
+
function_name=function_name,
|
|
414
|
+
scenario=self._extract_scenario(spec),
|
|
415
|
+
description=spec.description,
|
|
416
|
+
preconditions=', '.join(spec.preconditions),
|
|
417
|
+
action=self._describe_action(spec),
|
|
418
|
+
expected_outcome=spec.acceptance_criteria[0] if spec.acceptance_criteria else "expected behavior",
|
|
419
|
+
setup_code=setup_code,
|
|
420
|
+
function_call=function_call,
|
|
421
|
+
expected_value=self._extract_expected_value(spec),
|
|
422
|
+
assertions=assertions
|
|
423
|
+
)
|
|
424
|
+
|
|
425
|
+
def _generate_exception_test(self, spec: TestSpecification, function_name: str) -> str:
|
|
426
|
+
"""Generate exception test."""
|
|
427
|
+
|
|
428
|
+
template = self.templates['exception_test']
|
|
429
|
+
|
|
430
|
+
# Extract expected exception and message
|
|
431
|
+
exception_type = "Exception" # Default
|
|
432
|
+
expected_message = "Error occurred"
|
|
433
|
+
|
|
434
|
+
for criterion in spec.acceptance_criteria:
|
|
435
|
+
if 'raise' in criterion.lower() or 'exception' in criterion.lower():
|
|
436
|
+
# Try to extract exception type
|
|
437
|
+
if 'valueerror' in criterion.lower():
|
|
438
|
+
exception_type = "ValueError"
|
|
439
|
+
elif 'typeerror' in criterion.lower():
|
|
440
|
+
exception_type = "TypeError"
|
|
441
|
+
elif 'attributeerror' in criterion.lower():
|
|
442
|
+
exception_type = "AttributeError"
|
|
443
|
+
elif 'keyerror' in criterion.lower():
|
|
444
|
+
exception_type = "KeyError"
|
|
445
|
+
|
|
446
|
+
# Try to extract expected message
|
|
447
|
+
if 'message:' in criterion.lower():
|
|
448
|
+
parts = criterion.split('message:')
|
|
449
|
+
if len(parts) > 1:
|
|
450
|
+
expected_message = parts[1].strip().strip('"\'')
|
|
451
|
+
|
|
452
|
+
return template.format(
|
|
453
|
+
function_name=function_name,
|
|
454
|
+
exception=exception_type,
|
|
455
|
+
scenario=self._extract_scenario(spec),
|
|
456
|
+
condition=self._describe_condition(spec),
|
|
457
|
+
setup_code=self._generate_setup_code(spec),
|
|
458
|
+
function_call=self._generate_function_call(function_name, spec),
|
|
459
|
+
expected_message=expected_message
|
|
460
|
+
)
|
|
461
|
+
|
|
462
|
+
def _generate_parameterized_test(self, spec: TestSpecification, function_name: str) -> str:
|
|
463
|
+
"""Generate parameterized test."""
|
|
464
|
+
|
|
465
|
+
template = self.templates['parameterized_test']
|
|
466
|
+
|
|
467
|
+
# Generate test parameters and values
|
|
468
|
+
param_names, test_values = self._generate_test_parameters(spec)
|
|
469
|
+
|
|
470
|
+
return template.format(
|
|
471
|
+
function_name=function_name,
|
|
472
|
+
scenario=self._extract_scenario(spec),
|
|
473
|
+
description=spec.description,
|
|
474
|
+
param_names=', '.join(param_names),
|
|
475
|
+
test_values=test_values,
|
|
476
|
+
setup_code=self._generate_setup_code(spec),
|
|
477
|
+
function_call=self._generate_function_call(function_name, spec),
|
|
478
|
+
expected_value=self._extract_expected_value(spec)
|
|
479
|
+
)
|
|
480
|
+
|
|
481
|
+
def _generate_integration_test(self, spec: TestSpecification) -> str:
|
|
482
|
+
"""Generate integration test."""
|
|
483
|
+
|
|
484
|
+
template = self.templates['integration_test']
|
|
485
|
+
|
|
486
|
+
feature_name = spec.name.lower().replace('test_', '').replace('_test', '')
|
|
487
|
+
|
|
488
|
+
return template.format(
|
|
489
|
+
feature_name=feature_name,
|
|
490
|
+
scenario=self._extract_scenario(spec),
|
|
491
|
+
description=spec.description,
|
|
492
|
+
setup_code=self._generate_setup_code(spec),
|
|
493
|
+
action=self._describe_action(spec),
|
|
494
|
+
assertions=self._generate_assertions(spec),
|
|
495
|
+
cleanup_code=self._generate_cleanup_code(spec)
|
|
496
|
+
)
|
|
497
|
+
|
|
498
|
+
def _generate_generic_test(self, spec: TestSpecification) -> str:
|
|
499
|
+
"""Generate generic test code."""
|
|
500
|
+
|
|
501
|
+
test_code = f'''
|
|
502
|
+
def test_{spec.name.replace(' ', '_').lower()}():
|
|
503
|
+
"""
|
|
504
|
+
Test: {spec.description}
|
|
505
|
+
|
|
506
|
+
Requirements:
|
|
507
|
+
{chr(10).join(f" - {req}" for req in spec.requirements)}
|
|
508
|
+
|
|
509
|
+
Acceptance Criteria:
|
|
510
|
+
{chr(10).join(f" - {crit}" for crit in spec.acceptance_criteria)}
|
|
511
|
+
"""
|
|
512
|
+
# TODO: Implement test based on specification
|
|
513
|
+
# This is a generated template - fill in with actual test logic
|
|
514
|
+
|
|
515
|
+
# Arrange
|
|
516
|
+
# {chr(10).join(f" # {req}" for req in spec.preconditions)}
|
|
517
|
+
|
|
518
|
+
# Act
|
|
519
|
+
# result = function_to_test()
|
|
520
|
+
|
|
521
|
+
# Assert
|
|
522
|
+
# assert result is not None
|
|
523
|
+
# Add specific assertions based on acceptance criteria
|
|
524
|
+
'''
|
|
525
|
+
|
|
526
|
+
return test_code
|
|
527
|
+
|
|
528
|
+
def _extract_scenario(self, spec: TestSpecification) -> str:
|
|
529
|
+
"""Extract scenario name from specification."""
|
|
530
|
+
if '_' in spec.name:
|
|
531
|
+
parts = spec.name.split('_')
|
|
532
|
+
if len(parts) > 1:
|
|
533
|
+
return '_'.join(parts[1:])
|
|
534
|
+
return 'default'
|
|
535
|
+
|
|
536
|
+
def _describe_action(self, spec: TestSpecification) -> str:
|
|
537
|
+
"""Describe the action being tested."""
|
|
538
|
+
return f"Call {spec.name}"
|
|
539
|
+
|
|
540
|
+
def _describe_condition(self, spec: TestSpecification) -> str:
|
|
541
|
+
"""Describe condition for exception test."""
|
|
542
|
+
return spec.requirements[0] if spec.requirements else "invalid input"
|
|
543
|
+
|
|
544
|
+
def _generate_setup_code(self, spec: TestSpecification) -> str:
|
|
545
|
+
"""Generate setup code based on specification."""
|
|
546
|
+
setup_lines = []
|
|
547
|
+
|
|
548
|
+
# Add mock requirements
|
|
549
|
+
for mock_name, mock_config in spec.mock_requirements.items():
|
|
550
|
+
if isinstance(mock_config, dict) and 'return_value' in mock_config:
|
|
551
|
+
setup_lines.append(f"{mock_name} = Mock(return_value={mock_config['return_value']})")
|
|
552
|
+
else:
|
|
553
|
+
setup_lines.append(f"{mock_name} = Mock()")
|
|
554
|
+
|
|
555
|
+
# Add preconditions as setup
|
|
556
|
+
for condition in spec.preconditions:
|
|
557
|
+
setup_lines.append(f"# {condition}")
|
|
558
|
+
|
|
559
|
+
return '\n '.join(setup_lines) if setup_lines else "pass"
|
|
560
|
+
|
|
561
|
+
def _generate_function_call(self, function_name: str, spec: TestSpecification) -> str:
|
|
562
|
+
"""Generate function call with arguments."""
|
|
563
|
+
|
|
564
|
+
# Extract arguments from mock requirements or requirements
|
|
565
|
+
args = []
|
|
566
|
+
|
|
567
|
+
if spec.mock_requirements:
|
|
568
|
+
args.extend(spec.mock_requirements.keys())
|
|
569
|
+
|
|
570
|
+
if not args:
|
|
571
|
+
# Add placeholder arguments based on requirements
|
|
572
|
+
for req in spec.requirements[:3]: # Limit to first 3 requirements
|
|
573
|
+
if 'input' in req.lower() or 'parameter' in req.lower():
|
|
574
|
+
args.append("test_input")
|
|
575
|
+
break
|
|
576
|
+
|
|
577
|
+
return f"{function_name}({', '.join(args)})" if args else f"{function_name}()"
|
|
578
|
+
|
|
579
|
+
def _generate_assertions(self, spec: TestSpecification) -> str:
|
|
580
|
+
"""Generate assertions based on acceptance criteria."""
|
|
581
|
+
assertions = []
|
|
582
|
+
|
|
583
|
+
for criterion in spec.acceptance_criteria[:3]: # Limit to first 3 criteria
|
|
584
|
+
if 'returns' in criterion.lower() or 'result' in criterion.lower():
|
|
585
|
+
assertions.append("assert result is not None")
|
|
586
|
+
elif 'equals' in criterion.lower() or 'equal' in criterion.lower():
|
|
587
|
+
assertions.append("assert result == expected_value")
|
|
588
|
+
elif 'length' in criterion.lower():
|
|
589
|
+
assertions.append("assert len(result) > 0")
|
|
590
|
+
else:
|
|
591
|
+
assertions.append(f"# {criterion}")
|
|
592
|
+
|
|
593
|
+
return '\n '.join(assertions) if assertions else "assert True # Add specific assertions"
|
|
594
|
+
|
|
595
|
+
def _generate_cleanup_code(self, spec: TestSpecification) -> str:
|
|
596
|
+
"""Generate cleanup code for integration tests."""
|
|
597
|
+
cleanup_lines = []
|
|
598
|
+
|
|
599
|
+
# Add cleanup for any resources mentioned in postconditions
|
|
600
|
+
for condition in spec.postconditions:
|
|
601
|
+
if 'close' in condition.lower():
|
|
602
|
+
cleanup_lines.append("# Close connections")
|
|
603
|
+
elif 'delete' in condition.lower():
|
|
604
|
+
cleanup_lines.append("# Delete temporary resources")
|
|
605
|
+
else:
|
|
606
|
+
cleanup_lines.append(f"# {condition}")
|
|
607
|
+
|
|
608
|
+
return '\n '.join(cleanup_lines) if cleanup_lines else "pass"
|
|
609
|
+
|
|
610
|
+
def _extract_expected_value(self, spec: TestSpecification) -> str:
|
|
611
|
+
"""Extract expected value from acceptance criteria."""
|
|
612
|
+
for criterion in spec.acceptance_criteria:
|
|
613
|
+
if 'returns' in criterion.lower():
|
|
614
|
+
# Try to extract expected value
|
|
615
|
+
if 'true' in criterion.lower():
|
|
616
|
+
return "True"
|
|
617
|
+
elif 'false' in criterion.lower():
|
|
618
|
+
return "False"
|
|
619
|
+
elif 'none' in criterion.lower():
|
|
620
|
+
return "None"
|
|
621
|
+
elif 'empty' in criterion.lower():
|
|
622
|
+
return "[]"
|
|
623
|
+
else:
|
|
624
|
+
return "expected_result"
|
|
625
|
+
return "expected_result"
|
|
626
|
+
|
|
627
|
+
def _generate_test_parameters(self, spec: TestSpecification) -> tuple:
|
|
628
|
+
"""Generate parameters and values for parameterized tests."""
|
|
629
|
+
|
|
630
|
+
# Create test cases from acceptance criteria and edge cases
|
|
631
|
+
test_cases = []
|
|
632
|
+
|
|
633
|
+
# Add acceptance criteria as test cases
|
|
634
|
+
for criterion in spec.acceptance_criteria:
|
|
635
|
+
if 'input' in criterion.lower():
|
|
636
|
+
# Extract input values
|
|
637
|
+
if 'valid' in criterion.lower():
|
|
638
|
+
test_cases.append(('valid_input', 'expected_output'))
|
|
639
|
+
elif 'invalid' in criterion.lower():
|
|
640
|
+
test_cases.append(('invalid_input', 'exception'))
|
|
641
|
+
|
|
642
|
+
# Add edge cases
|
|
643
|
+
for edge_case in spec.edge_cases:
|
|
644
|
+
if 'zero' in edge_case.lower():
|
|
645
|
+
test_cases.append((0, 'zero_result'))
|
|
646
|
+
elif 'empty' in edge_case.lower():
|
|
647
|
+
test_cases.append(('', 'empty_result'))
|
|
648
|
+
elif 'null' in edge_case.lower() or 'none' in edge_case.lower():
|
|
649
|
+
test_cases.append((None, 'none_result'))
|
|
650
|
+
|
|
651
|
+
# Convert to pytest format
|
|
652
|
+
if test_cases:
|
|
653
|
+
param_names = ['test_input', 'expected_output']
|
|
654
|
+
test_values = str(test_cases).replace("'", '"')
|
|
655
|
+
return param_names, test_values
|
|
656
|
+
|
|
657
|
+
# Fallback
|
|
658
|
+
return ['test_input', 'expected_output'], '[("test", "expected")]'
|
|
659
|
+
|
|
660
|
+
class TDDManager:
|
|
661
|
+
"""Main TDD workflow manager with Context7 integration."""
|
|
662
|
+
|
|
663
|
+
def __init__(self, project_path: str, context7_client=None):
|
|
664
|
+
self.project_path = Path(project_path)
|
|
665
|
+
self.context7 = context7_client
|
|
666
|
+
self.context7_integration = Context7TDDIntegration(context7_client)
|
|
667
|
+
self.test_generator = TestGenerator(context7_client)
|
|
668
|
+
self.current_session = None
|
|
669
|
+
self.test_history = []
|
|
670
|
+
|
|
671
|
+
async def start_tdd_session(
|
|
672
|
+
self, feature_name: str,
|
|
673
|
+
test_types: List[TestType] = None
|
|
674
|
+
) -> TDDSession:
|
|
675
|
+
"""Start a new TDD development session."""
|
|
676
|
+
|
|
677
|
+
if test_types is None:
|
|
678
|
+
test_types = [TestType.UNIT, TestType.INTEGRATION]
|
|
679
|
+
|
|
680
|
+
# Load Context7 patterns
|
|
681
|
+
context7_patterns = await self.context7_integration.load_tdd_patterns()
|
|
682
|
+
|
|
683
|
+
# Create session
|
|
684
|
+
session = TDDSession(
|
|
685
|
+
id=f"tdd_{feature_name}_{int(time.time())}",
|
|
686
|
+
project_path=str(self.project_path),
|
|
687
|
+
current_phase=TDDPhase.RED,
|
|
688
|
+
test_cases=[],
|
|
689
|
+
start_time=time.time(),
|
|
690
|
+
context7_patterns=context7_patterns,
|
|
691
|
+
metrics={
|
|
692
|
+
'tests_written': 0,
|
|
693
|
+
'tests_passing': 0,
|
|
694
|
+
'tests_failing': 0,
|
|
695
|
+
'coverage_percentage': 0.0
|
|
696
|
+
}
|
|
697
|
+
)
|
|
698
|
+
|
|
699
|
+
self.current_session = session
|
|
700
|
+
return session
|
|
701
|
+
|
|
702
|
+
async def write_failing_test(
|
|
703
|
+
self, specification: TestSpecification,
|
|
704
|
+
file_path: str = None
|
|
705
|
+
) -> str:
|
|
706
|
+
"""RED phase: Write a failing test based on specification."""
|
|
707
|
+
|
|
708
|
+
if not self.current_session:
|
|
709
|
+
raise ValueError("No active TDD session")
|
|
710
|
+
|
|
711
|
+
# Generate test code
|
|
712
|
+
test_code = await self.test_generator.generate_test_case(
|
|
713
|
+
specification, self.current_session.context7_patterns
|
|
714
|
+
)
|
|
715
|
+
|
|
716
|
+
# Determine file path
|
|
717
|
+
if file_path is None:
|
|
718
|
+
file_path = self._determine_test_file_path(specification)
|
|
719
|
+
|
|
720
|
+
# Write test file
|
|
721
|
+
full_path = self.project_path / file_path
|
|
722
|
+
full_path.parent.mkdir(parents=True, exist_ok=True)
|
|
723
|
+
|
|
724
|
+
with open(full_path, 'a', encoding='utf-8') as f:
|
|
725
|
+
f.write('\n\n' + test_code)
|
|
726
|
+
|
|
727
|
+
# Create test case object
|
|
728
|
+
test_case = TestCase(
|
|
729
|
+
id=f"test_{int(time.time())}",
|
|
730
|
+
name=specification.name,
|
|
731
|
+
file_path=str(full_path),
|
|
732
|
+
line_number=self._count_lines_in_file(str(full_path)),
|
|
733
|
+
specification=specification,
|
|
734
|
+
status=TestStatus.PENDING,
|
|
735
|
+
execution_time=0.0
|
|
736
|
+
)
|
|
737
|
+
|
|
738
|
+
self.current_session.test_cases.append(test_case)
|
|
739
|
+
self.current_session.metrics['tests_written'] += 1
|
|
740
|
+
|
|
741
|
+
return str(full_path)
|
|
742
|
+
|
|
743
|
+
async def run_tests_and_verify_failure(self) -> Dict[str, Any]:
|
|
744
|
+
"""RED phase: Run tests and verify they fail as expected."""
|
|
745
|
+
|
|
746
|
+
if not self.current_session:
|
|
747
|
+
raise ValueError("No active TDD session")
|
|
748
|
+
|
|
749
|
+
# Run tests using pytest
|
|
750
|
+
test_results = await self._run_pytest()
|
|
751
|
+
|
|
752
|
+
# Update session metrics
|
|
753
|
+
failing_tests = test_results.get('failures', 0)
|
|
754
|
+
self.current_session.metrics['tests_failing'] = failing_tests
|
|
755
|
+
|
|
756
|
+
# Verify at least one test is failing (RED phase requirement)
|
|
757
|
+
if failing_tests == 0:
|
|
758
|
+
raise ValueError("RED phase violation: No tests are failing. Write a proper failing test first.")
|
|
759
|
+
|
|
760
|
+
return test_results
|
|
761
|
+
|
|
762
|
+
async def implement_minimum_code_to_pass(self, target_function: str) -> Dict[str, Any]:
|
|
763
|
+
"""GREEN phase: Implement minimum code to make tests pass."""
|
|
764
|
+
|
|
765
|
+
if not self.current_session:
|
|
766
|
+
raise ValueError("No active TDD session")
|
|
767
|
+
|
|
768
|
+
# Generate minimum implementation
|
|
769
|
+
implementation = await self._generate_minimum_implementation(target_function)
|
|
770
|
+
|
|
771
|
+
# Write implementation
|
|
772
|
+
impl_path = self._determine_implementation_file_path(target_function)
|
|
773
|
+
full_path = self.project_path / impl_path
|
|
774
|
+
full_path.parent.mkdir(parents=True, exist_ok=True)
|
|
775
|
+
|
|
776
|
+
with open(full_path, 'w', encoding='utf-8') as f:
|
|
777
|
+
f.write(implementation)
|
|
778
|
+
|
|
779
|
+
# Run tests to verify they pass
|
|
780
|
+
test_results = await self._run_pytest()
|
|
781
|
+
|
|
782
|
+
# Update session metrics
|
|
783
|
+
passing_tests = test_results.get('passed', 0)
|
|
784
|
+
self.current_session.metrics['tests_passing'] = passing_tests
|
|
785
|
+
|
|
786
|
+
if test_results.get('failures', 0) > 0:
|
|
787
|
+
raise ValueError("GREEN phase violation: Tests are still failing. Implementation needs adjustment.")
|
|
788
|
+
|
|
789
|
+
self.current_session.current_phase = TDDPhase.GREEN
|
|
790
|
+
return test_results
|
|
791
|
+
|
|
792
|
+
async def refactor_while_maintaining_tests(self) -> Dict[str, Any]:
|
|
793
|
+
"""REFACTOR phase: Improve code while keeping tests green."""
|
|
794
|
+
|
|
795
|
+
if not self.current_session:
|
|
796
|
+
raise ValueError("No active TDD session")
|
|
797
|
+
|
|
798
|
+
if self.current_session.current_phase != TDDPhase.GREEN:
|
|
799
|
+
raise ValueError("Must complete GREEN phase before REFACTOR")
|
|
800
|
+
|
|
801
|
+
# Get Context7 refactoring patterns
|
|
802
|
+
refactoring_patterns = await self._get_refactoring_patterns()
|
|
803
|
+
|
|
804
|
+
# Generate refactoring suggestions
|
|
805
|
+
suggestions = await self._generate_refactoring_suggestions(refactoring_patterns)
|
|
806
|
+
|
|
807
|
+
# Apply refactoring suggestions
|
|
808
|
+
for suggestion in suggestions:
|
|
809
|
+
await self._apply_refactoring_suggestion(suggestion)
|
|
810
|
+
|
|
811
|
+
# Verify tests still pass after each refactoring
|
|
812
|
+
test_results = await self._run_pytest()
|
|
813
|
+
if test_results.get('failures', 0) > 0:
|
|
814
|
+
raise ValueError(f"REFACTOR phase violation: Tests failed after applying suggestion: {suggestion['description']}")
|
|
815
|
+
|
|
816
|
+
self.current_session.current_phase = TDDPhase.REFACTOR
|
|
817
|
+
return suggestions
|
|
818
|
+
|
|
819
|
+
async def run_full_tdd_cycle(
|
|
820
|
+
self, specification: TestSpecification,
|
|
821
|
+
target_function: str = None
|
|
822
|
+
) -> Dict[str, Any]:
|
|
823
|
+
"""Run complete RED-GREEN-REFACTOR TDD cycle."""
|
|
824
|
+
|
|
825
|
+
cycle_results = {}
|
|
826
|
+
|
|
827
|
+
# RED phase
|
|
828
|
+
print(" RED Phase: Writing failing test...")
|
|
829
|
+
test_file = await self.write_failing_test(specification)
|
|
830
|
+
red_results = await self.run_tests_and_verify_failure()
|
|
831
|
+
cycle_results['red'] = {'test_file': test_file, 'results': red_results}
|
|
832
|
+
|
|
833
|
+
# GREEN phase
|
|
834
|
+
print("🟢 GREEN Phase: Implementing minimum code...")
|
|
835
|
+
if target_function is None:
|
|
836
|
+
target_function = specification.name.replace('test_', '').replace('_test', '')
|
|
837
|
+
green_results = await self.implement_minimum_code_to_pass(target_function)
|
|
838
|
+
cycle_results['green'] = {'results': green_results}
|
|
839
|
+
|
|
840
|
+
# REFACTOR phase
|
|
841
|
+
print(" REFACTOR Phase: Improving code quality...")
|
|
842
|
+
refactor_results = await self.refactor_while_maintaining_tests()
|
|
843
|
+
cycle_results['refactor'] = {'suggestions': refactor_results}
|
|
844
|
+
|
|
845
|
+
# REVIEW phase
|
|
846
|
+
print("🟣 REVIEW Phase: Final verification...")
|
|
847
|
+
coverage_results = await self._run_coverage_analysis()
|
|
848
|
+
cycle_results['review'] = {'coverage': coverage_results}
|
|
849
|
+
|
|
850
|
+
self.current_session.current_phase = TDDPhase.REVIEW
|
|
851
|
+
return cycle_results
|
|
852
|
+
|
|
853
|
+
async def _run_pytest(self) -> Dict[str, Any]:
|
|
854
|
+
"""Run pytest and return results."""
|
|
855
|
+
|
|
856
|
+
try:
|
|
857
|
+
# Run pytest with JSON output for parsing
|
|
858
|
+
result = subprocess.run(
|
|
859
|
+
[
|
|
860
|
+
sys.executable, '-m', 'pytest',
|
|
861
|
+
str(self.project_path),
|
|
862
|
+
'--tb=short',
|
|
863
|
+
'--json-report',
|
|
864
|
+
'--json-report-file=/tmp/pytest_results.json'
|
|
865
|
+
],
|
|
866
|
+
capture_output=True,
|
|
867
|
+
text=True,
|
|
868
|
+
cwd=str(self.project_path)
|
|
869
|
+
)
|
|
870
|
+
|
|
871
|
+
# Parse results
|
|
872
|
+
try:
|
|
873
|
+
with open('/tmp/pytest_results.json', 'r') as f:
|
|
874
|
+
results_data = json.load(f)
|
|
875
|
+
|
|
876
|
+
return {
|
|
877
|
+
'summary': results_data.get('summary', {}),
|
|
878
|
+
'tests': results_data.get('tests', []),
|
|
879
|
+
'passed': results_data.get('summary', {}).get('passed', 0),
|
|
880
|
+
'failed': results_data.get('summary', {}).get('failed', 0),
|
|
881
|
+
'skipped': results_data.get('summary', {}).get('skipped', 0),
|
|
882
|
+
'total': results_data.get('summary', {}).get('total', 0),
|
|
883
|
+
'duration': results_data.get('summary', {}).get('duration', 0)
|
|
884
|
+
}
|
|
885
|
+
except (FileNotFoundError, json.JSONDecodeError):
|
|
886
|
+
# Fallback to parsing stdout
|
|
887
|
+
return self._parse_pytest_output(result.stdout)
|
|
888
|
+
|
|
889
|
+
except Exception as e:
|
|
890
|
+
print(f"Error running pytest: {e}")
|
|
891
|
+
return {'error': str(e), 'passed': 0, 'failed': 0, 'skipped': 0, 'total': 0}
|
|
892
|
+
|
|
893
|
+
def _parse_pytest_output(self, output: str) -> Dict[str, Any]:
|
|
894
|
+
"""Parse pytest output when JSON is not available."""
|
|
895
|
+
|
|
896
|
+
lines = output.split('\n')
|
|
897
|
+
results = {'passed': 0, 'failed': 0, 'skipped': 0, 'total': 0, 'duration': 0}
|
|
898
|
+
|
|
899
|
+
for line in lines:
|
|
900
|
+
if ' passed in ' in line:
|
|
901
|
+
parts = line.split()
|
|
902
|
+
if parts and parts[0].isdigit():
|
|
903
|
+
results['passed'] = int(parts[0])
|
|
904
|
+
results['total'] = int(parts[0])
|
|
905
|
+
elif ' passed' in line and ' failed' in line:
|
|
906
|
+
# Parse format like "2 passed, 1 failed"
|
|
907
|
+
passed_part = line.split(' passed')[0]
|
|
908
|
+
if passed_part.strip().isdigit():
|
|
909
|
+
results['passed'] = int(passed_part.strip())
|
|
910
|
+
|
|
911
|
+
if ' failed' in line:
|
|
912
|
+
failed_part = line.split(' failed')[0].split(', ')[-1]
|
|
913
|
+
if failed_part.strip().isdigit():
|
|
914
|
+
results['failed'] = int(failed_part.strip())
|
|
915
|
+
|
|
916
|
+
results['total'] = results['passed'] + results['failed']
|
|
917
|
+
|
|
918
|
+
return results
|
|
919
|
+
|
|
920
|
+
def _determine_test_file_path(self, specification: TestSpecification) -> str:
|
|
921
|
+
"""Determine appropriate test file path based on specification."""
|
|
922
|
+
|
|
923
|
+
# Create tests directory structure
|
|
924
|
+
test_dir = "tests"
|
|
925
|
+
|
|
926
|
+
# Determine subdirectory based on test type
|
|
927
|
+
if specification.test_type == TestType.INTEGRATION:
|
|
928
|
+
test_dir += "/integration"
|
|
929
|
+
elif specification.test_type == TestType.ACCEPTANCE:
|
|
930
|
+
test_dir += "/acceptance"
|
|
931
|
+
elif specification.test_type == TestType.PERFORMANCE:
|
|
932
|
+
test_dir += "/performance"
|
|
933
|
+
|
|
934
|
+
# Generate filename
|
|
935
|
+
feature_name = specification.name.replace('test_', '').replace('_test', '')
|
|
936
|
+
filename = f"test_{feature_name}.py"
|
|
937
|
+
|
|
938
|
+
return f"{test_dir}/{filename}"
|
|
939
|
+
|
|
940
|
+
def _determine_implementation_file_path(self, function_name: str) -> str:
|
|
941
|
+
"""Determine implementation file path for target function."""
|
|
942
|
+
|
|
943
|
+
# Simple heuristic - place in src directory
|
|
944
|
+
# In real implementation, this would be more sophisticated
|
|
945
|
+
return f"src/{function_name}.py"
|
|
946
|
+
|
|
947
|
+
def _count_lines_in_file(self, file_path: str) -> int:
|
|
948
|
+
"""Count lines in a file."""
|
|
949
|
+
try:
|
|
950
|
+
with open(file_path, 'r', encoding='utf-8') as f:
|
|
951
|
+
return len(f.readlines())
|
|
952
|
+
except FileNotFoundError:
|
|
953
|
+
return 0
|
|
954
|
+
|
|
955
|
+
async def _generate_minimum_implementation(self, target_function: str) -> str:
|
|
956
|
+
"""Generate minimum implementation to make tests pass."""
|
|
957
|
+
|
|
958
|
+
# Get Context7 patterns for implementation
|
|
959
|
+
patterns = self.current_session.context7_patterns
|
|
960
|
+
|
|
961
|
+
# Simple implementation template
|
|
962
|
+
implementation = f'''
|
|
963
|
+
def {target_function}(*args, kwargs):
|
|
964
|
+
"""
|
|
965
|
+
Minimum implementation for {target_function}.
|
|
966
|
+
|
|
967
|
+
This is a TDD-generated implementation that will be
|
|
968
|
+
refined during the REFACTOR phase.
|
|
969
|
+
"""
|
|
970
|
+
# TODO: Implement proper logic based on test requirements
|
|
971
|
+
# This is a placeholder to make tests pass initially
|
|
972
|
+
|
|
973
|
+
if args:
|
|
974
|
+
return args[0] # Return first argument as default
|
|
975
|
+
|
|
976
|
+
return None # Default return value
|
|
977
|
+
'''
|
|
978
|
+
|
|
979
|
+
return implementation
|
|
980
|
+
|
|
981
|
+
async def _get_refactoring_patterns(self) -> Dict[str, Any]:
|
|
982
|
+
"""Get refactoring patterns from Context7."""
|
|
983
|
+
|
|
984
|
+
if self.context7:
|
|
985
|
+
try:
|
|
986
|
+
patterns = await self.context7.get_library_docs(
|
|
987
|
+
context7_library_id="/refactoring/guru",
|
|
988
|
+
topic="code refactoring patterns clean code 2025",
|
|
989
|
+
tokens=3000
|
|
990
|
+
)
|
|
991
|
+
return patterns
|
|
992
|
+
except Exception as e:
|
|
993
|
+
print(f"Failed to get refactoring patterns: {e}")
|
|
994
|
+
|
|
995
|
+
return {}
|
|
996
|
+
|
|
997
|
+
async def _generate_refactoring_suggestions(self, patterns: Dict[str, Any]) -> List[Dict[str, Any]]:
|
|
998
|
+
"""Generate refactoring suggestions based on current implementation."""
|
|
999
|
+
|
|
1000
|
+
suggestions = []
|
|
1001
|
+
|
|
1002
|
+
# Add general refactoring suggestions
|
|
1003
|
+
suggestions.extend([
|
|
1004
|
+
{
|
|
1005
|
+
'type': 'extract_method',
|
|
1006
|
+
'description': 'Extract complex logic into separate methods',
|
|
1007
|
+
'priority': 'medium',
|
|
1008
|
+
'applicable_to': ['large_functions']
|
|
1009
|
+
},
|
|
1010
|
+
{
|
|
1011
|
+
'type': 'improve_naming',
|
|
1012
|
+
'description': 'Improve variable and function naming for clarity',
|
|
1013
|
+
'priority': 'high',
|
|
1014
|
+
'applicable_to': ['all_functions']
|
|
1015
|
+
},
|
|
1016
|
+
{
|
|
1017
|
+
'type': 'add_documentation',
|
|
1018
|
+
'description': 'Add comprehensive docstrings and comments',
|
|
1019
|
+
'priority': 'medium',
|
|
1020
|
+
'applicable_to': ['all_functions']
|
|
1021
|
+
},
|
|
1022
|
+
{
|
|
1023
|
+
'type': 'handle_edge_cases',
|
|
1024
|
+
'description': 'Add proper error handling and edge case management',
|
|
1025
|
+
'priority': 'high',
|
|
1026
|
+
'applicable_to': ['public_functions']
|
|
1027
|
+
}
|
|
1028
|
+
])
|
|
1029
|
+
|
|
1030
|
+
return suggestions
|
|
1031
|
+
|
|
1032
|
+
async def _apply_refactoring_suggestion(self, suggestion: Dict[str, Any]) -> bool:
|
|
1033
|
+
"""Apply a refactoring suggestion to the codebase."""
|
|
1034
|
+
|
|
1035
|
+
# In a real implementation, this would analyze the code
|
|
1036
|
+
# and apply automated refactoring using tools like Rope
|
|
1037
|
+
|
|
1038
|
+
print(f"Applying refactoring: {suggestion['description']}")
|
|
1039
|
+
|
|
1040
|
+
# Simulate refactoring application
|
|
1041
|
+
await asyncio.sleep(0.1) # Simulate work
|
|
1042
|
+
|
|
1043
|
+
return True
|
|
1044
|
+
|
|
1045
|
+
async def _run_coverage_analysis(self) -> Dict[str, Any]:
|
|
1046
|
+
"""Run test coverage analysis."""
|
|
1047
|
+
|
|
1048
|
+
try:
|
|
1049
|
+
# Run coverage analysis
|
|
1050
|
+
result = subprocess.run(
|
|
1051
|
+
[
|
|
1052
|
+
sys.executable, '-m', 'pytest',
|
|
1053
|
+
str(self.project_path),
|
|
1054
|
+
'--cov=src',
|
|
1055
|
+
'--cov-report=json',
|
|
1056
|
+
'--cov-report=term-missing'
|
|
1057
|
+
],
|
|
1058
|
+
capture_output=True,
|
|
1059
|
+
text=True,
|
|
1060
|
+
cwd=str(self.project_path)
|
|
1061
|
+
)
|
|
1062
|
+
|
|
1063
|
+
# Parse coverage results
|
|
1064
|
+
try:
|
|
1065
|
+
# Look for coverage file
|
|
1066
|
+
import glob
|
|
1067
|
+
coverage_files = glob.glob(str(self.project_path) + '/coverage.json')
|
|
1068
|
+
if coverage_files:
|
|
1069
|
+
with open(coverage_files[0], 'r') as f:
|
|
1070
|
+
coverage_data = json.load(f)
|
|
1071
|
+
|
|
1072
|
+
total_coverage = coverage_data.get('totals', {}).get('percent_covered', 0)
|
|
1073
|
+
self.current_session.metrics['coverage_percentage'] = total_coverage
|
|
1074
|
+
|
|
1075
|
+
return {
|
|
1076
|
+
'total_coverage': total_coverage,
|
|
1077
|
+
'files': coverage_data.get('files', {}),
|
|
1078
|
+
'totals': coverage_data.get('totals', {})
|
|
1079
|
+
}
|
|
1080
|
+
except Exception:
|
|
1081
|
+
pass
|
|
1082
|
+
|
|
1083
|
+
return {'total_coverage': 0, 'message': 'Coverage analysis failed'}
|
|
1084
|
+
|
|
1085
|
+
except Exception as e:
|
|
1086
|
+
return {'error': str(e), 'total_coverage': 0}
|
|
1087
|
+
|
|
1088
|
+
def get_session_summary(self) -> Dict[str, Any]:
|
|
1089
|
+
"""Get summary of current TDD session."""
|
|
1090
|
+
|
|
1091
|
+
if not self.current_session:
|
|
1092
|
+
return {}
|
|
1093
|
+
|
|
1094
|
+
duration = time.time() - self.current_session.start_time
|
|
1095
|
+
|
|
1096
|
+
return {
|
|
1097
|
+
'session_id': self.current_session.id,
|
|
1098
|
+
'phase': self.current_session.current_phase.value,
|
|
1099
|
+
'duration_seconds': duration,
|
|
1100
|
+
'duration_formatted': f"{duration:.1f} seconds",
|
|
1101
|
+
'metrics': self.current_session.metrics,
|
|
1102
|
+
'test_cases_count': len(self.current_session.test_cases)
|
|
1103
|
+
}
|
|
1104
|
+
|
|
1105
|
+
# Usage Examples
|
|
1106
|
+
"""
|
|
1107
|
+
# Initialize TDD Manager
|
|
1108
|
+
tdd_manager = TDDManager(
|
|
1109
|
+
project_path="/path/to/project",
|
|
1110
|
+
context7_client=context7
|
|
1111
|
+
)
|
|
1112
|
+
|
|
1113
|
+
# Start TDD session
|
|
1114
|
+
session = await tdd_manager.start_tdd_session("user_authentication")
|
|
1115
|
+
|
|
1116
|
+
# Create test specification
|
|
1117
|
+
test_spec = TestSpecification(
|
|
1118
|
+
name="test_user_login_valid_credentials",
|
|
1119
|
+
description="Test that user can login with valid credentials",
|
|
1120
|
+
test_type=TestType.UNIT,
|
|
1121
|
+
requirements=[
|
|
1122
|
+
"User must provide valid email and password",
|
|
1123
|
+
"System should authenticate user credentials",
|
|
1124
|
+
"Successful login should return user token"
|
|
1125
|
+
],
|
|
1126
|
+
acceptance_criteria=[
|
|
1127
|
+
"Valid credentials return user token",
|
|
1128
|
+
"Invalid credentials raise AuthenticationError",
|
|
1129
|
+
"Empty credentials raise ValidationError"
|
|
1130
|
+
],
|
|
1131
|
+
edge_cases=[
|
|
1132
|
+
"Test with empty email",
|
|
1133
|
+
"Test with empty password",
|
|
1134
|
+
"Test with malformed email",
|
|
1135
|
+
"Test with very long password"
|
|
1136
|
+
],
|
|
1137
|
+
mock_requirements={
|
|
1138
|
+
"user_database": {"return_value": "mock_user"},
|
|
1139
|
+
"token_generator": {"return_value": "mock_token"}
|
|
1140
|
+
}
|
|
1141
|
+
)
|
|
1142
|
+
|
|
1143
|
+
# Run complete TDD cycle
|
|
1144
|
+
cycle_results = await tdd_manager.run_full_tdd_cycle(
|
|
1145
|
+
specification=test_spec,
|
|
1146
|
+
target_function="authenticate_user"
|
|
1147
|
+
)
|
|
1148
|
+
|
|
1149
|
+
print("TDD Cycle Results:")
|
|
1150
|
+
print(f" RED phase: Test written to {cycle_results['red']['test_file']}")
|
|
1151
|
+
print(f" GREEN phase: {cycle_results['green']['results']['passed']} tests passing")
|
|
1152
|
+
print(f" REFACTOR phase: {len(cycle_results['refactor']['suggestions'])} improvements made")
|
|
1153
|
+
print(f" REVIEW phase: {cycle_results['review']['coverage']['total_coverage']:.1f}% coverage")
|
|
1154
|
+
|
|
1155
|
+
# Get session summary
|
|
1156
|
+
summary = tdd_manager.get_session_summary()
|
|
1157
|
+
print(f"Session completed in {summary['duration_formatted']}")
|
|
1158
|
+
print(f"Final phase: {summary['phase']}")
|
|
1159
|
+
"""
|
|
1160
|
+
```
|
|
1161
|
+
|
|
1162
|
+
## Advanced Features
|
|
1163
|
+
|
|
1164
|
+
### Context7-Enhanced Test Generation
|
|
1165
|
+
|
|
1166
|
+
AI-Powered Test Case Generation:
|
|
1167
|
+
```python
|
|
1168
|
+
class EnhancedTestGenerator(TestGenerator):
|
|
1169
|
+
"""Enhanced test generator with advanced Context7 integration."""
|
|
1170
|
+
|
|
1171
|
+
async def generate_comprehensive_test_suite(
|
|
1172
|
+
self, function_code: str,
|
|
1173
|
+
context7_patterns: Dict[str, Any]
|
|
1174
|
+
) -> List[str]:
|
|
1175
|
+
"""Generate comprehensive test suite from function code."""
|
|
1176
|
+
|
|
1177
|
+
# Analyze function using AST
|
|
1178
|
+
function_analysis = self._analyze_function_code(function_code)
|
|
1179
|
+
|
|
1180
|
+
# Generate tests for different scenarios
|
|
1181
|
+
test_cases = []
|
|
1182
|
+
|
|
1183
|
+
# Happy path tests
|
|
1184
|
+
happy_path_tests = await self._generate_happy_path_tests(
|
|
1185
|
+
function_analysis, context7_patterns
|
|
1186
|
+
)
|
|
1187
|
+
test_cases.extend(happy_path_tests)
|
|
1188
|
+
|
|
1189
|
+
# Edge case tests
|
|
1190
|
+
edge_case_tests = await self._generate_edge_case_tests(
|
|
1191
|
+
function_analysis, context7_patterns
|
|
1192
|
+
)
|
|
1193
|
+
test_cases.extend(edge_case_tests)
|
|
1194
|
+
|
|
1195
|
+
# Error handling tests
|
|
1196
|
+
error_tests = await self._generate_error_handling_tests(
|
|
1197
|
+
function_analysis, context7_patterns
|
|
1198
|
+
)
|
|
1199
|
+
test_cases.extend(error_tests)
|
|
1200
|
+
|
|
1201
|
+
# Performance tests for critical functions
|
|
1202
|
+
if self._is_performance_critical(function_analysis):
|
|
1203
|
+
perf_tests = await self._generate_performance_tests(function_analysis)
|
|
1204
|
+
test_cases.extend(perf_tests)
|
|
1205
|
+
|
|
1206
|
+
return test_cases
|
|
1207
|
+
|
|
1208
|
+
def _analyze_function_code(self, code: str) -> Dict[str, Any]:
|
|
1209
|
+
"""Analyze function code to extract test requirements."""
|
|
1210
|
+
|
|
1211
|
+
try:
|
|
1212
|
+
tree = ast.parse(code)
|
|
1213
|
+
|
|
1214
|
+
analysis = {
|
|
1215
|
+
'functions': [],
|
|
1216
|
+
'parameters': [],
|
|
1217
|
+
'return_statements': [],
|
|
1218
|
+
'exceptions': [],
|
|
1219
|
+
'external_calls': []
|
|
1220
|
+
}
|
|
1221
|
+
|
|
1222
|
+
for node in ast.walk(tree):
|
|
1223
|
+
if isinstance(node, ast.FunctionDef):
|
|
1224
|
+
analysis['functions'].append({
|
|
1225
|
+
'name': node.name,
|
|
1226
|
+
'args': [arg.arg for arg in node.args.args],
|
|
1227
|
+
'decorators': [d.id if isinstance(d, ast.Name) else str(d) for d in node.decorator_list]
|
|
1228
|
+
})
|
|
1229
|
+
|
|
1230
|
+
elif isinstance(node, ast.Raise):
|
|
1231
|
+
analysis['exceptions'].append({
|
|
1232
|
+
'type': node.exc.func.id if node.exc and hasattr(node.exc, 'func') else 'Exception',
|
|
1233
|
+
'message': node.exc.msg if node.exc and hasattr(node.exc, 'msg') else None
|
|
1234
|
+
})
|
|
1235
|
+
|
|
1236
|
+
elif isinstance(node, ast.Call):
|
|
1237
|
+
if isinstance(node.func, ast.Attribute):
|
|
1238
|
+
analysis['external_calls'].append(f"{node.func.value.id}.{node.func.attr}")
|
|
1239
|
+
elif isinstance(node.func, ast.Name):
|
|
1240
|
+
analysis['external_calls'].append(node.func.id)
|
|
1241
|
+
|
|
1242
|
+
return analysis
|
|
1243
|
+
|
|
1244
|
+
except Exception as e:
|
|
1245
|
+
print(f"Error analyzing function code: {e}")
|
|
1246
|
+
return {}
|
|
1247
|
+
```
|
|
1248
|
+
|
|
1249
|
+
## Best Practices
|
|
1250
|
+
|
|
1251
|
+
1. RED Phase: Always write failing tests first, ensure they fail for the right reason
|
|
1252
|
+
2. GREEN Phase: Write minimum code to pass tests, avoid premature optimization
|
|
1253
|
+
3. REFACTOR Phase: Improve design while keeping tests green, apply small incremental changes
|
|
1254
|
+
4. Test Coverage: Aim for high coverage but focus on meaningful tests
|
|
1255
|
+
5. Context Integration: Leverage Context7 patterns for industry-standard testing approaches
|
|
1256
|
+
|
|
1257
|
+
---
|
|
1258
|
+
|
|
1259
|
+
Module: `modules/tdd-context7.md`
|
|
1260
|
+
Related: [AI Debugging](./ai-debugging.md) | [Performance Optimization](./performance-optimization.md)
|