Files
claude-skills-reference/engineering-team/tdd-guide/framework_adapter.py
Reza Rezvani 93e750a018 docs(skills): add 6 new undocumented skills and update all documentation
Pre-Sprint Task: Complete documentation audit and updates before starting
sprint-11-06-2025 (Orchestrator Framework).

## New Skills Added (6 total)

### Marketing Skills (2 new)
- app-store-optimization: 8 Python tools for ASO (App Store + Google Play)
  - keyword_analyzer.py, aso_scorer.py, metadata_optimizer.py
  - competitor_analyzer.py, ab_test_planner.py, review_analyzer.py
  - localization_helper.py, launch_checklist.py
- social-media-analyzer: 2 Python tools for social analytics
  - analyze_performance.py, calculate_metrics.py

### Engineering Skills (4 new)
- aws-solution-architect: 3 Python tools for AWS architecture
  - architecture_designer.py, serverless_stack.py, cost_optimizer.py
- ms365-tenant-manager: 3 Python tools for M365 administration
  - tenant_setup.py, user_management.py, powershell_generator.py
- tdd-guide: 8 Python tools for test-driven development
  - coverage_analyzer.py, test_generator.py, tdd_workflow.py
  - metrics_calculator.py, framework_adapter.py, fixture_generator.py
  - format_detector.py, output_formatter.py
- tech-stack-evaluator: 7 Python tools for technology evaluation
  - stack_comparator.py, tco_calculator.py, migration_analyzer.py
  - security_assessor.py, ecosystem_analyzer.py, report_generator.py
  - format_detector.py

## Documentation Updates

### README.md (154+ line changes)
- Updated skill counts: 42 → 48 skills
- Added marketing skills: 3 → 5 (app-store-optimization, social-media-analyzer)
- Added engineering skills: 9 → 13 core engineering skills
- Updated Python tools count: 97 → 68+ (corrected overcount)
- Updated ROI metrics:
  - Marketing teams: 250 → 310 hours/month saved
  - Core engineering: 460 → 580 hours/month saved
  - Total: 1,720 → 1,900 hours/month saved
  - Annual ROI: $20.8M → $21.0M per organization
- Updated projected impact table (48 current → 55+ target)

### CLAUDE.md (14 line changes)
- Updated scope: 42 → 48 skills, 97 → 68+ tools
- Updated repository structure comments
- Updated Phase 1 summary: Marketing (3→5), Engineering (14→18)
- Updated status: 42 → 48 skills deployed

### documentation/PYTHON_TOOLS_AUDIT.md (197+ line changes)
- Updated audit date: October 21 → November 7, 2025
- Updated skill counts: 43 → 48 total skills
- Updated tool counts: 69 → 81+ scripts
- Added comprehensive "NEW SKILLS DISCOVERED" sections
- Documented all 6 new skills with tool details
- Resolved "Issue 3: Undocumented Skills" (marked as RESOLVED)
- Updated production tool counts: 18-20 → 29-31 confirmed
- Added audit change log with November 7 update
- Corrected discrepancy explanation (97 claimed → 68-70 actual)

### documentation/GROWTH_STRATEGY.md (NEW - 600+ lines)
- Part 1: Adding New Skills (step-by-step process)
- Part 2: Enhancing Agents with New Skills
- Part 3: Agent-Skill Mapping Maintenance
- Part 4: Version Control & Compatibility
- Part 5: Quality Assurance Framework
- Part 6: Growth Projections & Resource Planning
- Part 7: Orchestrator Integration Strategy
- Part 8: Community Contribution Process
- Part 9: Monitoring & Analytics
- Part 10: Risk Management & Mitigation
- Appendix A: Templates (skill proposal, agent enhancement)
- Appendix B: Automation Scripts (validation, doc checker)

## Metrics Summary

**Before:**
- 42 skills documented
- 97 Python tools claimed
- Marketing: 3 skills
- Engineering: 9 core skills

**After:**
- 48 skills documented (+6)
- 68+ Python tools actual (corrected overcount)
- Marketing: 5 skills (+2)
- Engineering: 13 core skills (+4)
- Time savings: 1,900 hours/month (+180 hours)
- Annual ROI: $21.0M per org (+$200K)

## Quality Checklist

- [x] Skills audit completed across 4 folders
- [x] All 6 new skills have complete SKILL.md documentation
- [x] README.md updated with detailed skill descriptions
- [x] CLAUDE.md updated with accurate counts
- [x] PYTHON_TOOLS_AUDIT.md updated with new findings
- [x] GROWTH_STRATEGY.md created for systematic additions
- [x] All skill counts verified and corrected
- [x] ROI metrics recalculated
- [x] Conventional commit standards followed

## Next Steps

1. Review and approve this pre-sprint documentation update
2. Begin sprint-11-06-2025 (Orchestrator Framework)
3. Use GROWTH_STRATEGY.md for future skill additions
4. Verify engineering core/AI-ML tools (future task)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-07 10:08:08 +01:00

429 lines
14 KiB
Python

"""
Framework adapter module.
Provides multi-framework support with adapters for Jest, Pytest, JUnit, Vitest, and more.
Handles framework-specific patterns, imports, and test structure.
"""
from typing import Dict, List, Any, Optional
from enum import Enum
class Framework(Enum):
"""Supported testing frameworks."""
JEST = "jest"
VITEST = "vitest"
PYTEST = "pytest"
UNITTEST = "unittest"
JUNIT = "junit"
TESTNG = "testng"
MOCHA = "mocha"
JASMINE = "jasmine"
class Language(Enum):
"""Supported programming languages."""
TYPESCRIPT = "typescript"
JAVASCRIPT = "javascript"
PYTHON = "python"
JAVA = "java"
class FrameworkAdapter:
"""Adapter for multiple testing frameworks."""
def __init__(self, framework: Framework, language: Language):
"""
Initialize framework adapter.
Args:
framework: Testing framework
language: Programming language
"""
self.framework = framework
self.language = language
def generate_imports(self) -> str:
"""Generate framework-specific imports."""
if self.framework == Framework.JEST:
return self._jest_imports()
elif self.framework == Framework.VITEST:
return self._vitest_imports()
elif self.framework == Framework.PYTEST:
return self._pytest_imports()
elif self.framework == Framework.UNITTEST:
return self._unittest_imports()
elif self.framework == Framework.JUNIT:
return self._junit_imports()
elif self.framework == Framework.TESTNG:
return self._testng_imports()
elif self.framework == Framework.MOCHA:
return self._mocha_imports()
else:
return ""
def _jest_imports(self) -> str:
"""Generate Jest imports."""
return """import { describe, it, expect, beforeEach, afterEach } from '@jest/globals';"""
def _vitest_imports(self) -> str:
"""Generate Vitest imports."""
return """import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest';"""
def _pytest_imports(self) -> str:
"""Generate Pytest imports."""
return """import pytest"""
def _unittest_imports(self) -> str:
"""Generate unittest imports."""
return """import unittest"""
def _junit_imports(self) -> str:
"""Generate JUnit imports."""
return """import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.AfterEach;
import static org.junit.jupiter.api.Assertions.*;"""
def _testng_imports(self) -> str:
"""Generate TestNG imports."""
return """import org.testng.annotations.Test;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.AfterMethod;
import static org.testng.Assert.*;"""
def _mocha_imports(self) -> str:
"""Generate Mocha imports."""
return """import { describe, it, beforeEach, afterEach } from 'mocha';
import { expect } from 'chai';"""
def generate_test_suite_wrapper(
self,
suite_name: str,
test_content: str
) -> str:
"""
Wrap test content in framework-specific suite structure.
Args:
suite_name: Name of test suite
test_content: Test functions/methods
Returns:
Complete test suite code
"""
if self.framework in [Framework.JEST, Framework.VITEST, Framework.MOCHA]:
return f"""describe('{suite_name}', () => {{
{self._indent(test_content, 2)}
}});"""
elif self.framework == Framework.PYTEST:
return f"""class Test{self._to_class_name(suite_name)}:
\"\"\"Test suite for {suite_name}.\"\"\"
{self._indent(test_content, 4)}"""
elif self.framework == Framework.UNITTEST:
return f"""class Test{self._to_class_name(suite_name)}(unittest.TestCase):
\"\"\"Test suite for {suite_name}.\"\"\"
{self._indent(test_content, 4)}"""
elif self.framework in [Framework.JUNIT, Framework.TESTNG]:
return f"""public class {self._to_class_name(suite_name)}Test {{
{self._indent(test_content, 4)}
}}"""
return test_content
def generate_test_function(
self,
test_name: str,
test_body: str,
description: str = ""
) -> str:
"""
Generate framework-specific test function.
Args:
test_name: Name of test
test_body: Test body code
description: Test description
Returns:
Complete test function
"""
if self.framework == Framework.JEST:
return self._jest_test(test_name, test_body, description)
elif self.framework == Framework.VITEST:
return self._vitest_test(test_name, test_body, description)
elif self.framework == Framework.PYTEST:
return self._pytest_test(test_name, test_body, description)
elif self.framework == Framework.UNITTEST:
return self._unittest_test(test_name, test_body, description)
elif self.framework == Framework.JUNIT:
return self._junit_test(test_name, test_body, description)
elif self.framework == Framework.TESTNG:
return self._testng_test(test_name, test_body, description)
elif self.framework == Framework.MOCHA:
return self._mocha_test(test_name, test_body, description)
else:
return ""
def _jest_test(self, test_name: str, test_body: str, description: str) -> str:
"""Generate Jest test."""
return f"""it('{test_name}', () => {{
// {description}
{self._indent(test_body, 2)}
}});"""
def _vitest_test(self, test_name: str, test_body: str, description: str) -> str:
"""Generate Vitest test."""
return f"""it('{test_name}', () => {{
// {description}
{self._indent(test_body, 2)}
}});"""
def _pytest_test(self, test_name: str, test_body: str, description: str) -> str:
"""Generate Pytest test."""
func_name = test_name.replace(' ', '_').replace('-', '_')
return f"""def test_{func_name}(self):
\"\"\"
{description or test_name}
\"\"\"
{self._indent(test_body, 4)}"""
def _unittest_test(self, test_name: str, test_body: str, description: str) -> str:
"""Generate unittest test."""
func_name = self._to_camel_case(test_name)
return f"""def test_{func_name}(self):
\"\"\"
{description or test_name}
\"\"\"
{self._indent(test_body, 4)}"""
def _junit_test(self, test_name: str, test_body: str, description: str) -> str:
"""Generate JUnit test."""
method_name = self._to_camel_case(test_name)
return f"""@Test
public void test{method_name}() {{
// {description}
{self._indent(test_body, 4)}
}}"""
def _testng_test(self, test_name: str, test_body: str, description: str) -> str:
"""Generate TestNG test."""
method_name = self._to_camel_case(test_name)
return f"""@Test
public void test{method_name}() {{
// {description}
{self._indent(test_body, 4)}
}}"""
def _mocha_test(self, test_name: str, test_body: str, description: str) -> str:
"""Generate Mocha test."""
return f"""it('{test_name}', () => {{
// {description}
{self._indent(test_body, 2)}
}});"""
def generate_assertion(
self,
actual: str,
expected: str,
assertion_type: str = "equals"
) -> str:
"""
Generate framework-specific assertion.
Args:
actual: Actual value expression
expected: Expected value expression
assertion_type: Type of assertion (equals, not_equals, true, false, throws)
Returns:
Assertion statement
"""
if self.framework in [Framework.JEST, Framework.VITEST]:
return self._jest_assertion(actual, expected, assertion_type)
elif self.framework in [Framework.PYTEST, Framework.UNITTEST]:
return self._python_assertion(actual, expected, assertion_type)
elif self.framework in [Framework.JUNIT, Framework.TESTNG]:
return self._java_assertion(actual, expected, assertion_type)
elif self.framework == Framework.MOCHA:
return self._chai_assertion(actual, expected, assertion_type)
else:
return f"assert {actual} == {expected}"
def _jest_assertion(self, actual: str, expected: str, assertion_type: str) -> str:
"""Generate Jest assertion."""
if assertion_type == "equals":
return f"expect({actual}).toBe({expected});"
elif assertion_type == "not_equals":
return f"expect({actual}).not.toBe({expected});"
elif assertion_type == "true":
return f"expect({actual}).toBe(true);"
elif assertion_type == "false":
return f"expect({actual}).toBe(false);"
elif assertion_type == "throws":
return f"expect(() => {actual}).toThrow();"
else:
return f"expect({actual}).toBe({expected});"
def _python_assertion(self, actual: str, expected: str, assertion_type: str) -> str:
"""Generate Python assertion."""
if assertion_type == "equals":
return f"assert {actual} == {expected}"
elif assertion_type == "not_equals":
return f"assert {actual} != {expected}"
elif assertion_type == "true":
return f"assert {actual} is True"
elif assertion_type == "false":
return f"assert {actual} is False"
elif assertion_type == "throws":
return f"with pytest.raises(Exception):\n {actual}"
else:
return f"assert {actual} == {expected}"
def _java_assertion(self, actual: str, expected: str, assertion_type: str) -> str:
"""Generate Java assertion."""
if assertion_type == "equals":
return f"assertEquals({expected}, {actual});"
elif assertion_type == "not_equals":
return f"assertNotEquals({expected}, {actual});"
elif assertion_type == "true":
return f"assertTrue({actual});"
elif assertion_type == "false":
return f"assertFalse({actual});"
elif assertion_type == "throws":
return f"assertThrows(Exception.class, () -> {actual});"
else:
return f"assertEquals({expected}, {actual});"
def _chai_assertion(self, actual: str, expected: str, assertion_type: str) -> str:
"""Generate Chai assertion."""
if assertion_type == "equals":
return f"expect({actual}).to.equal({expected});"
elif assertion_type == "not_equals":
return f"expect({actual}).to.not.equal({expected});"
elif assertion_type == "true":
return f"expect({actual}).to.be.true;"
elif assertion_type == "false":
return f"expect({actual}).to.be.false;"
elif assertion_type == "throws":
return f"expect(() => {actual}).to.throw();"
else:
return f"expect({actual}).to.equal({expected});"
def generate_setup_teardown(
self,
setup_code: str = "",
teardown_code: str = ""
) -> str:
"""Generate setup and teardown hooks."""
result = []
if self.framework in [Framework.JEST, Framework.VITEST, Framework.MOCHA]:
if setup_code:
result.append(f"""beforeEach(() => {{
{self._indent(setup_code, 2)}
}});""")
if teardown_code:
result.append(f"""afterEach(() => {{
{self._indent(teardown_code, 2)}
}});""")
elif self.framework == Framework.PYTEST:
if setup_code:
result.append(f"""@pytest.fixture(autouse=True)
def setup_method(self):
{self._indent(setup_code, 4)}
yield""")
if teardown_code:
result.append(f"""
{self._indent(teardown_code, 4)}""")
elif self.framework == Framework.UNITTEST:
if setup_code:
result.append(f"""def setUp(self):
{self._indent(setup_code, 4)}""")
if teardown_code:
result.append(f"""def tearDown(self):
{self._indent(teardown_code, 4)}""")
elif self.framework in [Framework.JUNIT, Framework.TESTNG]:
annotation = "@BeforeEach" if self.framework == Framework.JUNIT else "@BeforeMethod"
if setup_code:
result.append(f"""{annotation}
public void setUp() {{
{self._indent(setup_code, 4)}
}}""")
annotation = "@AfterEach" if self.framework == Framework.JUNIT else "@AfterMethod"
if teardown_code:
result.append(f"""{annotation}
public void tearDown() {{
{self._indent(teardown_code, 4)}
}}""")
return "\n\n".join(result)
def _indent(self, text: str, spaces: int) -> str:
"""Indent text by number of spaces."""
indent = " " * spaces
lines = text.split('\n')
return '\n'.join(indent + line if line.strip() else line for line in lines)
def _to_camel_case(self, text: str) -> str:
"""Convert text to camelCase."""
words = text.replace('-', ' ').replace('_', ' ').split()
if not words:
return text
return words[0].lower() + ''.join(word.capitalize() for word in words[1:])
def _to_class_name(self, text: str) -> str:
"""Convert text to ClassName."""
words = text.replace('-', ' ').replace('_', ' ').split()
return ''.join(word.capitalize() for word in words)
def detect_framework(self, code: str) -> Optional[Framework]:
"""
Auto-detect testing framework from code.
Args:
code: Test code
Returns:
Detected framework or None
"""
# Jest patterns
if 'from \'@jest/globals\'' in code or '@jest/' in code:
return Framework.JEST
# Vitest patterns
if 'from \'vitest\'' in code or 'import { vi }' in code:
return Framework.VITEST
# Pytest patterns
if 'import pytest' in code or 'def test_' in code and 'pytest.fixture' in code:
return Framework.PYTEST
# Unittest patterns
if 'import unittest' in code and 'unittest.TestCase' in code:
return Framework.UNITTEST
# JUnit patterns
if '@Test' in code and 'import org.junit' in code:
return Framework.JUNIT
# TestNG patterns
if '@Test' in code and 'import org.testng' in code:
return Framework.TESTNG
# Mocha patterns
if 'from \'mocha\'' in code or ('describe(' in code and 'from \'chai\'' in code):
return Framework.MOCHA
return None