TDD Guide The agent guides red-green-refactor TDD workflows, generates framework-specific test stubs from requirements, parses coverage reports to identify prioritized gaps, and calculates test quality metrics including smell detection and assertion density. Supports Jest, Pytest, JUnit, Vitest, and Mocha. Quick Start --- Core Workflows Workflow 1: TDD a New Feature 1. Write a failing test for the feature requirement (RED phase) 2. Call -- confirms test exists and fails 3. Write minimal code to make the test pass (GREEN phase) 4. Call -- confirms all tests pass 5. Refactor while keeping tests…

, # Python comments\n r':\\s*

TDD Guide The agent guides red-green-refactor TDD workflows, generates framework-specific test stubs from requirements, parses coverage reports to identify prioritized gaps, and calculates test quality metrics including smell detection and assertion density. Supports Jest, Pytest, JUnit, Vitest, and Mocha. Quick Start --- Core Workflows Workflow 1: TDD a New Feature 1. Write a failing test for the feature requirement (RED phase) 2. Call -- confirms test exists and fails 3. Write minimal code to make the test pass (GREEN phase) 4. Call -- confirms all tests pass 5. Refactor while keeping tests…

, # Python colons\n ]\n\n matches = sum(1 for pattern in py_patterns if re.search(pattern, code, re.MULTILINE))\n return matches >= 3\n\n def _is_java(self, code: str) -> bool:\n \"\"\"Check if code is Java.\"\"\"\n java_patterns = [\n r'\\bpublic\\s+class', # public class\n r'\\bprivate\\s+\\w+', # private members\n r'\\bpublic\\s+\\w+\\s+\\w+\\s*\\(', # public methods\n r'import\\s+java\\.', # Java imports\n r'\\bvoid\\s+\\w+\\s*\\(', # void methods\n ]\n\n matches = sum(1 for pattern in java_patterns if re.search(pattern, code))\n return matches >= 2\n\n def detect_test_framework(self, code: str) -> str:\n \"\"\"\n Detect testing framework from test code.\n\n Args:\n code: Test code\n\n Returns:\n Detected framework (jest, vitest, pytest, junit, mocha, unknown)\n \"\"\"\n # Jest patterns\n if 'from \\'@jest/globals\\'' in code or '@jest/' in code:\n self.detected_framework = \"jest\"\n return \"jest\"\n\n # Vitest patterns\n if 'from \\'vitest\\'' in code or 'import { vi }' in code:\n self.detected_framework = \"vitest\"\n return \"vitest\"\n\n # Pytest patterns\n if 'import pytest' in code or 'def test_' in code:\n self.detected_framework = \"pytest\"\n return \"pytest\"\n\n # Unittest patterns\n if 'import unittest' in code and 'unittest.TestCase' in code:\n self.detected_framework = \"unittest\"\n return \"unittest\"\n\n # JUnit patterns\n if '@Test' in code and 'import org.junit' in code:\n self.detected_framework = \"junit\"\n return \"junit\"\n\n # Mocha patterns\n if 'describe(' in code and 'it(' in code:\n self.detected_framework = \"mocha\"\n return \"mocha\"\n\n self.detected_framework = \"unknown\"\n return \"unknown\"\n\n def detect_coverage_format(self, content: str) -> str:\n \"\"\"\n Detect coverage report format.\n\n Args:\n content: Coverage report content\n\n Returns:\n Format type (lcov, json, xml, unknown)\n \"\"\"\n content_stripped = content.strip()\n\n # LCOV format\n if content_stripped.startswith('TN:') or 'SF:' in content_stripped[:200]:\n return \"lcov\"\n\n # JSON format\n if content_stripped.startswith('{'):\n try:\n import json\n json.loads(content_stripped)\n return \"json\"\n except:\n pass\n\n # XML format\n if content_stripped.startswith('\u003c?xml') or content_stripped.startswith('\u003ccoverage'):\n return \"xml\"\n\n return \"unknown\"\n\n def detect_input_format(self, input_data: str) -> Dict[str, Any]:\n \"\"\"\n Detect input format and extract relevant information.\n\n Args:\n input_data: Input data (could be code, coverage report, etc.)\n\n Returns:\n Detection results with format, language, framework\n \"\"\"\n result = {\n 'format': 'unknown',\n 'language': 'unknown',\n 'framework': 'unknown',\n 'content_type': 'unknown'\n }\n\n # Detect if it's a coverage report\n coverage_format = self.detect_coverage_format(input_data)\n if coverage_format != \"unknown\":\n result['format'] = coverage_format\n result['content_type'] = 'coverage_report'\n return result\n\n # Detect if it's source code\n language = self.detect_language(input_data)\n if language != \"unknown\":\n result['language'] = language\n result['content_type'] = 'source_code'\n\n # Detect if it's test code\n framework = self.detect_test_framework(input_data)\n if framework != \"unknown\":\n result['framework'] = framework\n result['content_type'] = 'test_code'\n\n return result\n\n def extract_file_info(self, file_path: str) -> Dict[str, str]:\n \"\"\"\n Extract information from file path.\n\n Args:\n file_path: Path to file\n\n Returns:\n File information (extension, likely language, likely purpose)\n \"\"\"\n import os\n\n file_name = os.path.basename(file_path)\n file_ext = os.path.splitext(file_name)[1].lower()\n\n # Extension to language mapping\n ext_to_lang = {\n '.ts': 'typescript',\n '.tsx': 'typescript',\n '.js': 'javascript',\n '.jsx': 'javascript',\n '.py': 'python',\n '.java': 'java',\n '.kt': 'kotlin',\n '.go': 'go',\n '.rs': 'rust',\n }\n\n # Test file patterns\n is_test = any(pattern in file_name.lower()\n for pattern in ['test', 'spec', '_test.', '.test.'])\n\n return {\n 'file_name': file_name,\n 'extension': file_ext,\n 'language': ext_to_lang.get(file_ext, 'unknown'),\n 'is_test': is_test,\n 'purpose': 'test' if is_test else 'source'\n }\n\n def suggest_test_file_name(self, source_file: str, framework: str) -> str:\n \"\"\"\n Suggest test file name for source file.\n\n Args:\n source_file: Source file path\n framework: Testing framework\n\n Returns:\n Suggested test file name\n \"\"\"\n import os\n\n base_name = os.path.splitext(os.path.basename(source_file))[0]\n ext = os.path.splitext(source_file)[1]\n\n if framework in ['jest', 'vitest', 'mocha']:\n return f\"{base_name}.test{ext}\"\n elif framework in ['pytest', 'unittest']:\n return f\"test_{base_name}.py\"\n elif framework in ['junit', 'testng']:\n return f\"{base_name.capitalize()}Test.java\"\n else:\n return f\"{base_name}_test{ext}\"\n\n def identify_test_patterns(self, code: str) -> List[str]:\n \"\"\"\n Identify test patterns in code.\n\n Args:\n code: Test code\n\n Returns:\n List of identified patterns (AAA, Given-When-Then, etc.)\n \"\"\"\n patterns = []\n\n # Arrange-Act-Assert pattern\n if any(comment in code.lower() for comment in ['// arrange', '# arrange', '// act', '# act']):\n patterns.append('AAA (Arrange-Act-Assert)')\n\n # Given-When-Then pattern\n if any(comment in code.lower() for comment in ['given', 'when', 'then']):\n patterns.append('Given-When-Then')\n\n # Setup/Teardown pattern\n if any(keyword in code for keyword in ['beforeEach', 'afterEach', 'setUp', 'tearDown']):\n patterns.append('Setup-Teardown')\n\n # Mocking pattern\n if any(keyword in code.lower() for keyword in ['mock', 'stub', 'spy']):\n patterns.append('Mocking/Stubbing')\n\n # Parameterized tests\n if any(keyword in code for keyword in ['@pytest.mark.parametrize', 'test.each', '@ParameterizedTest']):\n patterns.append('Parameterized Tests')\n\n return patterns if patterns else ['No specific pattern detected']\n\n def analyze_project_structure(self, file_paths: List[str]) -> Dict[str, Any]:\n \"\"\"\n Analyze project structure from file paths.\n\n Args:\n file_paths: List of file paths in project\n\n Returns:\n Project structure analysis\n \"\"\"\n languages = {}\n test_frameworks = []\n source_files = []\n test_files = []\n\n for file_path in file_paths:\n file_info = self.extract_file_info(file_path)\n\n # Count languages\n lang = file_info['language']\n if lang != 'unknown':\n languages[lang] = languages.get(lang, 0) + 1\n\n # Categorize files\n if file_info['is_test']:\n test_files.append(file_path)\n else:\n source_files.append(file_path)\n\n # Determine primary language\n primary_language = max(languages.items(), key=lambda x: x[1])[0] if languages else 'unknown'\n\n return {\n 'primary_language': primary_language,\n 'languages': languages,\n 'source_file_count': len(source_files),\n 'test_file_count': len(test_files),\n 'test_ratio': len(test_files) / len(source_files) if source_files else 0,\n 'suggested_framework': self._suggest_framework(primary_language)\n }\n\n def _suggest_framework(self, language: str) -> str:\n \"\"\"Suggest testing framework based on language.\"\"\"\n framework_map = {\n 'typescript': 'jest or vitest',\n 'javascript': 'jest or mocha',\n 'python': 'pytest',\n 'java': 'junit',\n 'kotlin': 'junit',\n 'go': 'testing package',\n 'rust': 'cargo test',\n }\n\n return framework_map.get(language, 'unknown')\n\n def detect_environment(self) -> Dict[str, str]:\n \"\"\"\n Detect execution environment (CLI, Desktop, API).\n\n Returns:\n Environment information\n \"\"\"\n # This is a placeholder - actual detection would use environment variables\n # or other runtime checks\n return {\n 'environment': 'cli', # Could be 'desktop', 'api'\n 'output_preference': 'terminal-friendly' # Could be 'rich-markdown', 'json'\n }\n","content_type":"text/x-python; charset=utf-8","language":"python","size":12207,"content_sha256":"a12f1d016967fc0a8a3b3f68b28a172494c33c9252d72d662c7a37f765a6692d"},{"filename":"scripts/framework_adapter.py","content":"\"\"\"\nFramework adapter module.\n\nProvides multi-framework support with adapters for Jest, Pytest, JUnit, Vitest, and more.\nHandles framework-specific patterns, imports, and test structure.\n\"\"\"\n\nfrom typing import Dict, List, Any, Optional\nfrom enum import Enum\n\n\nclass Framework(Enum):\n \"\"\"Supported testing frameworks.\"\"\"\n JEST = \"jest\"\n VITEST = \"vitest\"\n PYTEST = \"pytest\"\n UNITTEST = \"unittest\"\n JUNIT = \"junit\"\n TESTNG = \"testng\"\n MOCHA = \"mocha\"\n JASMINE = \"jasmine\"\n\n\nclass Language(Enum):\n \"\"\"Supported programming languages.\"\"\"\n TYPESCRIPT = \"typescript\"\n JAVASCRIPT = \"javascript\"\n PYTHON = \"python\"\n JAVA = \"java\"\n\n\nclass FrameworkAdapter:\n \"\"\"Adapter for multiple testing frameworks.\"\"\"\n\n def __init__(self, framework: Framework, language: Language):\n \"\"\"\n Initialize framework adapter.\n\n Args:\n framework: Testing framework\n language: Programming language\n \"\"\"\n self.framework = framework\n self.language = language\n\n def generate_imports(self) -> str:\n \"\"\"Generate framework-specific imports.\"\"\"\n if self.framework == Framework.JEST:\n return self._jest_imports()\n elif self.framework == Framework.VITEST:\n return self._vitest_imports()\n elif self.framework == Framework.PYTEST:\n return self._pytest_imports()\n elif self.framework == Framework.UNITTEST:\n return self._unittest_imports()\n elif self.framework == Framework.JUNIT:\n return self._junit_imports()\n elif self.framework == Framework.TESTNG:\n return self._testng_imports()\n elif self.framework == Framework.MOCHA:\n return self._mocha_imports()\n else:\n return \"\"\n\n def _jest_imports(self) -> str:\n \"\"\"Generate Jest imports.\"\"\"\n return \"\"\"import { describe, it, expect, beforeEach, afterEach } from '@jest/globals';\"\"\"\n\n def _vitest_imports(self) -> str:\n \"\"\"Generate Vitest imports.\"\"\"\n return \"\"\"import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest';\"\"\"\n\n def _pytest_imports(self) -> str:\n \"\"\"Generate Pytest imports.\"\"\"\n return \"\"\"import pytest\"\"\"\n\n def _unittest_imports(self) -> str:\n \"\"\"Generate unittest imports.\"\"\"\n return \"\"\"import unittest\"\"\"\n\n def _junit_imports(self) -> str:\n \"\"\"Generate JUnit imports.\"\"\"\n return \"\"\"import org.junit.jupiter.api.Test;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.AfterEach;\nimport static org.junit.jupiter.api.Assertions.*;\"\"\"\n\n def _testng_imports(self) -> str:\n \"\"\"Generate TestNG imports.\"\"\"\n return \"\"\"import org.testng.annotations.Test;\nimport org.testng.annotations.BeforeMethod;\nimport org.testng.annotations.AfterMethod;\nimport static org.testng.Assert.*;\"\"\"\n\n def _mocha_imports(self) -> str:\n \"\"\"Generate Mocha imports.\"\"\"\n return \"\"\"import { describe, it, beforeEach, afterEach } from 'mocha';\nimport { expect } from 'chai';\"\"\"\n\n def generate_test_suite_wrapper(\n self,\n suite_name: str,\n test_content: str\n ) -> str:\n \"\"\"\n Wrap test content in framework-specific suite structure.\n\n Args:\n suite_name: Name of test suite\n test_content: Test functions/methods\n\n Returns:\n Complete test suite code\n \"\"\"\n if self.framework in [Framework.JEST, Framework.VITEST, Framework.MOCHA]:\n return f\"\"\"describe('{suite_name}', () => {{\n{self._indent(test_content, 2)}\n}});\"\"\"\n\n elif self.framework == Framework.PYTEST:\n return f\"\"\"class Test{self._to_class_name(suite_name)}:\n \\\"\\\"\\\"Test suite for {suite_name}.\\\"\\\"\\\"\n\n{self._indent(test_content, 4)}\"\"\"\n\n elif self.framework == Framework.UNITTEST:\n return f\"\"\"class Test{self._to_class_name(suite_name)}(unittest.TestCase):\n \\\"\\\"\\\"Test suite for {suite_name}.\\\"\\\"\\\"\n\n{self._indent(test_content, 4)}\"\"\"\n\n elif self.framework in [Framework.JUNIT, Framework.TESTNG]:\n return f\"\"\"public class {self._to_class_name(suite_name)}Test {{\n\n{self._indent(test_content, 4)}\n}}\"\"\"\n\n return test_content\n\n def generate_test_function(\n self,\n test_name: str,\n test_body: str,\n description: str = \"\"\n ) -> str:\n \"\"\"\n Generate framework-specific test function.\n\n Args:\n test_name: Name of test\n test_body: Test body code\n description: Test description\n\n Returns:\n Complete test function\n \"\"\"\n if self.framework == Framework.JEST:\n return self._jest_test(test_name, test_body, description)\n elif self.framework == Framework.VITEST:\n return self._vitest_test(test_name, test_body, description)\n elif self.framework == Framework.PYTEST:\n return self._pytest_test(test_name, test_body, description)\n elif self.framework == Framework.UNITTEST:\n return self._unittest_test(test_name, test_body, description)\n elif self.framework == Framework.JUNIT:\n return self._junit_test(test_name, test_body, description)\n elif self.framework == Framework.TESTNG:\n return self._testng_test(test_name, test_body, description)\n elif self.framework == Framework.MOCHA:\n return self._mocha_test(test_name, test_body, description)\n else:\n return \"\"\n\n def _jest_test(self, test_name: str, test_body: str, description: str) -> str:\n \"\"\"Generate Jest test.\"\"\"\n return f\"\"\"it('{test_name}', () => {{\n // {description}\n{self._indent(test_body, 2)}\n}});\"\"\"\n\n def _vitest_test(self, test_name: str, test_body: str, description: str) -> str:\n \"\"\"Generate Vitest test.\"\"\"\n return f\"\"\"it('{test_name}', () => {{\n // {description}\n{self._indent(test_body, 2)}\n}});\"\"\"\n\n def _pytest_test(self, test_name: str, test_body: str, description: str) -> str:\n \"\"\"Generate Pytest test.\"\"\"\n func_name = test_name.replace(' ', '_').replace('-', '_')\n return f\"\"\"def test_{func_name}(self):\n \\\"\\\"\\\"\n {description or test_name}\n \\\"\\\"\\\"\n{self._indent(test_body, 4)}\"\"\"\n\n def _unittest_test(self, test_name: str, test_body: str, description: str) -> str:\n \"\"\"Generate unittest test.\"\"\"\n func_name = self._to_camel_case(test_name)\n return f\"\"\"def test_{func_name}(self):\n \\\"\\\"\\\"\n {description or test_name}\n \\\"\\\"\\\"\n{self._indent(test_body, 4)}\"\"\"\n\n def _junit_test(self, test_name: str, test_body: str, description: str) -> str:\n \"\"\"Generate JUnit test.\"\"\"\n method_name = self._to_camel_case(test_name)\n return f\"\"\"@Test\npublic void test{method_name}() {{\n // {description}\n{self._indent(test_body, 4)}\n}}\"\"\"\n\n def _testng_test(self, test_name: str, test_body: str, description: str) -> str:\n \"\"\"Generate TestNG test.\"\"\"\n method_name = self._to_camel_case(test_name)\n return f\"\"\"@Test\npublic void test{method_name}() {{\n // {description}\n{self._indent(test_body, 4)}\n}}\"\"\"\n\n def _mocha_test(self, test_name: str, test_body: str, description: str) -> str:\n \"\"\"Generate Mocha test.\"\"\"\n return f\"\"\"it('{test_name}', () => {{\n // {description}\n{self._indent(test_body, 2)}\n}});\"\"\"\n\n def generate_assertion(\n self,\n actual: str,\n expected: str,\n assertion_type: str = \"equals\"\n ) -> str:\n \"\"\"\n Generate framework-specific assertion.\n\n Args:\n actual: Actual value expression\n expected: Expected value expression\n assertion_type: Type of assertion (equals, not_equals, true, false, throws)\n\n Returns:\n Assertion statement\n \"\"\"\n if self.framework in [Framework.JEST, Framework.VITEST]:\n return self._jest_assertion(actual, expected, assertion_type)\n elif self.framework in [Framework.PYTEST, Framework.UNITTEST]:\n return self._python_assertion(actual, expected, assertion_type)\n elif self.framework in [Framework.JUNIT, Framework.TESTNG]:\n return self._java_assertion(actual, expected, assertion_type)\n elif self.framework == Framework.MOCHA:\n return self._chai_assertion(actual, expected, assertion_type)\n else:\n return f\"assert {actual} == {expected}\"\n\n def _jest_assertion(self, actual: str, expected: str, assertion_type: str) -> str:\n \"\"\"Generate Jest assertion.\"\"\"\n if assertion_type == \"equals\":\n return f\"expect({actual}).toBe({expected});\"\n elif assertion_type == \"not_equals\":\n return f\"expect({actual}).not.toBe({expected});\"\n elif assertion_type == \"true\":\n return f\"expect({actual}).toBe(true);\"\n elif assertion_type == \"false\":\n return f\"expect({actual}).toBe(false);\"\n elif assertion_type == \"throws\":\n return f\"expect(() => {actual}).toThrow();\"\n else:\n return f\"expect({actual}).toBe({expected});\"\n\n def _python_assertion(self, actual: str, expected: str, assertion_type: str) -> str:\n \"\"\"Generate Python assertion.\"\"\"\n if assertion_type == \"equals\":\n return f\"assert {actual} == {expected}\"\n elif assertion_type == \"not_equals\":\n return f\"assert {actual} != {expected}\"\n elif assertion_type == \"true\":\n return f\"assert {actual} is True\"\n elif assertion_type == \"false\":\n return f\"assert {actual} is False\"\n elif assertion_type == \"throws\":\n return f\"with pytest.raises(Exception):\\n {actual}\"\n else:\n return f\"assert {actual} == {expected}\"\n\n def _java_assertion(self, actual: str, expected: str, assertion_type: str) -> str:\n \"\"\"Generate Java assertion.\"\"\"\n if assertion_type == \"equals\":\n return f\"assertEquals({expected}, {actual});\"\n elif assertion_type == \"not_equals\":\n return f\"assertNotEquals({expected}, {actual});\"\n elif assertion_type == \"true\":\n return f\"assertTrue({actual});\"\n elif assertion_type == \"false\":\n return f\"assertFalse({actual});\"\n elif assertion_type == \"throws\":\n return f\"assertThrows(Exception.class, () -> {actual});\"\n else:\n return f\"assertEquals({expected}, {actual});\"\n\n def _chai_assertion(self, actual: str, expected: str, assertion_type: str) -> str:\n \"\"\"Generate Chai assertion.\"\"\"\n if assertion_type == \"equals\":\n return f\"expect({actual}).to.equal({expected});\"\n elif assertion_type == \"not_equals\":\n return f\"expect({actual}).to.not.equal({expected});\"\n elif assertion_type == \"true\":\n return f\"expect({actual}).to.be.true;\"\n elif assertion_type == \"false\":\n return f\"expect({actual}).to.be.false;\"\n elif assertion_type == \"throws\":\n return f\"expect(() => {actual}).to.throw();\"\n else:\n return f\"expect({actual}).to.equal({expected});\"\n\n def generate_setup_teardown(\n self,\n setup_code: str = \"\",\n teardown_code: str = \"\"\n ) -> str:\n \"\"\"Generate setup and teardown hooks.\"\"\"\n result = []\n\n if self.framework in [Framework.JEST, Framework.VITEST, Framework.MOCHA]:\n if setup_code:\n result.append(f\"\"\"beforeEach(() => {{\n{self._indent(setup_code, 2)}\n}});\"\"\")\n if teardown_code:\n result.append(f\"\"\"afterEach(() => {{\n{self._indent(teardown_code, 2)}\n}});\"\"\")\n\n elif self.framework == Framework.PYTEST:\n if setup_code:\n result.append(f\"\"\"@pytest.fixture(autouse=True)\ndef setup_method(self):\n{self._indent(setup_code, 4)}\n yield\"\"\")\n if teardown_code:\n result.append(f\"\"\"\n{self._indent(teardown_code, 4)}\"\"\")\n\n elif self.framework == Framework.UNITTEST:\n if setup_code:\n result.append(f\"\"\"def setUp(self):\n{self._indent(setup_code, 4)}\"\"\")\n if teardown_code:\n result.append(f\"\"\"def tearDown(self):\n{self._indent(teardown_code, 4)}\"\"\")\n\n elif self.framework in [Framework.JUNIT, Framework.TESTNG]:\n annotation = \"@BeforeEach\" if self.framework == Framework.JUNIT else \"@BeforeMethod\"\n if setup_code:\n result.append(f\"\"\"{annotation}\npublic void setUp() {{\n{self._indent(setup_code, 4)}\n}}\"\"\")\n\n annotation = \"@AfterEach\" if self.framework == Framework.JUNIT else \"@AfterMethod\"\n if teardown_code:\n result.append(f\"\"\"{annotation}\npublic void tearDown() {{\n{self._indent(teardown_code, 4)}\n}}\"\"\")\n\n return \"\\n\\n\".join(result)\n\n def _indent(self, text: str, spaces: int) -> str:\n \"\"\"Indent text by number of spaces.\"\"\"\n indent = \" \" * spaces\n lines = text.split('\\n')\n return '\\n'.join(indent + line if line.strip() else line for line in lines)\n\n def _to_camel_case(self, text: str) -> str:\n \"\"\"Convert text to camelCase.\"\"\"\n words = text.replace('-', ' ').replace('_', ' ').split()\n if not words:\n return text\n return words[0].lower() + ''.join(word.capitalize() for word in words[1:])\n\n def _to_class_name(self, text: str) -> str:\n \"\"\"Convert text to ClassName.\"\"\"\n words = text.replace('-', ' ').replace('_', ' ').split()\n return ''.join(word.capitalize() for word in words)\n\n def detect_framework(self, code: str) -> Optional[Framework]:\n \"\"\"\n Auto-detect testing framework from code.\n\n Args:\n code: Test code\n\n Returns:\n Detected framework or None\n \"\"\"\n # Jest patterns\n if 'from \\'@jest/globals\\'' in code or '@jest/' in code:\n return Framework.JEST\n\n # Vitest patterns\n if 'from \\'vitest\\'' in code or 'import { vi }' in code:\n return Framework.VITEST\n\n # Pytest patterns\n if 'import pytest' in code or 'def test_' in code and 'pytest.fixture' in code:\n return Framework.PYTEST\n\n # Unittest patterns\n if 'import unittest' in code and 'unittest.TestCase' in code:\n return Framework.UNITTEST\n\n # JUnit patterns\n if '@Test' in code and 'import org.junit' in code:\n return Framework.JUNIT\n\n # TestNG patterns\n if '@Test' in code and 'import org.testng' in code:\n return Framework.TESTNG\n\n # Mocha patterns\n if 'from \\'mocha\\'' in code or ('describe(' in code and 'from \\'chai\\'' in code):\n return Framework.MOCHA\n\n return None\n","content_type":"text/x-python; charset=utf-8","language":"python","size":14834,"content_sha256":"03a189d01310f04cb025bb9498ecd6bdc7d16eef119e992ff513774939299c58"},{"filename":"scripts/metrics_calculator.py","content":"\"\"\"\nMetrics calculation module.\n\nCalculate comprehensive test and code quality metrics including complexity,\ntest quality scoring, and test execution analysis.\n\"\"\"\n\nfrom typing import Dict, List, Any, Optional\nimport re\n\n\nclass MetricsCalculator:\n \"\"\"Calculate comprehensive test and code quality metrics.\"\"\"\n\n def __init__(self):\n \"\"\"Initialize metrics calculator.\"\"\"\n self.metrics = {}\n\n def calculate_all_metrics(\n self,\n source_code: str,\n test_code: str,\n coverage_data: Optional[Dict[str, Any]] = None,\n execution_data: Optional[Dict[str, Any]] = None\n ) -> Dict[str, Any]:\n \"\"\"\n Calculate all available metrics.\n\n Args:\n source_code: Source code to analyze\n test_code: Test code to analyze\n coverage_data: Coverage report data\n execution_data: Test execution results\n\n Returns:\n Complete metrics dictionary\n \"\"\"\n metrics = {\n 'complexity': self.calculate_complexity(source_code),\n 'test_quality': self.calculate_test_quality(test_code),\n 'coverage': coverage_data or {},\n 'execution': execution_data or {}\n }\n\n self.metrics = metrics\n return metrics\n\n def calculate_complexity(self, code: str) -> Dict[str, Any]:\n \"\"\"\n Calculate code complexity metrics.\n\n Args:\n code: Source code to analyze\n\n Returns:\n Complexity metrics (cyclomatic, cognitive, testability score)\n \"\"\"\n cyclomatic = self._cyclomatic_complexity(code)\n cognitive = self._cognitive_complexity(code)\n testability = self._testability_score(code, cyclomatic)\n\n return {\n 'cyclomatic_complexity': cyclomatic,\n 'cognitive_complexity': cognitive,\n 'testability_score': testability,\n 'assessment': self._complexity_assessment(cyclomatic, cognitive)\n }\n\n def _cyclomatic_complexity(self, code: str) -> int:\n \"\"\"\n Calculate cyclomatic complexity (simplified).\n\n Counts decision points: if, for, while, case, catch, &&, ||\n \"\"\"\n # Count decision points\n decision_points = 0\n\n # Control flow keywords\n keywords = ['if', 'for', 'while', 'case', 'catch', 'except']\n for keyword in keywords:\n # Use word boundaries to avoid matching substrings\n pattern = r'\\b' + keyword + r'\\b'\n decision_points += len(re.findall(pattern, code))\n\n # Logical operators\n decision_points += len(re.findall(r'\\&\\&|\\|\\|', code))\n\n # Base complexity is 1\n return decision_points + 1\n\n def _cognitive_complexity(self, code: str) -> int:\n \"\"\"\n Calculate cognitive complexity (simplified).\n\n Similar to cyclomatic but penalizes nesting and non-obvious flow.\n \"\"\"\n lines = code.split('\\n')\n cognitive_score = 0\n nesting_level = 0\n\n for line in lines:\n stripped = line.strip()\n\n # Increase nesting level\n if any(keyword in stripped for keyword in ['if ', 'for ', 'while ', 'def ', 'function ', 'class ']):\n cognitive_score += (1 + nesting_level)\n if stripped.endswith(':') or stripped.endswith('{'):\n nesting_level += 1\n\n # Decrease nesting level\n if stripped.startswith('}') or (stripped and not stripped.startswith(' ') and nesting_level > 0):\n nesting_level = max(0, nesting_level - 1)\n\n # Penalize complex conditions\n if '&&' in stripped or '||' in stripped:\n cognitive_score += 1\n\n return cognitive_score\n\n def _testability_score(self, code: str, cyclomatic: int) -> float:\n \"\"\"\n Calculate testability score (0-100).\n\n Based on:\n - Complexity (lower is better)\n - Dependencies (fewer is better)\n - Pure functions (more is better)\n \"\"\"\n score = 100.0\n\n # Penalize high complexity\n if cyclomatic > 10:\n score -= (cyclomatic - 10) * 5\n elif cyclomatic > 5:\n score -= (cyclomatic - 5) * 2\n\n # Penalize many dependencies\n imports = len(re.findall(r'import |require\\(|from .* import', code))\n if imports > 10:\n score -= (imports - 10) * 2\n\n # Reward small functions\n functions = len(re.findall(r'def |function ', code))\n lines = len(code.split('\\n'))\n if functions > 0:\n avg_function_size = lines / functions\n if avg_function_size \u003c 20:\n score += 10\n elif avg_function_size > 50:\n score -= 10\n\n return max(0.0, min(100.0, score))\n\n def _complexity_assessment(self, cyclomatic: int, cognitive: int) -> str:\n \"\"\"Generate complexity assessment.\"\"\"\n if cyclomatic \u003c= 5 and cognitive \u003c= 10:\n return \"Low complexity - easy to test\"\n elif cyclomatic \u003c= 10 and cognitive \u003c= 20:\n return \"Medium complexity - moderately testable\"\n elif cyclomatic \u003c= 15 and cognitive \u003c= 30:\n return \"High complexity - challenging to test\"\n else:\n return \"Very high complexity - consider refactoring\"\n\n def calculate_test_quality(self, test_code: str) -> Dict[str, Any]:\n \"\"\"\n Calculate test quality metrics.\n\n Args:\n test_code: Test code to analyze\n\n Returns:\n Test quality metrics\n \"\"\"\n assertions = self._count_assertions(test_code)\n test_functions = self._count_test_functions(test_code)\n isolation_score = self._isolation_score(test_code)\n naming_quality = self._naming_quality(test_code)\n test_smells = self._detect_test_smells(test_code)\n\n avg_assertions = assertions / test_functions if test_functions > 0 else 0\n\n return {\n 'total_tests': test_functions,\n 'total_assertions': assertions,\n 'avg_assertions_per_test': round(avg_assertions, 2),\n 'isolation_score': isolation_score,\n 'naming_quality': naming_quality,\n 'test_smells': test_smells,\n 'quality_score': self._calculate_quality_score(\n avg_assertions, isolation_score, naming_quality, test_smells\n )\n }\n\n def _count_assertions(self, test_code: str) -> int:\n \"\"\"Count assertion statements.\"\"\"\n # Common assertion patterns\n patterns = [\n r'\\bassert[A-Z]\\w*\\(', # JUnit: assertTrue, assertEquals\n r'\\bexpect\\(', # Jest/Vitest: expect()\n r'\\bassert\\s+', # Python: assert\n r'\\.should\\.', # Chai: should\n r'\\.to\\.', # Chai: expect().to\n ]\n\n count = 0\n for pattern in patterns:\n count += len(re.findall(pattern, test_code))\n\n return count\n\n def _count_test_functions(self, test_code: str) -> int:\n \"\"\"Count test functions.\"\"\"\n patterns = [\n r'\\btest_\\w+', # Python: test_*\n r'\\bit\\(', # Jest/Mocha: it()\n r'\\btest\\(', # Jest: test()\n r'@Test', # JUnit: @Test\n r'\\bdef test_', # Python def test_\n ]\n\n count = 0\n for pattern in patterns:\n count += len(re.findall(pattern, test_code))\n\n return max(1, count) # At least 1 to avoid division by zero\n\n def _isolation_score(self, test_code: str) -> float:\n \"\"\"\n Calculate test isolation score (0-100).\n\n Higher score = better isolation (fewer shared dependencies)\n \"\"\"\n score = 100.0\n\n # Penalize global state\n globals_used = len(re.findall(r'\\bglobal\\s+\\w+', test_code))\n score -= globals_used * 10\n\n # Penalize shared setup without proper cleanup\n setup_count = len(re.findall(r'beforeAll|beforeEach|setUp', test_code))\n cleanup_count = len(re.findall(r'afterAll|afterEach|tearDown', test_code))\n if setup_count > cleanup_count:\n score -= (setup_count - cleanup_count) * 5\n\n # Reward mocking\n mocks = len(re.findall(r'mock|stub|spy', test_code, re.IGNORECASE))\n score += min(mocks * 2, 10)\n\n return max(0.0, min(100.0, score))\n\n def _naming_quality(self, test_code: str) -> float:\n \"\"\"\n Calculate test naming quality score (0-100).\n\n Better names are descriptive and follow conventions.\n \"\"\"\n test_names = re.findall(r'(?:it|test|def test_)\\s*\\(?\\s*[\"\\']?([^\"\\')\\n]+)', test_code)\n\n if not test_names:\n return 50.0\n\n score = 0\n for name in test_names:\n name_score = 0\n\n # Check length (too short or too long is bad)\n if 20 \u003c= len(name) \u003c= 80:\n name_score += 30\n elif 10 \u003c= len(name) \u003c 20 or 80 \u003c len(name) \u003c= 100:\n name_score += 15\n\n # Check for descriptive words\n descriptive_words = ['should', 'when', 'given', 'returns', 'throws', 'handles']\n if any(word in name.lower() for word in descriptive_words):\n name_score += 30\n\n # Check for underscores or camelCase (not just letters)\n if '_' in name or re.search(r'[a-z][A-Z]', name):\n name_score += 20\n\n # Avoid generic names\n generic = ['test1', 'test2', 'testit', 'mytest']\n if name.lower() not in generic:\n name_score += 20\n\n score += name_score\n\n return min(100.0, score / len(test_names))\n\n def _detect_test_smells(self, test_code: str) -> List[Dict[str, str]]:\n \"\"\"Detect common test smells.\"\"\"\n smells = []\n\n # Test smell 1: No assertions\n if 'assert' not in test_code.lower() and 'expect' not in test_code.lower():\n smells.append({\n 'smell': 'missing_assertions',\n 'description': 'Tests without assertions',\n 'severity': 'high'\n })\n\n # Test smell 2: Too many assertions\n test_count = self._count_test_functions(test_code)\n assertion_count = self._count_assertions(test_code)\n avg_assertions = assertion_count / test_count if test_count > 0 else 0\n if avg_assertions > 5:\n smells.append({\n 'smell': 'assertion_roulette',\n 'description': f'Too many assertions per test (avg: {avg_assertions:.1f})',\n 'severity': 'medium'\n })\n\n # Test smell 3: Sleeps in tests\n if 'sleep' in test_code.lower() or 'wait' in test_code.lower():\n smells.append({\n 'smell': 'sleepy_test',\n 'description': 'Tests using sleep/wait (potential flakiness)',\n 'severity': 'high'\n })\n\n # Test smell 4: Conditional logic in tests\n if re.search(r'\\bif\\s*\\(', test_code):\n smells.append({\n 'smell': 'conditional_test_logic',\n 'description': 'Tests contain conditional logic',\n 'severity': 'medium'\n })\n\n return smells\n\n def _calculate_quality_score(\n self,\n avg_assertions: float,\n isolation: float,\n naming: float,\n smells: List[Dict[str, str]]\n ) -> float:\n \"\"\"Calculate overall test quality score.\"\"\"\n score = 0.0\n\n # Assertions (30 points)\n if 1 \u003c= avg_assertions \u003c= 3:\n score += 30\n elif 0 \u003c avg_assertions \u003c 1 or 3 \u003c avg_assertions \u003c= 5:\n score += 20\n else:\n score += 10\n\n # Isolation (30 points)\n score += isolation * 0.3\n\n # Naming (20 points)\n score += naming * 0.2\n\n # Smells (20 points - deduct based on severity)\n smell_penalty = 0\n for smell in smells:\n if smell['severity'] == 'high':\n smell_penalty += 10\n elif smell['severity'] == 'medium':\n smell_penalty += 5\n else:\n smell_penalty += 2\n\n score = max(0, score - smell_penalty)\n\n return round(min(100.0, score), 2)\n\n def analyze_execution_metrics(\n self,\n execution_data: Dict[str, Any]\n ) -> Dict[str, Any]:\n \"\"\"\n Analyze test execution metrics.\n\n Args:\n execution_data: Test execution results with timing\n\n Returns:\n Execution analysis\n \"\"\"\n tests = execution_data.get('tests', [])\n\n if not tests:\n return {}\n\n # Calculate timing statistics\n timings = [test.get('duration', 0) for test in tests]\n total_time = sum(timings)\n avg_time = total_time / len(tests) if tests else 0\n\n # Identify slow tests (>100ms for unit tests)\n slow_tests = [\n test for test in tests\n if test.get('duration', 0) > 100\n ]\n\n # Identify flaky tests (if failure history available)\n flaky_tests = [\n test for test in tests\n if test.get('failure_rate', 0) > 0.1 # Failed >10% of time\n ]\n\n return {\n 'total_tests': len(tests),\n 'total_time_ms': round(total_time, 2),\n 'avg_time_ms': round(avg_time, 2),\n 'slow_tests': len(slow_tests),\n 'slow_test_details': slow_tests[:5], # Top 5\n 'flaky_tests': len(flaky_tests),\n 'flaky_test_details': flaky_tests,\n 'pass_rate': self._calculate_pass_rate(tests)\n }\n\n def _calculate_pass_rate(self, tests: List[Dict[str, Any]]) -> float:\n \"\"\"Calculate test pass rate.\"\"\"\n if not tests:\n return 0.0\n\n passed = sum(1 for test in tests if test.get('status') == 'passed')\n return round((passed / len(tests)) * 100, 2)\n\n def generate_metrics_summary(self) -> str:\n \"\"\"Generate human-readable metrics summary.\"\"\"\n if not self.metrics:\n return \"No metrics calculated yet.\"\n\n lines = [\"# Test Metrics Summary\\n\"]\n\n # Complexity\n if 'complexity' in self.metrics:\n comp = self.metrics['complexity']\n lines.append(f\"## Code Complexity\")\n lines.append(f\"- Cyclomatic Complexity: {comp['cyclomatic_complexity']}\")\n lines.append(f\"- Cognitive Complexity: {comp['cognitive_complexity']}\")\n lines.append(f\"- Testability Score: {comp['testability_score']:.1f}/100\")\n lines.append(f\"- Assessment: {comp['assessment']}\\n\")\n\n # Test Quality\n if 'test_quality' in self.metrics:\n qual = self.metrics['test_quality']\n lines.append(f\"## Test Quality\")\n lines.append(f\"- Total Tests: {qual['total_tests']}\")\n lines.append(f\"- Assertions per Test: {qual['avg_assertions_per_test']}\")\n lines.append(f\"- Isolation Score: {qual['isolation_score']:.1f}/100\")\n lines.append(f\"- Naming Quality: {qual['naming_quality']:.1f}/100\")\n lines.append(f\"- Quality Score: {qual['quality_score']:.1f}/100\\n\")\n\n if qual['test_smells']:\n lines.append(f\"### Test Smells Detected:\")\n for smell in qual['test_smells']:\n lines.append(f\"- {smell['description']} (severity: {smell['severity']})\")\n lines.append(\"\")\n\n return \"\\n\".join(lines)\n","content_type":"text/x-python; charset=utf-8","language":"python","size":15476,"content_sha256":"8080b0daa70cb38114cf7937e3e8f942cef99b81db3fdd786e1ca44350bd57a8"},{"filename":"scripts/output_formatter.py","content":"\"\"\"\nOutput formatting module.\n\nProvides context-aware output formatting for different environments (Desktop, CLI, API).\nImplements progressive disclosure and token-efficient reporting.\n\"\"\"\n\nfrom typing import Dict, List, Any, Optional\n\n\nclass OutputFormatter:\n \"\"\"Format output based on environment and preferences.\"\"\"\n\n def __init__(self, environment: str = \"cli\", verbose: bool = False):\n \"\"\"\n Initialize output formatter.\n\n Args:\n environment: Target environment (desktop, cli, api)\n verbose: Whether to include detailed output\n \"\"\"\n self.environment = environment\n self.verbose = verbose\n\n def format_coverage_summary(\n self,\n summary: Dict[str, Any],\n detailed: bool = False\n ) -> str:\n \"\"\"\n Format coverage summary.\n\n Args:\n summary: Coverage summary data\n detailed: Whether to include detailed breakdown\n\n Returns:\n Formatted coverage summary\n \"\"\"\n if self.environment == \"desktop\":\n return self._format_coverage_markdown(summary, detailed)\n elif self.environment == \"api\":\n return self._format_coverage_json(summary)\n else:\n return self._format_coverage_terminal(summary, detailed)\n\n def _format_coverage_markdown(self, summary: Dict[str, Any], detailed: bool) -> str:\n \"\"\"Format coverage as rich markdown (for Claude Desktop).\"\"\"\n lines = [\"## Test Coverage Summary\\n\"]\n\n # Overall metrics\n lines.append(\"### Overall Metrics\")\n lines.append(f\"- **Line Coverage**: {summary.get('line_coverage', 0):.1f}%\")\n lines.append(f\"- **Branch Coverage**: {summary.get('branch_coverage', 0):.1f}%\")\n lines.append(f\"- **Function Coverage**: {summary.get('function_coverage', 0):.1f}%\\n\")\n\n # Visual indicator\n line_cov = summary.get('line_coverage', 0)\n lines.append(self._coverage_badge(line_cov))\n lines.append(\"\")\n\n # Detailed breakdown if requested\n if detailed:\n lines.append(\"### Detailed Breakdown\")\n lines.append(f\"- Total Lines: {summary.get('total_lines', 0)}\")\n lines.append(f\"- Covered Lines: {summary.get('covered_lines', 0)}\")\n lines.append(f\"- Total Branches: {summary.get('total_branches', 0)}\")\n lines.append(f\"- Covered Branches: {summary.get('covered_branches', 0)}\")\n lines.append(f\"- Total Functions: {summary.get('total_functions', 0)}\")\n lines.append(f\"- Covered Functions: {summary.get('covered_functions', 0)}\\n\")\n\n return \"\\n\".join(lines)\n\n def _format_coverage_terminal(self, summary: Dict[str, Any], detailed: bool) -> str:\n \"\"\"Format coverage for terminal (Claude Code CLI).\"\"\"\n lines = [\"Coverage Summary:\"]\n lines.append(f\" Line: {summary.get('line_coverage', 0):.1f}%\")\n lines.append(f\" Branch: {summary.get('branch_coverage', 0):.1f}%\")\n lines.append(f\" Function: {summary.get('function_coverage', 0):.1f}%\")\n\n if detailed:\n lines.append(f\"\\nDetails:\")\n lines.append(f\" Lines: {summary.get('covered_lines', 0)}/{summary.get('total_lines', 0)}\")\n lines.append(f\" Branches: {summary.get('covered_branches', 0)}/{summary.get('total_branches', 0)}\")\n\n return \"\\n\".join(lines)\n\n def _format_coverage_json(self, summary: Dict[str, Any]) -> str:\n \"\"\"Format coverage as JSON (for API/CI integration).\"\"\"\n import json\n return json.dumps(summary, indent=2)\n\n def _coverage_badge(self, coverage: float) -> str:\n \"\"\"Generate coverage badge markdown.\"\"\"\n if coverage >= 80:\n color = \"green\"\n emoji = \"✅\"\n elif coverage >= 60:\n color = \"yellow\"\n emoji = \"⚠️\"\n else:\n color = \"red\"\n emoji = \"❌\"\n\n return f\"{emoji} **{coverage:.1f}%** coverage ({color})\"\n\n def format_recommendations(\n self,\n recommendations: List[Dict[str, Any]],\n max_items: Optional[int] = None\n ) -> str:\n \"\"\"\n Format recommendations with progressive disclosure.\n\n Args:\n recommendations: List of recommendation dictionaries\n max_items: Maximum number of items to show (None for all)\n\n Returns:\n Formatted recommendations\n \"\"\"\n if not recommendations:\n return \"No recommendations at this time.\"\n\n # Group by priority\n p0 = [r for r in recommendations if r.get('priority') == 'P0']\n p1 = [r for r in recommendations if r.get('priority') == 'P1']\n p2 = [r for r in recommendations if r.get('priority') == 'P2']\n\n if self.environment == \"desktop\":\n return self._format_recommendations_markdown(p0, p1, p2, max_items)\n elif self.environment == \"api\":\n return self._format_recommendations_json(recommendations)\n else:\n return self._format_recommendations_terminal(p0, p1, p2, max_items)\n\n def _format_recommendations_markdown(\n self,\n p0: List[Dict],\n p1: List[Dict],\n p2: List[Dict],\n max_items: Optional[int]\n ) -> str:\n \"\"\"Format recommendations as rich markdown.\"\"\"\n lines = [\"## Recommendations\\n\"]\n\n if p0:\n lines.append(\"### 🔴 Critical (P0)\")\n for i, rec in enumerate(p0[:max_items] if max_items else p0):\n lines.append(f\"{i+1}. **{rec.get('message', 'No message')}**\")\n lines.append(f\" - Action: {rec.get('action', 'No action specified')}\")\n if 'file' in rec:\n lines.append(f\" - File: `{rec['file']}`\")\n lines.append(\"\")\n\n if p1 and (not max_items or len(p0) \u003c max_items):\n remaining = max_items - len(p0) if max_items else None\n lines.append(\"### 🟡 Important (P1)\")\n for i, rec in enumerate(p1[:remaining] if remaining else p1):\n lines.append(f\"{i+1}. {rec.get('message', 'No message')}\")\n lines.append(f\" - Action: {rec.get('action', 'No action specified')}\")\n lines.append(\"\")\n\n if p2 and self.verbose:\n lines.append(\"### 🔵 Nice to Have (P2)\")\n for i, rec in enumerate(p2):\n lines.append(f\"{i+1}. {rec.get('message', 'No message')}\")\n lines.append(\"\")\n\n return \"\\n\".join(lines)\n\n def _format_recommendations_terminal(\n self,\n p0: List[Dict],\n p1: List[Dict],\n p2: List[Dict],\n max_items: Optional[int]\n ) -> str:\n \"\"\"Format recommendations for terminal.\"\"\"\n lines = [\"Recommendations:\"]\n\n if p0:\n lines.append(\"\\nCritical (P0):\")\n for i, rec in enumerate(p0[:max_items] if max_items else p0):\n lines.append(f\" {i+1}. {rec.get('message', 'No message')}\")\n lines.append(f\" Action: {rec.get('action', 'No action')}\")\n\n if p1 and (not max_items or len(p0) \u003c max_items):\n remaining = max_items - len(p0) if max_items else None\n lines.append(\"\\nImportant (P1):\")\n for i, rec in enumerate(p1[:remaining] if remaining else p1):\n lines.append(f\" {i+1}. {rec.get('message', 'No message')}\")\n\n return \"\\n\".join(lines)\n\n def _format_recommendations_json(self, recommendations: List[Dict[str, Any]]) -> str:\n \"\"\"Format recommendations as JSON.\"\"\"\n import json\n return json.dumps(recommendations, indent=2)\n\n def format_test_results(\n self,\n results: Dict[str, Any],\n show_details: bool = False\n ) -> str:\n \"\"\"\n Format test execution results.\n\n Args:\n results: Test results data\n show_details: Whether to show detailed results\n\n Returns:\n Formatted test results\n \"\"\"\n if self.environment == \"desktop\":\n return self._format_results_markdown(results, show_details)\n elif self.environment == \"api\":\n return self._format_results_json(results)\n else:\n return self._format_results_terminal(results, show_details)\n\n def _format_results_markdown(self, results: Dict[str, Any], show_details: bool) -> str:\n \"\"\"Format test results as markdown.\"\"\"\n lines = [\"## Test Results\\n\"]\n\n total = results.get('total_tests', 0)\n passed = results.get('passed', 0)\n failed = results.get('failed', 0)\n skipped = results.get('skipped', 0)\n\n # Summary\n lines.append(f\"- **Total Tests**: {total}\")\n lines.append(f\"- **Passed**: ✅ {passed}\")\n if failed > 0:\n lines.append(f\"- **Failed**: ❌ {failed}\")\n if skipped > 0:\n lines.append(f\"- **Skipped**: ⏭️ {skipped}\")\n\n # Pass rate\n pass_rate = (passed / total * 100) if total > 0 else 0\n lines.append(f\"- **Pass Rate**: {pass_rate:.1f}%\\n\")\n\n # Failed tests details\n if show_details and failed > 0:\n lines.append(\"### Failed Tests\")\n for test in results.get('failed_tests', []):\n lines.append(f\"- `{test.get('name', 'Unknown')}`\")\n if 'error' in test:\n lines.append(f\" ```\\n {test['error']}\\n ```\")\n\n return \"\\n\".join(lines)\n\n def _format_results_terminal(self, results: Dict[str, Any], show_details: bool) -> str:\n \"\"\"Format test results for terminal.\"\"\"\n total = results.get('total_tests', 0)\n passed = results.get('passed', 0)\n failed = results.get('failed', 0)\n\n lines = [f\"Test Results: {passed}/{total} passed\"]\n\n if failed > 0:\n lines.append(f\" Failed: {failed}\")\n\n if show_details and failed > 0:\n lines.append(\"\\nFailed tests:\")\n for test in results.get('failed_tests', [])[:5]:\n lines.append(f\" - {test.get('name', 'Unknown')}\")\n\n return \"\\n\".join(lines)\n\n def _format_results_json(self, results: Dict[str, Any]) -> str:\n \"\"\"Format test results as JSON.\"\"\"\n import json\n return json.dumps(results, indent=2)\n\n def create_summary_report(\n self,\n coverage: Dict[str, Any],\n metrics: Dict[str, Any],\n recommendations: List[Dict[str, Any]]\n ) -> str:\n \"\"\"\n Create comprehensive summary report (token-efficient).\n\n Args:\n coverage: Coverage data\n metrics: Quality metrics\n recommendations: Recommendations list\n\n Returns:\n Summary report (\u003c200 tokens)\n \"\"\"\n lines = []\n\n # Coverage (1-2 lines)\n line_cov = coverage.get('line_coverage', 0)\n branch_cov = coverage.get('branch_coverage', 0)\n lines.append(f\"Coverage: {line_cov:.0f}% lines, {branch_cov:.0f}% branches\")\n\n # Quality (1-2 lines)\n if 'test_quality' in metrics:\n quality_score = metrics['test_quality'].get('quality_score', 0)\n lines.append(f\"Test Quality: {quality_score:.0f}/100\")\n\n # Top recommendations (2-3 lines)\n p0_count = sum(1 for r in recommendations if r.get('priority') == 'P0')\n if p0_count > 0:\n lines.append(f\"Critical issues: {p0_count}\")\n top_rec = next((r for r in recommendations if r.get('priority') == 'P0'), None)\n if top_rec:\n lines.append(f\" - {top_rec.get('message', '')}\")\n\n return \"\\n\".join(lines)\n\n def should_show_detailed(self, data_size: int) -> bool:\n \"\"\"\n Determine if detailed output should be shown based on data size.\n\n Args:\n data_size: Size of data to display\n\n Returns:\n Whether to show detailed output\n \"\"\"\n if self.verbose:\n return True\n\n # Progressive disclosure thresholds\n if self.environment == \"desktop\":\n return data_size \u003c 100 # Show more in Desktop\n else:\n return data_size \u003c 20 # Show less in CLI\n\n def truncate_output(self, text: str, max_lines: int = 50) -> str:\n \"\"\"\n Truncate output to maximum lines.\n\n Args:\n text: Text to truncate\n max_lines: Maximum number of lines\n\n Returns:\n Truncated text with indicator\n \"\"\"\n lines = text.split('\\n')\n\n if len(lines) \u003c= max_lines:\n return text\n\n truncated = '\\n'.join(lines[:max_lines])\n remaining = len(lines) - max_lines\n\n return f\"{truncated}\\n\\n... ({remaining} more lines, use --verbose for full output)\"\n","content_type":"text/x-python; charset=utf-8","language":"python","size":12734,"content_sha256":"e92a7559ae39c9b144a55b2dfaf6f14d9137a7e37aa9ee07adaf7c4c346b21fd"},{"filename":"scripts/tdd_workflow.py","content":"\"\"\"\nTDD workflow guidance module.\n\nProvides step-by-step guidance through red-green-refactor cycles with validation.\n\"\"\"\n\nfrom typing import Dict, List, Any, Optional\nfrom enum import Enum\n\n\nclass TDDPhase(Enum):\n \"\"\"TDD cycle phases.\"\"\"\n RED = \"red\" # Write failing test\n GREEN = \"green\" # Make test pass\n REFACTOR = \"refactor\" # Improve code\n\n\nclass WorkflowState(Enum):\n \"\"\"Current state of TDD workflow.\"\"\"\n INITIAL = \"initial\"\n TEST_WRITTEN = \"test_written\"\n TEST_FAILING = \"test_failing\"\n TEST_PASSING = \"test_passing\"\n CODE_REFACTORED = \"code_refactored\"\n\n\nclass TDDWorkflow:\n \"\"\"Guide users through TDD red-green-refactor workflow.\"\"\"\n\n def __init__(self):\n \"\"\"Initialize TDD workflow guide.\"\"\"\n self.current_phase = TDDPhase.RED\n self.state = WorkflowState.INITIAL\n self.history = []\n\n def start_cycle(self, requirement: str) -> Dict[str, Any]:\n \"\"\"\n Start a new TDD cycle.\n\n Args:\n requirement: User story or requirement to implement\n\n Returns:\n Guidance for RED phase\n \"\"\"\n self.current_phase = TDDPhase.RED\n self.state = WorkflowState.INITIAL\n\n return {\n 'phase': 'RED',\n 'instruction': 'Write a failing test for the requirement',\n 'requirement': requirement,\n 'checklist': [\n 'Write test that describes desired behavior',\n 'Test should fail when run (no implementation yet)',\n 'Test name clearly describes what is being tested',\n 'Test has clear arrange-act-assert structure'\n ],\n 'tips': [\n 'Focus on behavior, not implementation',\n 'Start with simplest test case',\n 'Test should be specific and focused'\n ]\n }\n\n def validate_red_phase(\n self,\n test_code: str,\n test_result: Optional[Dict[str, Any]] = None\n ) -> Dict[str, Any]:\n \"\"\"\n Validate RED phase completion.\n\n Args:\n test_code: The test code written\n test_result: Test execution result (optional)\n\n Returns:\n Validation result and next steps\n \"\"\"\n validations = []\n\n # Check test exists\n if not test_code or len(test_code.strip()) \u003c 10:\n validations.append({\n 'valid': False,\n 'message': 'No test code provided'\n })\n else:\n validations.append({\n 'valid': True,\n 'message': 'Test code provided'\n })\n\n # Check for assertions\n has_assertion = any(keyword in test_code.lower()\n for keyword in ['assert', 'expect', 'should'])\n validations.append({\n 'valid': has_assertion,\n 'message': 'Contains assertions' if has_assertion else 'Missing assertions'\n })\n\n # Check test result if provided\n if test_result:\n test_failed = test_result.get('status') == 'failed'\n validations.append({\n 'valid': test_failed,\n 'message': 'Test fails as expected' if test_failed else 'Test should fail in RED phase'\n })\n\n all_valid = all(v['valid'] for v in validations)\n\n if all_valid:\n self.state = WorkflowState.TEST_FAILING\n self.current_phase = TDDPhase.GREEN\n return {\n 'phase_complete': True,\n 'next_phase': 'GREEN',\n 'validations': validations,\n 'instruction': 'Write minimal code to make the test pass'\n }\n else:\n return {\n 'phase_complete': False,\n 'current_phase': 'RED',\n 'validations': validations,\n 'instruction': 'Address validation issues before proceeding'\n }\n\n def validate_green_phase(\n self,\n implementation_code: str,\n test_result: Dict[str, Any]\n ) -> Dict[str, Any]:\n \"\"\"\n Validate GREEN phase completion.\n\n Args:\n implementation_code: The implementation code\n test_result: Test execution result\n\n Returns:\n Validation result and next steps\n \"\"\"\n validations = []\n\n # Check implementation exists\n if not implementation_code or len(implementation_code.strip()) \u003c 5:\n validations.append({\n 'valid': False,\n 'message': 'No implementation code provided'\n })\n else:\n validations.append({\n 'valid': True,\n 'message': 'Implementation code provided'\n })\n\n # Check test now passes\n test_passed = test_result.get('status') == 'passed'\n validations.append({\n 'valid': test_passed,\n 'message': 'Test passes' if test_passed else 'Test still failing'\n })\n\n # Check for minimal implementation (heuristic)\n is_minimal = self._check_minimal_implementation(implementation_code)\n validations.append({\n 'valid': is_minimal,\n 'message': 'Implementation appears minimal' if is_minimal\n else 'Implementation may be over-engineered'\n })\n\n all_valid = all(v['valid'] for v in validations)\n\n if all_valid:\n self.state = WorkflowState.TEST_PASSING\n self.current_phase = TDDPhase.REFACTOR\n return {\n 'phase_complete': True,\n 'next_phase': 'REFACTOR',\n 'validations': validations,\n 'instruction': 'Refactor code while keeping tests green',\n 'refactoring_suggestions': self._suggest_refactorings(implementation_code)\n }\n else:\n return {\n 'phase_complete': False,\n 'current_phase': 'GREEN',\n 'validations': validations,\n 'instruction': 'Make the test pass before refactoring'\n }\n\n def validate_refactor_phase(\n self,\n original_code: str,\n refactored_code: str,\n test_result: Dict[str, Any]\n ) -> Dict[str, Any]:\n \"\"\"\n Validate REFACTOR phase completion.\n\n Args:\n original_code: Original implementation\n refactored_code: Refactored implementation\n test_result: Test execution result after refactoring\n\n Returns:\n Validation result and cycle completion status\n \"\"\"\n validations = []\n\n # Check tests still pass\n test_passed = test_result.get('status') == 'passed'\n validations.append({\n 'valid': test_passed,\n 'message': 'Tests still pass after refactoring' if test_passed\n else 'Tests broken by refactoring'\n })\n\n # Check code was actually refactored\n code_changed = original_code != refactored_code\n validations.append({\n 'valid': code_changed,\n 'message': 'Code was refactored' if code_changed\n else 'No refactoring applied (optional)'\n })\n\n # Check code quality improved\n quality_improved = self._check_quality_improvement(original_code, refactored_code)\n if code_changed:\n validations.append({\n 'valid': quality_improved,\n 'message': 'Code quality improved' if quality_improved\n else 'Consider further refactoring for better quality'\n })\n\n all_valid = all(v['valid'] for v in validations if v.get('valid') is not None)\n\n if all_valid:\n self.state = WorkflowState.CODE_REFACTORED\n self.history.append({\n 'cycle_complete': True,\n 'final_state': self.state\n })\n return {\n 'phase_complete': True,\n 'cycle_complete': True,\n 'validations': validations,\n 'message': 'TDD cycle complete! Ready for next requirement.',\n 'next_steps': [\n 'Commit your changes',\n 'Start next TDD cycle with new requirement',\n 'Or add more test cases for current feature'\n ]\n }\n else:\n return {\n 'phase_complete': False,\n 'current_phase': 'REFACTOR',\n 'validations': validations,\n 'instruction': 'Ensure tests still pass after refactoring'\n }\n\n def _check_minimal_implementation(self, code: str) -> bool:\n \"\"\"Check if implementation is minimal (heuristic).\"\"\"\n # Simple heuristics:\n # - Not too long (\u003c 50 lines for unit tests)\n # - Not too complex (few nested structures)\n\n lines = code.split('\\n')\n non_empty_lines = [line for line in lines if line.strip() and not line.strip().startswith('#')]\n\n # Check length\n if len(non_empty_lines) > 50:\n return False\n\n # Check nesting depth (simplified)\n max_depth = 0\n current_depth = 0\n for line in lines:\n stripped = line.lstrip()\n if stripped:\n indent = len(line) - len(stripped)\n depth = indent // 4 # Assuming 4-space indent\n max_depth = max(max_depth, depth)\n\n # Max nesting of 3 levels for simple implementation\n return max_depth \u003c= 3\n\n def _check_quality_improvement(self, original: str, refactored: str) -> bool:\n \"\"\"Check if refactoring improved code quality.\"\"\"\n # Simple heuristics:\n # - Reduced duplication\n # - Better naming\n # - Simpler structure\n\n # Check for reduced duplication (basic check)\n original_lines = set(line.strip() for line in original.split('\\n') if line.strip())\n refactored_lines = set(line.strip() for line in refactored.split('\\n') if line.strip())\n\n # If unique lines increased proportionally, likely extracted duplicates\n if len(refactored_lines) > len(original_lines):\n return True\n\n # Check for better naming (longer, more descriptive names)\n original_avg_identifier_length = self._avg_identifier_length(original)\n refactored_avg_identifier_length = self._avg_identifier_length(refactored)\n\n if refactored_avg_identifier_length > original_avg_identifier_length:\n return True\n\n # If no clear improvement detected, assume refactoring was beneficial\n return True\n\n def _avg_identifier_length(self, code: str) -> float:\n \"\"\"Calculate average identifier length (proxy for naming quality).\"\"\"\n import re\n identifiers = re.findall(r'\\b[a-zA-Z_][a-zA-Z0-9_]*\\b', code)\n\n # Filter out keywords\n keywords = {'if', 'else', 'for', 'while', 'def', 'class', 'return', 'import', 'from'}\n identifiers = [i for i in identifiers if i.lower() not in keywords]\n\n if not identifiers:\n return 0.0\n\n return sum(len(i) for i in identifiers) / len(identifiers)\n\n def _suggest_refactorings(self, code: str) -> List[str]:\n \"\"\"Suggest potential refactorings.\"\"\"\n suggestions = []\n\n # Check for long functions\n lines = code.split('\\n')\n if len(lines) > 30:\n suggestions.append('Consider breaking long function into smaller functions')\n\n # Check for duplication (simple check)\n line_counts = {}\n for line in lines:\n stripped = line.strip()\n if len(stripped) > 10: # Ignore very short lines\n line_counts[stripped] = line_counts.get(stripped, 0) + 1\n\n duplicates = [line for line, count in line_counts.items() if count > 2]\n if duplicates:\n suggestions.append(f'Found {len(duplicates)} duplicated code patterns - consider extraction')\n\n # Check for magic numbers\n import re\n magic_numbers = re.findall(r'\\b\\d+\\b', code)\n if len(magic_numbers) > 5:\n suggestions.append('Consider extracting magic numbers to named constants')\n\n # Check for long parameter lists\n if 'def ' in code or 'function' in code:\n param_matches = re.findall(r'\\(([^)]+)\\)', code)\n for params in param_matches:\n if params.count(',') > 3:\n suggestions.append('Consider using parameter object for functions with many parameters')\n break\n\n if not suggestions:\n suggestions.append('Code looks clean - no obvious refactorings needed')\n\n return suggestions\n\n def generate_workflow_summary(self) -> str:\n \"\"\"Generate summary of TDD workflow progress.\"\"\"\n summary = [\n \"# TDD Workflow Summary\\n\",\n f\"Current Phase: {self.current_phase.value.upper()}\",\n f\"Current State: {self.state.value.replace('_', ' ').title()}\",\n f\"Completed Cycles: {len(self.history)}\\n\"\n ]\n\n summary.append(\"## TDD Cycle Steps:\\n\")\n summary.append(\"1. **RED**: Write a failing test\")\n summary.append(\" - Test describes desired behavior\")\n summary.append(\" - Test fails (no implementation)\\n\")\n\n summary.append(\"2. **GREEN**: Make the test pass\")\n summary.append(\" - Write minimal code to pass test\")\n summary.append(\" - All tests should pass\\n\")\n\n summary.append(\"3. **REFACTOR**: Improve the code\")\n summary.append(\" - Clean up implementation\")\n summary.append(\" - Tests still pass\")\n summary.append(\" - Code is more maintainable\\n\")\n\n return \"\\n\".join(summary)\n\n def get_phase_guidance(self, phase: Optional[TDDPhase] = None) -> Dict[str, Any]:\n \"\"\"\n Get detailed guidance for a specific phase.\n\n Args:\n phase: TDD phase (uses current if not specified)\n\n Returns:\n Detailed guidance dictionary\n \"\"\"\n target_phase = phase or self.current_phase\n\n if target_phase == TDDPhase.RED:\n return {\n 'phase': 'RED',\n 'goal': 'Write a failing test',\n 'steps': [\n '1. Read and understand the requirement',\n '2. Think about expected behavior',\n '3. Write test that verifies this behavior',\n '4. Run test and ensure it fails',\n '5. Verify failure reason is correct (not syntax error)'\n ],\n 'common_mistakes': [\n 'Test passes immediately (no real assertion)',\n 'Test fails for wrong reason (syntax error)',\n 'Test is too broad or tests multiple things'\n ],\n 'tips': [\n 'Start with simplest test case',\n 'One assertion per test (focused)',\n 'Test should read like specification'\n ]\n }\n\n elif target_phase == TDDPhase.GREEN:\n return {\n 'phase': 'GREEN',\n 'goal': 'Make the test pass with minimal code',\n 'steps': [\n '1. Write simplest code that makes test pass',\n '2. Run test and verify it passes',\n '3. Run all tests to ensure no regression',\n '4. Resist urge to add extra features'\n ],\n 'common_mistakes': [\n 'Over-engineering solution',\n 'Adding features not covered by tests',\n 'Breaking existing tests'\n ],\n 'tips': [\n 'Fake it till you make it (hardcode if needed)',\n 'Triangulate with more tests if needed',\n 'Keep implementation simple'\n ]\n }\n\n elif target_phase == TDDPhase.REFACTOR:\n return {\n 'phase': 'REFACTOR',\n 'goal': 'Improve code quality while keeping tests green',\n 'steps': [\n '1. Identify code smells or duplication',\n '2. Apply one refactoring at a time',\n '3. Run tests after each change',\n '4. Commit when satisfied with quality'\n ],\n 'common_mistakes': [\n 'Changing behavior (breaking tests)',\n 'Refactoring too much at once',\n 'Skipping this phase'\n ],\n 'tips': [\n 'Extract methods for better naming',\n 'Remove duplication',\n 'Improve variable names',\n 'Tests are safety net - use them!'\n ]\n }\n\n return {}\n","content_type":"text/x-python; charset=utf-8","language":"python","size":16968,"content_sha256":"5048dda42125f9c95cd49dbf67816f5bc635fee0cc5938a74a4d1b59361f9095"},{"filename":"scripts/test_generator.py","content":"\"\"\"\nTest case generation module.\n\nGenerates test cases from requirements, user stories, API specs, and code analysis.\nSupports multiple testing frameworks with intelligent test scaffolding.\n\"\"\"\n\nfrom typing import Dict, List, Any, Optional\nfrom enum import Enum\n\n\nclass TestFramework(Enum):\n \"\"\"Supported testing frameworks.\"\"\"\n JEST = \"jest\"\n VITEST = \"vitest\"\n PYTEST = \"pytest\"\n JUNIT = \"junit\"\n MOCHA = \"mocha\"\n\n\nclass TestType(Enum):\n \"\"\"Types of tests to generate.\"\"\"\n UNIT = \"unit\"\n INTEGRATION = \"integration\"\n E2E = \"e2e\"\n\n\nclass TestGenerator:\n \"\"\"Generate test cases and test stubs from requirements and code.\"\"\"\n\n def __init__(self, framework: TestFramework, language: str):\n \"\"\"\n Initialize test generator.\n\n Args:\n framework: Testing framework to use\n language: Programming language (typescript, javascript, python, java)\n \"\"\"\n self.framework = framework\n self.language = language\n self.test_cases = []\n\n def generate_from_requirements(\n self,\n requirements: Dict[str, Any],\n test_type: TestType = TestType.UNIT\n ) -> List[Dict[str, Any]]:\n \"\"\"\n Generate test cases from requirements.\n\n Args:\n requirements: Dictionary with user_stories, acceptance_criteria, api_specs\n test_type: Type of tests to generate\n\n Returns:\n List of test case specifications\n \"\"\"\n test_cases = []\n\n # Generate from user stories\n if 'user_stories' in requirements:\n for story in requirements['user_stories']:\n test_cases.extend(self._test_cases_from_story(story))\n\n # Generate from acceptance criteria\n if 'acceptance_criteria' in requirements:\n for criterion in requirements['acceptance_criteria']:\n test_cases.extend(self._test_cases_from_criteria(criterion))\n\n # Generate from API specs\n if 'api_specs' in requirements:\n for endpoint in requirements['api_specs']:\n test_cases.extend(self._test_cases_from_api(endpoint))\n\n self.test_cases = test_cases\n return test_cases\n\n def _test_cases_from_story(self, story: Dict[str, Any]) -> List[Dict[str, Any]]:\n \"\"\"Generate test cases from user story.\"\"\"\n test_cases = []\n\n # Happy path test\n test_cases.append({\n 'name': f\"should_{story.get('action', 'work')}_successfully\",\n 'type': 'happy_path',\n 'description': story.get('description', ''),\n 'given': story.get('given', []),\n 'when': story.get('when', ''),\n 'then': story.get('then', ''),\n 'priority': 'P0'\n })\n\n # Error cases\n if 'error_conditions' in story:\n for error in story['error_conditions']:\n test_cases.append({\n 'name': f\"should_handle_{error.get('condition', 'error')}\",\n 'type': 'error_case',\n 'description': error.get('description', ''),\n 'expected_error': error.get('error_type', ''),\n 'priority': 'P0'\n })\n\n # Edge cases\n if 'edge_cases' in story:\n for edge_case in story['edge_cases']:\n test_cases.append({\n 'name': f\"should_handle_{edge_case.get('scenario', 'edge_case')}\",\n 'type': 'edge_case',\n 'description': edge_case.get('description', ''),\n 'priority': 'P1'\n })\n\n return test_cases\n\n def _test_cases_from_criteria(self, criterion: Dict[str, Any]) -> List[Dict[str, Any]]:\n \"\"\"Generate test cases from acceptance criteria.\"\"\"\n return [{\n 'name': f\"should_meet_{criterion.get('id', 'criterion')}\",\n 'type': 'acceptance',\n 'description': criterion.get('description', ''),\n 'verification': criterion.get('verification_steps', []),\n 'priority': 'P0'\n }]\n\n def _test_cases_from_api(self, endpoint: Dict[str, Any]) -> List[Dict[str, Any]]:\n \"\"\"Generate test cases from API specification.\"\"\"\n test_cases = []\n method = endpoint.get('method', 'GET')\n path = endpoint.get('path', '/')\n\n # Success case\n test_cases.append({\n 'name': f\"should_{method.lower()}_{path.replace('/', '_')}_successfully\",\n 'type': 'api_success',\n 'method': method,\n 'path': path,\n 'expected_status': endpoint.get('success_status', 200),\n 'priority': 'P0'\n })\n\n # Validation errors\n if 'required_params' in endpoint:\n test_cases.append({\n 'name': f\"should_return_400_for_missing_params\",\n 'type': 'api_validation',\n 'method': method,\n 'path': path,\n 'expected_status': 400,\n 'priority': 'P0'\n })\n\n # Authorization\n if endpoint.get('requires_auth', False):\n test_cases.append({\n 'name': f\"should_return_401_for_unauthenticated\",\n 'type': 'api_auth',\n 'method': method,\n 'path': path,\n 'expected_status': 401,\n 'priority': 'P0'\n })\n\n return test_cases\n\n def generate_test_stub(self, test_case: Dict[str, Any]) -> str:\n \"\"\"\n Generate test stub code for a test case.\n\n Args:\n test_case: Test case specification\n\n Returns:\n Test stub code as string\n \"\"\"\n if self.framework == TestFramework.JEST:\n return self._generate_jest_stub(test_case)\n elif self.framework == TestFramework.PYTEST:\n return self._generate_pytest_stub(test_case)\n elif self.framework == TestFramework.JUNIT:\n return self._generate_junit_stub(test_case)\n elif self.framework == TestFramework.VITEST:\n return self._generate_vitest_stub(test_case)\n else:\n return self._generate_generic_stub(test_case)\n\n def _generate_jest_stub(self, test_case: Dict[str, Any]) -> str:\n \"\"\"Generate Jest test stub.\"\"\"\n name = test_case.get('name', 'test')\n description = test_case.get('description', '')\n\n stub = f\"\"\"\ndescribe('{{Feature Name}}', () => {{\n it('{name}', () => {{\n // {description}\n\n // Arrange\n // TODO: Set up test data and dependencies\n\n // Act\n // TODO: Execute the code under test\n\n // Assert\n // TODO: Verify expected behavior\n expect(true).toBe(true); // Replace with actual assertion\n }});\n}});\n\"\"\"\n return stub.strip()\n\n def _generate_pytest_stub(self, test_case: Dict[str, Any]) -> str:\n \"\"\"Generate Pytest test stub.\"\"\"\n name = test_case.get('name', 'test')\n description = test_case.get('description', '')\n\n stub = f\"\"\"\ndef test_{name}():\n \\\"\\\"\\\"\n {description}\n \\\"\\\"\\\"\n # Arrange\n # TODO: Set up test data and dependencies\n\n # Act\n # TODO: Execute the code under test\n\n # Assert\n # TODO: Verify expected behavior\n assert True # Replace with actual assertion\n\"\"\"\n return stub.strip()\n\n def _generate_junit_stub(self, test_case: Dict[str, Any]) -> str:\n \"\"\"Generate JUnit test stub.\"\"\"\n name = test_case.get('name', 'test')\n description = test_case.get('description', '')\n\n # Convert snake_case to camelCase for Java\n method_name = ''.join(word.capitalize() if i > 0 else word\n for i, word in enumerate(name.split('_')))\n\n stub = f\"\"\"\n@Test\npublic void {method_name}() {{\n // {description}\n\n // Arrange\n // TODO: Set up test data and dependencies\n\n // Act\n // TODO: Execute the code under test\n\n // Assert\n // TODO: Verify expected behavior\n assertTrue(true); // Replace with actual assertion\n}}\n\"\"\"\n return stub.strip()\n\n def _generate_vitest_stub(self, test_case: Dict[str, Any]) -> str:\n \"\"\"Generate Vitest test stub (similar to Jest).\"\"\"\n name = test_case.get('name', 'test')\n description = test_case.get('description', '')\n\n stub = f\"\"\"\ndescribe('{{Feature Name}}', () => {{\n it('{name}', () => {{\n // {description}\n\n // Arrange\n // TODO: Set up test data and dependencies\n\n // Act\n // TODO: Execute the code under test\n\n // Assert\n // TODO: Verify expected behavior\n expect(true).toBe(true); // Replace with actual assertion\n }});\n}});\n\"\"\"\n return stub.strip()\n\n def _generate_generic_stub(self, test_case: Dict[str, Any]) -> str:\n \"\"\"Generate generic test stub.\"\"\"\n name = test_case.get('name', 'test')\n description = test_case.get('description', '')\n\n return f\"\"\"\n# Test: {name}\n# Description: {description}\n#\n# TODO: Implement test\n# 1. Arrange: Set up test data\n# 2. Act: Execute code under test\n# 3. Assert: Verify expected behavior\n\"\"\"\n\n def generate_test_file(\n self,\n module_name: str,\n test_cases: Optional[List[Dict[str, Any]]] = None\n ) -> str:\n \"\"\"\n Generate complete test file with all test stubs.\n\n Args:\n module_name: Name of module being tested\n test_cases: List of test cases (uses self.test_cases if not provided)\n\n Returns:\n Complete test file content\n \"\"\"\n cases = test_cases or self.test_cases\n\n if self.framework == TestFramework.JEST:\n return self._generate_jest_file(module_name, cases)\n elif self.framework == TestFramework.PYTEST:\n return self._generate_pytest_file(module_name, cases)\n elif self.framework == TestFramework.JUNIT:\n return self._generate_junit_file(module_name, cases)\n elif self.framework == TestFramework.VITEST:\n return self._generate_vitest_file(module_name, cases)\n else:\n return \"\"\n\n def _generate_jest_file(self, module_name: str, test_cases: List[Dict[str, Any]]) -> str:\n \"\"\"Generate complete Jest test file.\"\"\"\n imports = f\"import {{ {module_name} }} from '../{module_name}';\\n\\n\"\n\n stubs = []\n for test_case in test_cases:\n stubs.append(self._generate_jest_stub(test_case))\n\n return imports + \"\\n\\n\".join(stubs)\n\n def _generate_pytest_file(self, module_name: str, test_cases: List[Dict[str, Any]]) -> str:\n \"\"\"Generate complete Pytest test file.\"\"\"\n imports = f\"import pytest\\nfrom {module_name} import *\\n\\n\\n\"\n\n stubs = []\n for test_case in test_cases:\n stubs.append(self._generate_pytest_stub(test_case))\n\n return imports + \"\\n\\n\\n\".join(stubs)\n\n def _generate_junit_file(self, module_name: str, test_cases: List[Dict[str, Any]]) -> str:\n \"\"\"Generate complete JUnit test file.\"\"\"\n class_name = ''.join(word.capitalize() for word in module_name.split('_'))\n\n imports = \"\"\"import org.junit.jupiter.api.Test;\nimport static org.junit.jupiter.api.Assertions.*;\n\n\"\"\"\n\n class_header = f\"public class {class_name}Test {{\\n\\n\"\n\n stubs = []\n for test_case in test_cases:\n stubs.append(self._generate_junit_stub(test_case))\n\n class_footer = \"\\n}\"\n\n return imports + class_header + \"\\n\\n\".join(stubs) + class_footer\n\n def _generate_vitest_file(self, module_name: str, test_cases: List[Dict[str, Any]]) -> str:\n \"\"\"Generate complete Vitest test file.\"\"\"\n imports = f\"import {{ describe, it, expect }} from 'vitest';\\nimport {{ {module_name} }} from '../{module_name}';\\n\\n\"\n\n stubs = []\n for test_case in test_cases:\n stubs.append(self._generate_vitest_stub(test_case))\n\n return imports + \"\\n\\n\".join(stubs)\n\n def suggest_missing_scenarios(\n self,\n existing_tests: List[str],\n code_analysis: Dict[str, Any]\n ) -> List[Dict[str, Any]]:\n \"\"\"\n Suggest missing test scenarios based on code analysis.\n\n Args:\n existing_tests: List of existing test names\n code_analysis: Analysis of code under test (branches, error paths, etc.)\n\n Returns:\n List of suggested test scenarios\n \"\"\"\n suggestions = []\n\n # Check for untested error conditions\n if 'error_handlers' in code_analysis:\n for error_handler in code_analysis['error_handlers']:\n error_name = error_handler.get('type', 'error')\n if not self._has_test_for(existing_tests, error_name):\n suggestions.append({\n 'name': f\"should_handle_{error_name}\",\n 'type': 'error_case',\n 'reason': 'Error handler exists but no corresponding test',\n 'priority': 'P0'\n })\n\n # Check for untested branches\n if 'conditional_branches' in code_analysis:\n for branch in code_analysis['conditional_branches']:\n branch_name = branch.get('condition', 'condition')\n if not self._has_test_for(existing_tests, branch_name):\n suggestions.append({\n 'name': f\"should_test_{branch_name}_branch\",\n 'type': 'branch_coverage',\n 'reason': 'Conditional branch not fully tested',\n 'priority': 'P1'\n })\n\n # Check for boundary conditions\n if 'input_validation' in code_analysis:\n for validation in code_analysis['input_validation']:\n param = validation.get('parameter', 'input')\n if not self._has_test_for(existing_tests, f\"{param}_boundary\"):\n suggestions.append({\n 'name': f\"should_test_{param}_boundary_values\",\n 'type': 'boundary',\n 'reason': 'Input validation exists but boundary tests missing',\n 'priority': 'P1'\n })\n\n return suggestions\n\n def _has_test_for(self, existing_tests: List[str], keyword: str) -> bool:\n \"\"\"Check if existing tests cover a keyword/scenario.\"\"\"\n keyword_lower = keyword.lower().replace('_', '').replace('-', '')\n for test in existing_tests:\n test_lower = test.lower().replace('_', '').replace('-', '')\n if keyword_lower in test_lower:\n return True\n return False\n","content_type":"text/x-python; charset=utf-8","language":"python","size":14617,"content_sha256":"6ec26f0f29339ab23f0ff65fd140eaec143751759c7ddf360ada988059959346"}],"content_json":{"type":"doc","content":[{"type":"heading","attrs":{"level":1},"content":[{"text":"TDD Guide","type":"text"}]},{"type":"paragraph","content":[{"text":"The agent guides red-green-refactor TDD workflows, generates framework-specific test stubs from requirements, parses coverage reports to identify prioritized gaps, and calculates test quality metrics including smell detection and assertion density. Supports Jest, Pytest, JUnit, Vitest, and Mocha.","type":"text"}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"Quick Start","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"bash"},"content":[{"text":"# Generate test cases from requirements (Python API)\nfrom test_generator import TestGenerator, TestFramework\ngen = TestGenerator(framework=TestFramework.PYTEST, language=\"python\")\ncases = gen.generate_from_requirements(requirements)\n\n# Analyze coverage gaps from LCOV report\nfrom coverage_analyzer import CoverageAnalyzer\nanalyzer = CoverageAnalyzer()\nanalyzer.parse_coverage_report(content, \"lcov\")\ngaps = analyzer.identify_gaps(threshold=80.0)\n\n# Guide TDD cycle\nfrom tdd_workflow import TDDWorkflow\nwf = TDDWorkflow()\nwf.start_cycle(\"User can reset password via email\")","type":"text"}]},{"type":"hr","attrs":{"markup":"---"}},{"type":"heading","attrs":{"level":2},"content":[{"text":"Core Workflows","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Workflow 1: TDD a New Feature","type":"text"}]},{"type":"ordered_list","attrs":{"order":1,"listStyle":"number"},"content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Write a failing test for the feature requirement (RED phase)","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Call ","type":"text"},{"text":"validate_red_phase()","type":"text","marks":[{"type":"code_inline"}]},{"text":" -- confirms test exists and fails","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Write minimal code to make the test pass (GREEN phase)","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Call ","type":"text"},{"text":"validate_green_phase()","type":"text","marks":[{"type":"code_inline"}]},{"text":" -- confirms all tests pass","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Refactor while keeping tests green (REFACTOR phase)","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Call ","type":"text"},{"text":"validate_refactor_phase()","type":"text","marks":[{"type":"code_inline"}]},{"text":" -- confirms tests still pass after cleanup","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Validation checkpoint:","type":"text","marks":[{"type":"strong"}]},{"text":" Each cycle completes in under 10 minutes; zero test smells introduced","type":"text"}]}]}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Workflow 2: Analyze Coverage Gaps","type":"text"}]},{"type":"ordered_list","attrs":{"order":1,"listStyle":"number"},"content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Generate coverage report: ","type":"text"},{"text":"npm test -- --coverage","type":"text","marks":[{"type":"code_inline"}]},{"text":" or ","type":"text"},{"text":"pytest --cov","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Detect format with ","type":"text"},{"text":"detect_format()","type":"text","marks":[{"type":"code_inline"}]},{"text":" and parse with ","type":"text"},{"text":"parse_coverage_report()","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Run ","type":"text"},{"text":"identify_gaps(threshold=80.0)","type":"text","marks":[{"type":"code_inline"}]},{"text":" to get prioritized file list (P0/P1/P2)","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Generate test stubs for P0 files (business-critical, lowest coverage)","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Validation checkpoint:","type":"text","marks":[{"type":"strong"}]},{"text":" Line coverage >= 80%; branch coverage >= 70%; zero P0 gaps in critical paths","type":"text"}]}]}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Workflow 3: Generate Tests from Requirements","type":"text"}]},{"type":"ordered_list","attrs":{"order":1,"listStyle":"number"},"content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Structure requirements as user stories with acceptance criteria","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Call ","type":"text"},{"text":"generate_from_requirements()","type":"text","marks":[{"type":"code_inline"}]},{"text":" with target framework","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Review generated test cases for completeness (happy path, error, edge cases)","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Generate test file with ","type":"text"},{"text":"generate_test_file()","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Validation checkpoint:","type":"text","marks":[{"type":"strong"}]},{"text":" Each acceptance criterion has at least one test; all tests compile","type":"text"}]}]}]},{"type":"hr","attrs":{"markup":"---"}},{"type":"heading","attrs":{"level":2},"content":[{"text":"Tools","type":"text"}]},{"type":"table","attrs":{"layout":null},"content":[{"type":"tr","content":[{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Tool","type":"text"}]}]},{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Purpose","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"test_generator.py","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Generate test cases from requirements/specs","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"coverage_analyzer.py","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Parse LCOV/JSON/XML reports, find gaps","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"tdd_workflow.py","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Guide red-green-refactor cycles","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"framework_adapter.py","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Convert tests between frameworks","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"fixture_generator.py","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Generate test data and mocks with seeds","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"metrics_calculator.py","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Calculate complexity and test quality","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"format_detector.py","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Auto-detect language and framework","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"output_formatter.py","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Format output for CLI/desktop/CI","type":"text"}]}]}]}]},{"type":"hr","attrs":{"markup":"---"}},{"type":"heading","attrs":{"level":2},"content":[{"text":"Anti-Patterns","type":"text"}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Tests that pass immediately","type":"text","marks":[{"type":"strong"}]},{"text":" -- a test with no real assertion or ","type":"text"},{"text":"assert True","type":"text","marks":[{"type":"code_inline"}]},{"text":" skips the RED phase; every test must fail before implementation","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Testing implementation details","type":"text","marks":[{"type":"strong"}]},{"text":" -- coupling tests to internal method names makes refactoring break tests; test behavior and outputs, not internals","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Non-deterministic fixtures","type":"text","marks":[{"type":"strong"}]},{"text":" -- random data without a seed produces different failures across CI runs; always pass ","type":"text"},{"text":"seed=\u003cint>","type":"text","marks":[{"type":"code_inline"}]},{"text":" to ","type":"text"},{"text":"FixtureGenerator","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Skipping the refactor phase","type":"text","marks":[{"type":"strong"}]},{"text":" -- GREEN code that works but is messy accumulates; refactoring is not optional in TDD","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Coverage theater","type":"text","marks":[{"type":"strong"}]},{"text":" -- writing tests that hit lines without meaningful assertions; use ","type":"text"},{"text":"metrics_calculator.py","type":"text","marks":[{"type":"code_inline"}]},{"text":" to detect low assertion density","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Conditional test logic","type":"text","marks":[{"type":"strong"}]},{"text":" -- ","type":"text"},{"text":"if/else","type":"text","marks":[{"type":"code_inline"}]},{"text":" inside tests masks failures; each test should have a single clear path","type":"text"}]}]}]},{"type":"hr","attrs":{"markup":"---"}},{"type":"heading","attrs":{"level":2},"content":[{"text":"Troubleshooting","type":"text"}]},{"type":"table","attrs":{"layout":null},"content":[{"type":"tr","content":[{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Problem","type":"text"}]}]},{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Cause","type":"text"}]}]},{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Solution","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Generated tests pass immediately (no RED phase)","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Test has no real assertion or asserts a trivially true value","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Ensure every test contains an assertion against the actual unit under test; remove placeholder ","type":"text"},{"text":"assert True","type":"text","marks":[{"type":"code_inline"}]},{"text":" stubs before running","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Coverage report fails to parse","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Report format does not match the expected LCOV, JSON, or XML structure","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Run ","type":"text"},{"text":"format_detector.py","type":"text","marks":[{"type":"code_inline"}]},{"text":" first to verify the detected format; convert non-standard reports (e.g., Clover) to Cobertura XML","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Framework adapter produces wrong import style","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Source and target framework were swapped, or language/framework mismatch","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Verify the ","type":"text"},{"text":"framework","type":"text","marks":[{"type":"code_inline"}]},{"text":" and ","type":"text"},{"text":"language","type":"text","marks":[{"type":"code_inline"}]},{"text":" arguments match your project; use ","type":"text"},{"text":"detect_framework()","type":"text","marks":[{"type":"code_inline"}]},{"text":" on existing test code to auto-detect","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Fixture generator produces non-deterministic data","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"No random seed was supplied, so each run yields different values","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Pass ","type":"text"},{"text":"seed=\u003cint>","type":"text","marks":[{"type":"code_inline"}]},{"text":" to ","type":"text"},{"text":"FixtureGenerator()","type":"text","marks":[{"type":"code_inline"}]},{"text":" for reproducible fixtures across CI runs","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Metrics calculator reports 0 test functions","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Test code uses an unsupported naming convention (e.g., ","type":"text"},{"text":"spec_","type":"text","marks":[{"type":"code_inline"}]},{"text":" prefix)","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Rename tests to follow ","type":"text"},{"text":"test_*","type":"text","marks":[{"type":"code_inline"}]},{"text":" / ","type":"text"},{"text":"it()","type":"text","marks":[{"type":"code_inline"}]},{"text":" / ","type":"text"},{"text":"@Test","type":"text","marks":[{"type":"code_inline"}]},{"text":" conventions, or extend the regex patterns in ","type":"text"},{"text":"_count_test_functions()","type":"text","marks":[{"type":"code_inline"}]}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"TDD workflow validates GREEN phase but tests still fail locally","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Test result dict passed to ","type":"text"},{"text":"validate_green_phase()","type":"text","marks":[{"type":"code_inline"}]},{"text":" has ","type":"text"},{"text":"status","type":"text","marks":[{"type":"code_inline"}]},{"text":" not set to ","type":"text"},{"text":"\"passed\"","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Ensure your test runner output is normalized to ","type":"text"},{"text":"{\"status\": \"passed\"}","type":"text","marks":[{"type":"code_inline"}]},{"text":" or ","type":"text"},{"text":"{\"status\": \"failed\"}","type":"text","marks":[{"type":"code_inline"}]},{"text":" before passing it in","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Coverage gaps list is empty despite low overall coverage","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"All individual files meet the threshold even though the aggregate does not","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Lower the ","type":"text"},{"text":"threshold","type":"text","marks":[{"type":"code_inline"}]},{"text":" argument in ","type":"text"},{"text":"identify_gaps()","type":"text","marks":[{"type":"code_inline"}]},{"text":" or inspect per-file coverage with ","type":"text"},{"text":"get_file_coverage()","type":"text","marks":[{"type":"code_inline"}]}]}]}]}]},{"type":"hr","attrs":{"markup":"---"}},{"type":"heading","attrs":{"level":2},"content":[{"text":"Success Criteria","type":"text"}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Test-first ratio above 80%","type":"text","marks":[{"type":"strong"}]},{"text":" -- at least 4 out of every 5 features begin with a failing test before any implementation code is written.","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Red-green-refactor cycle under 10 minutes","type":"text","marks":[{"type":"strong"}]},{"text":" -- each TDD micro-cycle (write failing test, make it pass, refactor) completes within a single focused interval.","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Line coverage at or above 80%","type":"text","marks":[{"type":"strong"}]},{"text":" -- measured by ","type":"text"},{"text":"coverage_analyzer.py","type":"text","marks":[{"type":"code_inline"}]},{"text":" against LCOV/JSON/XML reports, with branch coverage at or above 70%.","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Test quality score at or above 75/100","type":"text","marks":[{"type":"strong"}]},{"text":" -- as reported by ","type":"text"},{"text":"metrics_calculator.py","type":"text","marks":[{"type":"code_inline"}]},{"text":", combining assertion density, isolation, naming quality, and absence of test smells.","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Zero P0 coverage gaps in critical paths","type":"text","marks":[{"type":"strong"}]},{"text":" -- business-critical modules (auth, payments, data persistence) have no files flagged P0 by ","type":"text"},{"text":"identify_gaps()","type":"text","marks":[{"type":"code_inline"}]},{"text":".","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Test smell count of zero for high-severity items","type":"text","marks":[{"type":"strong"}]},{"text":" -- no ","type":"text"},{"text":"missing_assertions","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"sleepy_test","type":"text","marks":[{"type":"code_inline"}]},{"text":", or ","type":"text"},{"text":"conditional_test_logic","type":"text","marks":[{"type":"code_inline"}]},{"text":" smells detected at high severity.","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Fixture reproducibility across CI","type":"text","marks":[{"type":"strong"}]},{"text":" -- all generated fixtures use a fixed seed and produce identical output on every pipeline run.","type":"text"}]}]}]},{"type":"hr","attrs":{"markup":"---"}},{"type":"heading","attrs":{"level":2},"content":[{"text":"Scope & Limitations","type":"text"}]},{"type":"paragraph","content":[{"text":"This skill covers:","type":"text","marks":[{"type":"strong"}]}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Unit test generation, scaffolding, and stub creation for Jest, Pytest, JUnit, Vitest, and Mocha","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Static coverage report parsing (LCOV, JSON/Istanbul, XML/Cobertura) with gap identification and prioritized recommendations","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Red-green-refactor workflow guidance with phase validation and cycle tracking","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Test quality assessment including complexity analysis, isolation scoring, naming quality, and test smell detection","type":"text"}]}]}]},{"type":"paragraph","content":[{"text":"This skill does NOT cover:","type":"text","marks":[{"type":"strong"}]}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Integration, end-to-end, or performance test generation -- see ","type":"text"},{"text":"senior-qa","type":"text","marks":[{"type":"code_inline"}]},{"text":" for E2E patterns and ","type":"text"},{"text":"senior-devops","type":"text","marks":[{"type":"code_inline"}]},{"text":" for load testing","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Runtime test execution or live coverage measurement -- scripts perform static analysis only; you must run your test suite externally","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Visual/snapshot testing or browser-based test workflows -- use Playwright, Cypress, or Storybook for UI-level testing","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Security-focused test generation (fuzz testing, penetration testing) -- see ","type":"text"},{"text":"senior-security","type":"text","marks":[{"type":"code_inline"}]},{"text":" and ","type":"text"},{"text":"senior-secops","type":"text","marks":[{"type":"code_inline"}]},{"text":" skills","type":"text"}]}]}]},{"type":"hr","attrs":{"markup":"---"}},{"type":"heading","attrs":{"level":2},"content":[{"text":"Integration Points","type":"text"}]},{"type":"table","attrs":{"layout":null},"content":[{"type":"tr","content":[{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Skill","type":"text"}]}]},{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Integration","type":"text"}]}]},{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Data Flow","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"senior-qa","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Generated test stubs feed into QA review workflows; QA coverage standards inform threshold settings","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"test_generator.py","type":"text","marks":[{"type":"code_inline"}]},{"text":" output → QA review → approved test suite","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"code-reviewer","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Metrics calculator output provides quantitative data for code review checklists","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"metrics_calculator.py","type":"text","marks":[{"type":"code_inline"}]},{"text":" quality report → code review scoring","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"senior-fullstack","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Scaffolded projects include test infrastructure; TDD guide generates tests for scaffolded modules","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"project_scaffolder.py","type":"text","marks":[{"type":"code_inline"}]},{"text":" output → ","type":"text"},{"text":"test_generator.py","type":"text","marks":[{"type":"code_inline"}]},{"text":" input","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"senior-devops","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Coverage reports from CI pipelines are parsed by coverage analyzer; recommendations feed back into pipeline gates","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"CI coverage artifact → ","type":"text"},{"text":"coverage_analyzer.py","type":"text","marks":[{"type":"code_inline"}]},{"text":" → pass/fail gate","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"senior-security","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Edge-case fixtures for auth and API scenarios complement security-focused test plans","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"fixture_generator.py","type":"text","marks":[{"type":"code_inline"}]},{"text":" auth/API edge cases → security test plan","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"tech-stack-evaluator","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Framework detection informs stack evaluation; test quality metrics feed into technology assessment","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"format_detector.py","type":"text","marks":[{"type":"code_inline"}]},{"text":" analysis → stack evaluation input","type":"text"}]}]}]}]},{"type":"hr","attrs":{"markup":"---"}},{"type":"heading","attrs":{"level":2},"content":[{"text":"Tool Reference","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"1. ","type":"text"},{"text":"test_generator.py","type":"text","marks":[{"type":"code_inline"}]}]},{"type":"paragraph","content":[{"text":"Purpose:","type":"text","marks":[{"type":"strong"}]},{"text":" Generate test cases from requirements, user stories, and API specs, then produce framework-specific test stubs and complete test files.","type":"text"}]},{"type":"paragraph","content":[{"text":"Module:","type":"text","marks":[{"type":"strong"}]},{"text":" ","type":"text"},{"text":"TestGenerator","type":"text","marks":[{"type":"code_inline"}]},{"text":" class","type":"text"}]},{"type":"paragraph","content":[{"text":"Usage:","type":"text","marks":[{"type":"strong"}]}]},{"type":"code_block","attrs":{"wrap":false,"language":"python"},"content":[{"text":"from test_generator import TestGenerator, TestFramework, TestType\n\ngen = TestGenerator(framework=TestFramework.PYTEST, language=\"python\")\ncases = gen.generate_from_requirements(requirements, test_type=TestType.UNIT)\nstub = gen.generate_test_stub(cases[0])\nfile_content = gen.generate_test_file(\"my_module\", cases)\nsuggestions = gen.suggest_missing_scenarios(existing_tests, code_analysis)","type":"text"}]},{"type":"paragraph","content":[{"text":"Constructor Parameters:","type":"text","marks":[{"type":"strong"}]}]},{"type":"table","attrs":{"layout":null},"content":[{"type":"tr","content":[{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Parameter","type":"text"}]}]},{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Type","type":"text"}]}]},{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Required","type":"text"}]}]},{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Description","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"framework","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"TestFramework","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Yes","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Target framework: ","type":"text"},{"text":"JEST","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"VITEST","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"PYTEST","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"JUNIT","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"MOCHA","type":"text","marks":[{"type":"code_inline"}]}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"language","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"str","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Yes","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Programming language: ","type":"text"},{"text":"typescript","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"javascript","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"python","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"java","type":"text","marks":[{"type":"code_inline"}]}]}]}]}]},{"type":"paragraph","content":[{"text":"Key Methods:","type":"text","marks":[{"type":"strong"}]}]},{"type":"table","attrs":{"layout":null},"content":[{"type":"tr","content":[{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Method","type":"text"}]}]},{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Parameters","type":"text"}]}]},{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Returns","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"generate_from_requirements(requirements, test_type)","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"requirements","type":"text","marks":[{"type":"code_inline"}]},{"text":": dict with ","type":"text"},{"text":"user_stories","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"acceptance_criteria","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"api_specs","type":"text","marks":[{"type":"code_inline"}]},{"text":"; ","type":"text"},{"text":"test_type","type":"text","marks":[{"type":"code_inline"}]},{"text":": ","type":"text"},{"text":"TestType","type":"text","marks":[{"type":"code_inline"}]},{"text":" enum (default ","type":"text"},{"text":"UNIT","type":"text","marks":[{"type":"code_inline"}]},{"text":")","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"List[Dict]","type":"text","marks":[{"type":"code_inline"}]},{"text":" of test case specs","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"generate_test_stub(test_case)","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"test_case","type":"text","marks":[{"type":"code_inline"}]},{"text":": single test case dict","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"str","type":"text","marks":[{"type":"code_inline"}]},{"text":" -- framework-specific test stub code","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"generate_test_file(module_name, test_cases)","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"module_name","type":"text","marks":[{"type":"code_inline"}]},{"text":": str; ","type":"text"},{"text":"test_cases","type":"text","marks":[{"type":"code_inline"}]},{"text":": optional list (uses stored cases if omitted)","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"str","type":"text","marks":[{"type":"code_inline"}]},{"text":" -- complete test file with imports","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"suggest_missing_scenarios(existing_tests, code_analysis)","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"existing_tests","type":"text","marks":[{"type":"code_inline"}]},{"text":": list of test name strings; ","type":"text"},{"text":"code_analysis","type":"text","marks":[{"type":"code_inline"}]},{"text":": dict with ","type":"text"},{"text":"error_handlers","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"conditional_branches","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"input_validation","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"List[Dict]","type":"text","marks":[{"type":"code_inline"}]},{"text":" of suggested test scenarios","type":"text"}]}]}]}]},{"type":"paragraph","content":[{"text":"Output Formats:","type":"text","marks":[{"type":"strong"}]},{"text":" Python dict/list (test case specifications), string (generated code).","type":"text"}]},{"type":"paragraph","content":[{"text":"Example:","type":"text","marks":[{"type":"strong"}]}]},{"type":"code_block","attrs":{"wrap":false,"language":"python"},"content":[{"text":"requirements = {\n \"user_stories\": [{\"action\": \"login\", \"given\": [\"valid credentials\"], \"when\": \"submit form\", \"then\": \"redirect to dashboard\"}],\n \"api_specs\": [{\"method\": \"POST\", \"path\": \"/auth/login\", \"requires_auth\": False, \"required_params\": [\"email\", \"password\"]}]\n}\ngen = TestGenerator(framework=TestFramework.JEST, language=\"typescript\")\ncases = gen.generate_from_requirements(requirements)\nprint(gen.generate_test_file(\"auth_service\", cases))","type":"text"}]},{"type":"hr","attrs":{"markup":"---"}},{"type":"heading","attrs":{"level":3},"content":[{"text":"2. ","type":"text"},{"text":"coverage_analyzer.py","type":"text","marks":[{"type":"code_inline"}]}]},{"type":"paragraph","content":[{"text":"Purpose:","type":"text","marks":[{"type":"strong"}]},{"text":" Parse coverage reports in LCOV, JSON (Istanbul/nyc), and XML (Cobertura) formats. Calculate summary metrics, identify files below threshold, and generate prioritized recommendations.","type":"text"}]},{"type":"paragraph","content":[{"text":"Module:","type":"text","marks":[{"type":"strong"}]},{"text":" ","type":"text"},{"text":"CoverageAnalyzer","type":"text","marks":[{"type":"code_inline"}]},{"text":" class","type":"text"}]},{"type":"paragraph","content":[{"text":"Usage:","type":"text","marks":[{"type":"strong"}]}]},{"type":"code_block","attrs":{"wrap":false,"language":"python"},"content":[{"text":"from coverage_analyzer import CoverageAnalyzer\n\nanalyzer = CoverageAnalyzer()\ndata = analyzer.parse_coverage_report(report_content, format_type=\"lcov\")\nsummary = analyzer.calculate_summary()\ngaps = analyzer.identify_gaps(threshold=80.0)\nrecs = analyzer.generate_recommendations()\nfile_detail = analyzer.get_file_coverage(\"src/auth.ts\")\ndetected = analyzer.detect_format(raw_content)","type":"text"}]},{"type":"paragraph","content":[{"text":"Constructor Parameters:","type":"text","marks":[{"type":"strong"}]},{"text":" None.","type":"text"}]},{"type":"paragraph","content":[{"text":"Key Methods:","type":"text","marks":[{"type":"strong"}]}]},{"type":"table","attrs":{"layout":null},"content":[{"type":"tr","content":[{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Method","type":"text"}]}]},{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Parameters","type":"text"}]}]},{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Returns","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"parse_coverage_report(report_content, format_type)","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"report_content","type":"text","marks":[{"type":"code_inline"}]},{"text":": str; ","type":"text"},{"text":"format_type","type":"text","marks":[{"type":"code_inline"}]},{"text":": ","type":"text"},{"text":"\"lcov\"","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"\"json\"","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"\"xml\"","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"\"cobertura\"","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Dict","type":"text","marks":[{"type":"code_inline"}]},{"text":" of per-file coverage data","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"calculate_summary()","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"None","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Dict","type":"text","marks":[{"type":"code_inline"}]},{"text":" with ","type":"text"},{"text":"line_coverage","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"branch_coverage","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"function_coverage","type":"text","marks":[{"type":"code_inline"}]},{"text":", totals","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"identify_gaps(threshold)","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"threshold","type":"text","marks":[{"type":"code_inline"}]},{"text":": float (default ","type":"text"},{"text":"80.0","type":"text","marks":[{"type":"code_inline"}]},{"text":")","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"List[Dict]","type":"text","marks":[{"type":"code_inline"}]},{"text":" of files below threshold with priority P0/P1/P2","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"generate_recommendations()","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"None","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"List[Dict]","type":"text","marks":[{"type":"code_inline"}]},{"text":" of prioritized recommendations","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"get_file_coverage(file_path)","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"file_path","type":"text","marks":[{"type":"code_inline"}]},{"text":": str","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Dict","type":"text","marks":[{"type":"code_inline"}]},{"text":" with per-file line/branch/function coverage","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"detect_format(content)","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"content","type":"text","marks":[{"type":"code_inline"}]},{"text":": str","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"str","type":"text","marks":[{"type":"code_inline"}]},{"text":" -- ","type":"text"},{"text":"\"lcov\"","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"\"json\"","type":"text","marks":[{"type":"code_inline"}]},{"text":", or ","type":"text"},{"text":"\"xml\"","type":"text","marks":[{"type":"code_inline"}]}]}]}]}]},{"type":"paragraph","content":[{"text":"Output Formats:","type":"text","marks":[{"type":"strong"}]},{"text":" Python dict/list. Use ","type":"text"},{"text":"output_formatter.py","type":"text","marks":[{"type":"code_inline"}]},{"text":" for terminal/markdown/JSON rendering.","type":"text"}]},{"type":"paragraph","content":[{"text":"Example:","type":"text","marks":[{"type":"strong"}]}]},{"type":"code_block","attrs":{"wrap":false,"language":"python"},"content":[{"text":"with open(\"coverage/lcov.info\") as f:\n content = f.read()\nanalyzer = CoverageAnalyzer()\nfmt = analyzer.detect_format(content)\nanalyzer.parse_coverage_report(content, fmt)\nsummary = analyzer.calculate_summary()\n# {'line_coverage': 76.5, 'branch_coverage': 62.3, ...}\ngaps = analyzer.identify_gaps(threshold=80.0)\n# [{'file': 'src/auth.ts', 'line_coverage': 45.0, 'priority': 'P0', ...}]","type":"text"}]},{"type":"hr","attrs":{"markup":"---"}},{"type":"heading","attrs":{"level":3},"content":[{"text":"3. ","type":"text"},{"text":"tdd_workflow.py","type":"text","marks":[{"type":"code_inline"}]}]},{"type":"paragraph","content":[{"text":"Purpose:","type":"text","marks":[{"type":"strong"}]},{"text":" Guide users through red-green-refactor TDD cycles with phase validation, workflow state tracking, and refactoring suggestions.","type":"text"}]},{"type":"paragraph","content":[{"text":"Module:","type":"text","marks":[{"type":"strong"}]},{"text":" ","type":"text"},{"text":"TDDWorkflow","type":"text","marks":[{"type":"code_inline"}]},{"text":" class","type":"text"}]},{"type":"paragraph","content":[{"text":"Usage:","type":"text","marks":[{"type":"strong"}]}]},{"type":"code_block","attrs":{"wrap":false,"language":"python"},"content":[{"text":"from tdd_workflow import TDDWorkflow\n\nwf = TDDWorkflow()\nguidance = wf.start_cycle(\"User can reset password via email\")\nred_result = wf.validate_red_phase(test_code, test_result={\"status\": \"failed\"})\ngreen_result = wf.validate_green_phase(impl_code, {\"status\": \"passed\"})\nrefactor_result = wf.validate_refactor_phase(original, refactored, {\"status\": \"passed\"})\nphase_guide = wf.get_phase_guidance()\nsummary = wf.generate_workflow_summary()","type":"text"}]},{"type":"paragraph","content":[{"text":"Constructor Parameters:","type":"text","marks":[{"type":"strong"}]},{"text":" None.","type":"text"}]},{"type":"paragraph","content":[{"text":"Key Methods:","type":"text","marks":[{"type":"strong"}]}]},{"type":"table","attrs":{"layout":null},"content":[{"type":"tr","content":[{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Method","type":"text"}]}]},{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Parameters","type":"text"}]}]},{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Returns","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"start_cycle(requirement)","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"requirement","type":"text","marks":[{"type":"code_inline"}]},{"text":": str -- user story or feature description","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Dict","type":"text","marks":[{"type":"code_inline"}]},{"text":" with phase, instruction, checklist, tips","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"validate_red_phase(test_code, test_result)","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"test_code","type":"text","marks":[{"type":"code_inline"}]},{"text":": str; ","type":"text"},{"text":"test_result","type":"text","marks":[{"type":"code_inline"}]},{"text":": optional dict with ","type":"text"},{"text":"status","type":"text","marks":[{"type":"code_inline"}]},{"text":" key","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Dict","type":"text","marks":[{"type":"code_inline"}]},{"text":" with ","type":"text"},{"text":"phase_complete","type":"text","marks":[{"type":"code_inline"}]},{"text":", validations, next instruction","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"validate_green_phase(implementation_code, test_result)","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"implementation_code","type":"text","marks":[{"type":"code_inline"}]},{"text":": str; ","type":"text"},{"text":"test_result","type":"text","marks":[{"type":"code_inline"}]},{"text":": dict with ","type":"text"},{"text":"status","type":"text","marks":[{"type":"code_inline"}]},{"text":" key","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Dict","type":"text","marks":[{"type":"code_inline"}]},{"text":" with ","type":"text"},{"text":"phase_complete","type":"text","marks":[{"type":"code_inline"}]},{"text":", validations, ","type":"text"},{"text":"refactoring_suggestions","type":"text","marks":[{"type":"code_inline"}]}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"validate_refactor_phase(original_code, refactored_code, test_result)","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"original_code","type":"text","marks":[{"type":"code_inline"}]},{"text":": str; ","type":"text"},{"text":"refactored_code","type":"text","marks":[{"type":"code_inline"}]},{"text":": str; ","type":"text"},{"text":"test_result","type":"text","marks":[{"type":"code_inline"}]},{"text":": dict with ","type":"text"},{"text":"status","type":"text","marks":[{"type":"code_inline"}]},{"text":" key","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Dict","type":"text","marks":[{"type":"code_inline"}]},{"text":" with ","type":"text"},{"text":"phase_complete","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"cycle_complete","type":"text","marks":[{"type":"code_inline"}]},{"text":", next steps","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"get_phase_guidance(phase)","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"phase","type":"text","marks":[{"type":"code_inline"}]},{"text":": optional ","type":"text"},{"text":"TDDPhase","type":"text","marks":[{"type":"code_inline"}]},{"text":" enum (uses current phase if omitted)","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Dict","type":"text","marks":[{"type":"code_inline"}]},{"text":" with goal, steps, common mistakes, tips","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"generate_workflow_summary()","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"None","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"str","type":"text","marks":[{"type":"code_inline"}]},{"text":" -- markdown summary of current state and completed cycles","type":"text"}]}]}]}]},{"type":"paragraph","content":[{"text":"Output Formats:","type":"text","marks":[{"type":"strong"}]},{"text":" Python dict (validation results), string (summary).","type":"text"}]},{"type":"paragraph","content":[{"text":"Example:","type":"text","marks":[{"type":"strong"}]}]},{"type":"code_block","attrs":{"wrap":false,"language":"python"},"content":[{"text":"wf = TDDWorkflow()\nwf.start_cycle(\"Add email validation to signup form\")\nresult = wf.validate_red_phase(\"def test_invalid_email():\\n assert validate('bad') == False\", {\"status\": \"failed\"})\n# {'phase_complete': True, 'next_phase': 'GREEN', ...}","type":"text"}]},{"type":"hr","attrs":{"markup":"---"}},{"type":"heading","attrs":{"level":3},"content":[{"text":"4. ","type":"text"},{"text":"framework_adapter.py","type":"text","marks":[{"type":"code_inline"}]}]},{"type":"paragraph","content":[{"text":"Purpose:","type":"text","marks":[{"type":"strong"}]},{"text":" Provide multi-framework support with adapters for Jest, Vitest, Pytest, unittest, JUnit, TestNG, Mocha, and Jasmine. Generate framework-specific imports, test suites, test functions, assertions, and setup/teardown hooks.","type":"text"}]},{"type":"paragraph","content":[{"text":"Module:","type":"text","marks":[{"type":"strong"}]},{"text":" ","type":"text"},{"text":"FrameworkAdapter","type":"text","marks":[{"type":"code_inline"}]},{"text":" class","type":"text"}]},{"type":"paragraph","content":[{"text":"Usage:","type":"text","marks":[{"type":"strong"}]}]},{"type":"code_block","attrs":{"wrap":false,"language":"python"},"content":[{"text":"from framework_adapter import FrameworkAdapter, Framework, Language\n\nadapter = FrameworkAdapter(framework=Framework.JEST, language=Language.TYPESCRIPT)\nimports = adapter.generate_imports()\nsuite = adapter.generate_test_suite_wrapper(\"AuthService\", test_content)\ntest_fn = adapter.generate_test_function(\"should reject invalid email\", body, \"Validates email format\")\nassertion = adapter.generate_assertion(\"result\", \"true\", \"true\")\nhooks = adapter.generate_setup_teardown(setup_code=\"db = create_test_db()\", teardown_code=\"db.close()\")\ndetected = adapter.detect_framework(existing_code)","type":"text"}]},{"type":"paragraph","content":[{"text":"Constructor Parameters:","type":"text","marks":[{"type":"strong"}]}]},{"type":"table","attrs":{"layout":null},"content":[{"type":"tr","content":[{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Parameter","type":"text"}]}]},{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Type","type":"text"}]}]},{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Required","type":"text"}]}]},{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Description","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"framework","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Framework","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Yes","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"JEST","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"VITEST","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"PYTEST","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"UNITTEST","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"JUNIT","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"TESTNG","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"MOCHA","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"JASMINE","type":"text","marks":[{"type":"code_inline"}]}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"language","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Language","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Yes","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"TYPESCRIPT","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"JAVASCRIPT","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"PYTHON","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"JAVA","type":"text","marks":[{"type":"code_inline"}]}]}]}]}]},{"type":"paragraph","content":[{"text":"Key Methods:","type":"text","marks":[{"type":"strong"}]}]},{"type":"table","attrs":{"layout":null},"content":[{"type":"tr","content":[{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Method","type":"text"}]}]},{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Parameters","type":"text"}]}]},{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Returns","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"generate_imports()","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"None","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"str","type":"text","marks":[{"type":"code_inline"}]},{"text":" -- framework-specific import statements","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"generate_test_suite_wrapper(suite_name, test_content)","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"suite_name","type":"text","marks":[{"type":"code_inline"}]},{"text":": str; ","type":"text"},{"text":"test_content","type":"text","marks":[{"type":"code_inline"}]},{"text":": str","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"str","type":"text","marks":[{"type":"code_inline"}]},{"text":" -- complete test suite wrapping content","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"generate_test_function(test_name, test_body, description)","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"test_name","type":"text","marks":[{"type":"code_inline"}]},{"text":": str; ","type":"text"},{"text":"test_body","type":"text","marks":[{"type":"code_inline"}]},{"text":": str; ","type":"text"},{"text":"description","type":"text","marks":[{"type":"code_inline"}]},{"text":": str (default ","type":"text"},{"text":"\"\"","type":"text","marks":[{"type":"code_inline"}]},{"text":")","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"str","type":"text","marks":[{"type":"code_inline"}]},{"text":" -- complete test function","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"generate_assertion(actual, expected, assertion_type)","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"actual","type":"text","marks":[{"type":"code_inline"}]},{"text":": str; ","type":"text"},{"text":"expected","type":"text","marks":[{"type":"code_inline"}]},{"text":": str; ","type":"text"},{"text":"assertion_type","type":"text","marks":[{"type":"code_inline"}]},{"text":": ","type":"text"},{"text":"\"equals\"","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"\"not_equals\"","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"\"true\"","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"\"false\"","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"\"throws\"","type":"text","marks":[{"type":"code_inline"}]},{"text":" (default ","type":"text"},{"text":"\"equals\"","type":"text","marks":[{"type":"code_inline"}]},{"text":")","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"str","type":"text","marks":[{"type":"code_inline"}]},{"text":" -- assertion statement","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"generate_setup_teardown(setup_code, teardown_code)","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"setup_code","type":"text","marks":[{"type":"code_inline"}]},{"text":": str (default ","type":"text"},{"text":"\"\"","type":"text","marks":[{"type":"code_inline"}]},{"text":"); ","type":"text"},{"text":"teardown_code","type":"text","marks":[{"type":"code_inline"}]},{"text":": str (default ","type":"text"},{"text":"\"\"","type":"text","marks":[{"type":"code_inline"}]},{"text":")","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"str","type":"text","marks":[{"type":"code_inline"}]},{"text":" -- setup/teardown hooks","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"detect_framework(code)","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"code","type":"text","marks":[{"type":"code_inline"}]},{"text":": str","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Framework","type":"text","marks":[{"type":"code_inline"}]},{"text":" enum or ","type":"text"},{"text":"None","type":"text","marks":[{"type":"code_inline"}]}]}]}]}]},{"type":"paragraph","content":[{"text":"Output Formats:","type":"text","marks":[{"type":"strong"}]},{"text":" String (generated code).","type":"text"}]},{"type":"paragraph","content":[{"text":"Example:","type":"text","marks":[{"type":"strong"}]}]},{"type":"code_block","attrs":{"wrap":false,"language":"python"},"content":[{"text":"adapter = FrameworkAdapter(Framework.PYTEST, Language.PYTHON)\nprint(adapter.generate_imports())\n# import pytest\nprint(adapter.generate_assertion(\"calculate_total(items)\", \"150.0\", \"equals\"))\n# assert calculate_total(items) == 150.0","type":"text"}]},{"type":"hr","attrs":{"markup":"---"}},{"type":"heading","attrs":{"level":3},"content":[{"text":"5. ","type":"text"},{"text":"fixture_generator.py","type":"text","marks":[{"type":"code_inline"}]}]},{"type":"paragraph","content":[{"text":"Purpose:","type":"text","marks":[{"type":"strong"}]},{"text":" Generate realistic test data, boundary values, edge-case scenarios, and mock objects for various domains (auth, payment, form, API, file upload).","type":"text"}]},{"type":"paragraph","content":[{"text":"Module:","type":"text","marks":[{"type":"strong"}]},{"text":" ","type":"text"},{"text":"FixtureGenerator","type":"text","marks":[{"type":"code_inline"}]},{"text":" class","type":"text"}]},{"type":"paragraph","content":[{"text":"Usage:","type":"text","marks":[{"type":"strong"}]}]},{"type":"code_block","attrs":{"wrap":false,"language":"python"},"content":[{"text":"from fixture_generator import FixtureGenerator\n\ngen = FixtureGenerator(seed=42)\nboundaries = gen.generate_boundary_values(\"int\", {\"min\": 0, \"max\": 255})\nedge_cases = gen.generate_edge_cases(\"auth\")\nmocks = gen.generate_mock_data(schema, count=5)\nfixture_content = gen.generate_fixture_file(\"users\", mocks, format=\"json\")","type":"text"}]},{"type":"paragraph","content":[{"text":"Constructor Parameters:","type":"text","marks":[{"type":"strong"}]}]},{"type":"table","attrs":{"layout":null},"content":[{"type":"tr","content":[{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Parameter","type":"text"}]}]},{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Type","type":"text"}]}]},{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Required","type":"text"}]}]},{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Description","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"seed","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"int","type":"text","marks":[{"type":"code_inline"}]},{"text":" or ","type":"text"},{"text":"None","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"No","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Random seed for reproducible output (default ","type":"text"},{"text":"None","type":"text","marks":[{"type":"code_inline"}]},{"text":")","type":"text"}]}]}]}]},{"type":"paragraph","content":[{"text":"Key Methods:","type":"text","marks":[{"type":"strong"}]}]},{"type":"table","attrs":{"layout":null},"content":[{"type":"tr","content":[{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Method","type":"text"}]}]},{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Parameters","type":"text"}]}]},{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Returns","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"generate_boundary_values(data_type, constraints)","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"data_type","type":"text","marks":[{"type":"code_inline"}]},{"text":": ","type":"text"},{"text":"\"int\"","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"\"string\"","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"\"array\"","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"\"date\"","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"\"email\"","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"\"url\"","type":"text","marks":[{"type":"code_inline"}]},{"text":"; ","type":"text"},{"text":"constraints","type":"text","marks":[{"type":"code_inline"}]},{"text":": optional dict (","type":"text"},{"text":"min","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"max","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"min_length","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"max_length","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"min_size","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"max_size","type":"text","marks":[{"type":"code_inline"}]},{"text":")","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"List","type":"text","marks":[{"type":"code_inline"}]},{"text":" of boundary values","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"generate_edge_cases(scenario, context)","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"scenario","type":"text","marks":[{"type":"code_inline"}]},{"text":": ","type":"text"},{"text":"\"auth\"","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"\"payment\"","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"\"form\"","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"\"api\"","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"\"file_upload\"","type":"text","marks":[{"type":"code_inline"}]},{"text":"; ","type":"text"},{"text":"context","type":"text","marks":[{"type":"code_inline"}]},{"text":": optional dict (required for ","type":"text"},{"text":"\"form\"","type":"text","marks":[{"type":"code_inline"}]},{"text":" with ","type":"text"},{"text":"fields","type":"text","marks":[{"type":"code_inline"}]},{"text":" key)","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"List[Dict]","type":"text","marks":[{"type":"code_inline"}]},{"text":" of edge case scenarios","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"generate_mock_data(schema, count)","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"schema","type":"text","marks":[{"type":"code_inline"}]},{"text":": dict mapping field names to ","type":"text"},{"text":"{\"type\": ...}","type":"text","marks":[{"type":"code_inline"}]},{"text":" defs; ","type":"text"},{"text":"count","type":"text","marks":[{"type":"code_inline"}]},{"text":": int (default ","type":"text"},{"text":"1","type":"text","marks":[{"type":"code_inline"}]},{"text":")","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"List[Dict]","type":"text","marks":[{"type":"code_inline"}]},{"text":" of mock objects","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"generate_fixture_file(fixture_name, data, format)","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"fixture_name","type":"text","marks":[{"type":"code_inline"}]},{"text":": str; ","type":"text"},{"text":"data","type":"text","marks":[{"type":"code_inline"}]},{"text":": any; ","type":"text"},{"text":"format","type":"text","marks":[{"type":"code_inline"}]},{"text":": ","type":"text"},{"text":"\"json\"","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"\"python\"","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"\"yaml\"","type":"text","marks":[{"type":"code_inline"}]},{"text":" (default ","type":"text"},{"text":"\"json\"","type":"text","marks":[{"type":"code_inline"}]},{"text":")","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"str","type":"text","marks":[{"type":"code_inline"}]},{"text":" -- fixture file content","type":"text"}]}]}]}]},{"type":"paragraph","content":[{"text":"Supported Schema Field Types:","type":"text","marks":[{"type":"strong"}]},{"text":" ","type":"text"},{"text":"string","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"int","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"float","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"bool","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"email","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"date","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"array","type":"text","marks":[{"type":"code_inline"}]},{"text":".","type":"text"}]},{"type":"paragraph","content":[{"text":"Output Formats:","type":"text","marks":[{"type":"strong"}]},{"text":" Python list/dict (data), string (file content in JSON/Python/YAML).","type":"text"}]},{"type":"paragraph","content":[{"text":"Example:","type":"text","marks":[{"type":"strong"}]}]},{"type":"code_block","attrs":{"wrap":false,"language":"python"},"content":[{"text":"gen = FixtureGenerator(seed=123)\nschema = {\n \"id\": {\"type\": \"int\", \"min\": 1, \"max\": 9999},\n \"email\": {\"type\": \"email\"},\n \"active\": {\"type\": \"bool\"}\n}\nusers = gen.generate_mock_data(schema, count=3)\nprint(gen.generate_fixture_file(\"test_users\", users, format=\"json\"))","type":"text"}]},{"type":"hr","attrs":{"markup":"---"}},{"type":"heading","attrs":{"level":3},"content":[{"text":"6. ","type":"text"},{"text":"metrics_calculator.py","type":"text","marks":[{"type":"code_inline"}]}]},{"type":"paragraph","content":[{"text":"Purpose:","type":"text","marks":[{"type":"strong"}]},{"text":" Calculate comprehensive test and code quality metrics including cyclomatic/cognitive complexity, testability scoring, test quality assessment (assertions, isolation, naming, smells), and execution analysis.","type":"text"}]},{"type":"paragraph","content":[{"text":"Module:","type":"text","marks":[{"type":"strong"}]},{"text":" ","type":"text"},{"text":"MetricsCalculator","type":"text","marks":[{"type":"code_inline"}]},{"text":" class","type":"text"}]},{"type":"paragraph","content":[{"text":"Usage:","type":"text","marks":[{"type":"strong"}]}]},{"type":"code_block","attrs":{"wrap":false,"language":"python"},"content":[{"text":"from metrics_calculator import MetricsCalculator\n\ncalc = MetricsCalculator()\nall_metrics = calc.calculate_all_metrics(source_code, test_code, coverage_data, execution_data)\ncomplexity = calc.calculate_complexity(source_code)\ntest_quality = calc.calculate_test_quality(test_code)\nexecution = calc.analyze_execution_metrics(execution_data)\nsummary = calc.generate_metrics_summary()","type":"text"}]},{"type":"paragraph","content":[{"text":"Constructor Parameters:","type":"text","marks":[{"type":"strong"}]},{"text":" None.","type":"text"}]},{"type":"paragraph","content":[{"text":"Key Methods:","type":"text","marks":[{"type":"strong"}]}]},{"type":"table","attrs":{"layout":null},"content":[{"type":"tr","content":[{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Method","type":"text"}]}]},{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Parameters","type":"text"}]}]},{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Returns","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"calculate_all_metrics(source_code, test_code, coverage_data, execution_data)","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"source_code","type":"text","marks":[{"type":"code_inline"}]},{"text":": str; ","type":"text"},{"text":"test_code","type":"text","marks":[{"type":"code_inline"}]},{"text":": str; ","type":"text"},{"text":"coverage_data","type":"text","marks":[{"type":"code_inline"}]},{"text":": optional dict; ","type":"text"},{"text":"execution_data","type":"text","marks":[{"type":"code_inline"}]},{"text":": optional dict","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Dict","type":"text","marks":[{"type":"code_inline"}]},{"text":" with ","type":"text"},{"text":"complexity","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"test_quality","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"coverage","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"execution","type":"text","marks":[{"type":"code_inline"}]}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"calculate_complexity(code)","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"code","type":"text","marks":[{"type":"code_inline"}]},{"text":": str","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Dict","type":"text","marks":[{"type":"code_inline"}]},{"text":" with ","type":"text"},{"text":"cyclomatic_complexity","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"cognitive_complexity","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"testability_score","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"assessment","type":"text","marks":[{"type":"code_inline"}]}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"calculate_test_quality(test_code)","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"test_code","type":"text","marks":[{"type":"code_inline"}]},{"text":": str","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Dict","type":"text","marks":[{"type":"code_inline"}]},{"text":" with ","type":"text"},{"text":"total_tests","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"total_assertions","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"avg_assertions_per_test","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"isolation_score","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"naming_quality","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"test_smells","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"quality_score","type":"text","marks":[{"type":"code_inline"}]}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"analyze_execution_metrics(execution_data)","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"execution_data","type":"text","marks":[{"type":"code_inline"}]},{"text":": dict with ","type":"text"},{"text":"tests","type":"text","marks":[{"type":"code_inline"}]},{"text":" list (each having ","type":"text"},{"text":"duration","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"status","type":"text","marks":[{"type":"code_inline"}]},{"text":", optional ","type":"text"},{"text":"failure_rate","type":"text","marks":[{"type":"code_inline"}]},{"text":")","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Dict","type":"text","marks":[{"type":"code_inline"}]},{"text":" with ","type":"text"},{"text":"total_tests","type":"text","marks":[{"type":"code_inline"}]},{"text":", timing stats, ","type":"text"},{"text":"slow_tests","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"flaky_tests","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"pass_rate","type":"text","marks":[{"type":"code_inline"}]}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"generate_metrics_summary()","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"None","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"str","type":"text","marks":[{"type":"code_inline"}]},{"text":" -- human-readable markdown summary","type":"text"}]}]}]}]},{"type":"paragraph","content":[{"text":"Output Formats:","type":"text","marks":[{"type":"strong"}]},{"text":" Python dict (metrics data), string (markdown summary).","type":"text"}]},{"type":"paragraph","content":[{"text":"Example:","type":"text","marks":[{"type":"strong"}]}]},{"type":"code_block","attrs":{"wrap":false,"language":"python"},"content":[{"text":"calc = MetricsCalculator()\ncomplexity = calc.calculate_complexity(open(\"src/auth.py\").read())\n# {'cyclomatic_complexity': 8, 'cognitive_complexity': 12, 'testability_score': 82.0, 'assessment': 'Medium complexity - moderately testable'}\nquality = calc.calculate_test_quality(open(\"tests/test_auth.py\").read())\n# {'quality_score': 78.5, 'test_smells': [], ...}","type":"text"}]},{"type":"hr","attrs":{"markup":"---"}},{"type":"heading","attrs":{"level":3},"content":[{"text":"7. ","type":"text"},{"text":"format_detector.py","type":"text","marks":[{"type":"code_inline"}]}]},{"type":"paragraph","content":[{"text":"Purpose:","type":"text","marks":[{"type":"strong"}]},{"text":" Automatically detect programming language, testing framework, coverage report format, and project structure from code content or file paths.","type":"text"}]},{"type":"paragraph","content":[{"text":"Module:","type":"text","marks":[{"type":"strong"}]},{"text":" ","type":"text"},{"text":"FormatDetector","type":"text","marks":[{"type":"code_inline"}]},{"text":" class","type":"text"}]},{"type":"paragraph","content":[{"text":"Usage:","type":"text","marks":[{"type":"strong"}]}]},{"type":"code_block","attrs":{"wrap":false,"language":"python"},"content":[{"text":"from format_detector import FormatDetector\n\ndetector = FormatDetector()\nlanguage = detector.detect_language(code)\nframework = detector.detect_test_framework(test_code)\ncov_format = detector.detect_coverage_format(report_content)\ninput_info = detector.detect_input_format(raw_input)\nfile_info = detector.extract_file_info(\"/src/auth.service.ts\")\ntest_name = detector.suggest_test_file_name(\"auth.service.ts\", \"jest\")\npatterns = detector.identify_test_patterns(test_code)\nproject = detector.analyze_project_structure(file_path_list)\nenv = detector.detect_environment()","type":"text"}]},{"type":"paragraph","content":[{"text":"Constructor Parameters:","type":"text","marks":[{"type":"strong"}]},{"text":" None.","type":"text"}]},{"type":"paragraph","content":[{"text":"Key Methods:","type":"text","marks":[{"type":"strong"}]}]},{"type":"table","attrs":{"layout":null},"content":[{"type":"tr","content":[{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Method","type":"text"}]}]},{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Parameters","type":"text"}]}]},{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Returns","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"detect_language(code)","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"code","type":"text","marks":[{"type":"code_inline"}]},{"text":": str","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"str","type":"text","marks":[{"type":"code_inline"}]},{"text":" -- ","type":"text"},{"text":"\"typescript\"","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"\"javascript\"","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"\"python\"","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"\"java\"","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"\"unknown\"","type":"text","marks":[{"type":"code_inline"}]}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"detect_test_framework(code)","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"code","type":"text","marks":[{"type":"code_inline"}]},{"text":": str","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"str","type":"text","marks":[{"type":"code_inline"}]},{"text":" -- ","type":"text"},{"text":"\"jest\"","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"\"vitest\"","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"\"pytest\"","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"\"unittest\"","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"\"junit\"","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"\"mocha\"","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"\"unknown\"","type":"text","marks":[{"type":"code_inline"}]}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"detect_coverage_format(content)","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"content","type":"text","marks":[{"type":"code_inline"}]},{"text":": str","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"str","type":"text","marks":[{"type":"code_inline"}]},{"text":" -- ","type":"text"},{"text":"\"lcov\"","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"\"json\"","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"\"xml\"","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"\"unknown\"","type":"text","marks":[{"type":"code_inline"}]}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"detect_input_format(input_data)","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"input_data","type":"text","marks":[{"type":"code_inline"}]},{"text":": str","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Dict","type":"text","marks":[{"type":"code_inline"}]},{"text":" with ","type":"text"},{"text":"format","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"language","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"framework","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"content_type","type":"text","marks":[{"type":"code_inline"}]}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"extract_file_info(file_path)","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"file_path","type":"text","marks":[{"type":"code_inline"}]},{"text":": str","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Dict","type":"text","marks":[{"type":"code_inline"}]},{"text":" with ","type":"text"},{"text":"file_name","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"extension","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"language","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"is_test","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"purpose","type":"text","marks":[{"type":"code_inline"}]}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"suggest_test_file_name(source_file, framework)","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"source_file","type":"text","marks":[{"type":"code_inline"}]},{"text":": str; ","type":"text"},{"text":"framework","type":"text","marks":[{"type":"code_inline"}]},{"text":": str","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"str","type":"text","marks":[{"type":"code_inline"}]},{"text":" -- suggested test file name","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"identify_test_patterns(code)","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"code","type":"text","marks":[{"type":"code_inline"}]},{"text":": str","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"List[str]","type":"text","marks":[{"type":"code_inline"}]},{"text":" of detected patterns (AAA, Given-When-Then, etc.)","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"analyze_project_structure(file_paths)","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"file_paths","type":"text","marks":[{"type":"code_inline"}]},{"text":": list of str","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Dict","type":"text","marks":[{"type":"code_inline"}]},{"text":" with ","type":"text"},{"text":"primary_language","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"test_ratio","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"suggested_framework","type":"text","marks":[{"type":"code_inline"}]}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"detect_environment()","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"None","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Dict","type":"text","marks":[{"type":"code_inline"}]},{"text":" with ","type":"text"},{"text":"environment","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"output_preference","type":"text","marks":[{"type":"code_inline"}]}]}]}]}]},{"type":"paragraph","content":[{"text":"Output Formats:","type":"text","marks":[{"type":"strong"}]},{"text":" String (detection result), Python dict (detailed analysis).","type":"text"}]},{"type":"paragraph","content":[{"text":"Example:","type":"text","marks":[{"type":"strong"}]}]},{"type":"code_block","attrs":{"wrap":false,"language":"python"},"content":[{"text":"detector = FormatDetector()\nprint(detector.detect_language(\"const add = (a: number, b: number): number => a + b;\"))\n# \"typescript\"\nprint(detector.suggest_test_file_name(\"UserService.java\", \"junit\"))\n# \"UserserviceTest.java\"\nprint(detector.identify_test_patterns(\"// Arrange\\nsetup()\\n// Act\\nresult = run()\\n// Assert\\nassert result\"))\n# ['AAA (Arrange-Act-Assert)']","type":"text"}]},{"type":"hr","attrs":{"markup":"---"}},{"type":"heading","attrs":{"level":3},"content":[{"text":"8. ","type":"text"},{"text":"output_formatter.py","type":"text","marks":[{"type":"code_inline"}]}]},{"type":"paragraph","content":[{"text":"Purpose:","type":"text","marks":[{"type":"strong"}]},{"text":" Context-aware output formatting for different environments (Desktop/markdown, CLI/terminal, API/JSON). Supports progressive disclosure, token-efficient summary reports, and output truncation.","type":"text"}]},{"type":"paragraph","content":[{"text":"Module:","type":"text","marks":[{"type":"strong"}]},{"text":" ","type":"text"},{"text":"OutputFormatter","type":"text","marks":[{"type":"code_inline"}]},{"text":" class","type":"text"}]},{"type":"paragraph","content":[{"text":"Usage:","type":"text","marks":[{"type":"strong"}]}]},{"type":"code_block","attrs":{"wrap":false,"language":"python"},"content":[{"text":"from output_formatter import OutputFormatter\n\nfmt = OutputFormatter(environment=\"cli\", verbose=False)\ncov_output = fmt.format_coverage_summary(summary, detailed=True)\nrec_output = fmt.format_recommendations(recommendations, max_items=5)\ntest_output = fmt.format_test_results(results, show_details=True)\nreport = fmt.create_summary_report(coverage, metrics, recommendations)\nshould_detail = fmt.should_show_detailed(data_size=50)\ntruncated = fmt.truncate_output(long_text, max_lines=30)","type":"text"}]},{"type":"paragraph","content":[{"text":"Constructor Parameters:","type":"text","marks":[{"type":"strong"}]}]},{"type":"table","attrs":{"layout":null},"content":[{"type":"tr","content":[{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Parameter","type":"text"}]}]},{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Type","type":"text"}]}]},{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Required","type":"text"}]}]},{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Description","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"environment","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"str","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"No","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Target environment: ","type":"text"},{"text":"\"desktop\"","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"\"cli\"","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"\"api\"","type":"text","marks":[{"type":"code_inline"}]},{"text":" (default ","type":"text"},{"text":"\"cli\"","type":"text","marks":[{"type":"code_inline"}]},{"text":")","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"verbose","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"bool","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"No","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Include detailed output (default ","type":"text"},{"text":"False","type":"text","marks":[{"type":"code_inline"}]},{"text":")","type":"text"}]}]}]}]},{"type":"paragraph","content":[{"text":"Key Methods:","type":"text","marks":[{"type":"strong"}]}]},{"type":"table","attrs":{"layout":null},"content":[{"type":"tr","content":[{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Method","type":"text"}]}]},{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Parameters","type":"text"}]}]},{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Returns","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"format_coverage_summary(summary, detailed)","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"summary","type":"text","marks":[{"type":"code_inline"}]},{"text":": dict; ","type":"text"},{"text":"detailed","type":"text","marks":[{"type":"code_inline"}]},{"text":": bool (default ","type":"text"},{"text":"False","type":"text","marks":[{"type":"code_inline"}]},{"text":")","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"str","type":"text","marks":[{"type":"code_inline"}]},{"text":" -- formatted coverage (markdown/terminal/JSON based on environment)","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"format_recommendations(recommendations, max_items)","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"recommendations","type":"text","marks":[{"type":"code_inline"}]},{"text":": list of dicts; ","type":"text"},{"text":"max_items","type":"text","marks":[{"type":"code_inline"}]},{"text":": optional int","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"str","type":"text","marks":[{"type":"code_inline"}]},{"text":" -- formatted recommendations grouped by priority","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"format_test_results(results, show_details)","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"results","type":"text","marks":[{"type":"code_inline"}]},{"text":": dict with ","type":"text"},{"text":"total_tests","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"passed","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"failed","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"skipped","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"failed_tests","type":"text","marks":[{"type":"code_inline"}]},{"text":"; ","type":"text"},{"text":"show_details","type":"text","marks":[{"type":"code_inline"}]},{"text":": bool (default ","type":"text"},{"text":"False","type":"text","marks":[{"type":"code_inline"}]},{"text":")","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"str","type":"text","marks":[{"type":"code_inline"}]},{"text":" -- formatted test results","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"create_summary_report(coverage, metrics, recommendations)","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"coverage","type":"text","marks":[{"type":"code_inline"}]},{"text":": dict; ","type":"text"},{"text":"metrics","type":"text","marks":[{"type":"code_inline"}]},{"text":": dict; ","type":"text"},{"text":"recommendations","type":"text","marks":[{"type":"code_inline"}]},{"text":": list","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"str","type":"text","marks":[{"type":"code_inline"}]},{"text":" -- token-efficient summary (\u003c200 tokens)","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"should_show_detailed(data_size)","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"data_size","type":"text","marks":[{"type":"code_inline"}]},{"text":": int","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"bool","type":"text","marks":[{"type":"code_inline"}]},{"text":" -- whether to show detailed output","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"truncate_output(text, max_lines)","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"text","type":"text","marks":[{"type":"code_inline"}]},{"text":": str; ","type":"text"},{"text":"max_lines","type":"text","marks":[{"type":"code_inline"}]},{"text":": int (default ","type":"text"},{"text":"50","type":"text","marks":[{"type":"code_inline"}]},{"text":")","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"str","type":"text","marks":[{"type":"code_inline"}]},{"text":" -- truncated text with remaining-lines indicator","type":"text"}]}]}]}]},{"type":"paragraph","content":[{"text":"Output Formats:","type":"text","marks":[{"type":"strong"}]},{"text":" String in markdown (desktop), plain text (CLI), or JSON (API) depending on ","type":"text"},{"text":"environment","type":"text","marks":[{"type":"code_inline"}]},{"text":" setting.","type":"text"}]},{"type":"paragraph","content":[{"text":"Example:","type":"text","marks":[{"type":"strong"}]}]},{"type":"code_block","attrs":{"wrap":false,"language":"python"},"content":[{"text":"fmt = OutputFormatter(environment=\"desktop\", verbose=True)\nprint(fmt.format_coverage_summary({\"line_coverage\": 82.5, \"branch_coverage\": 71.0, \"function_coverage\": 90.0}))\n# ## Test Coverage Summary\n# ### Overall Metrics\n# - **Line Coverage**: 82.5%\n# ...","type":"text"}]},{"type":"hr","attrs":{"markup":"---"}}]},"metadata":{"date":"2026-06-05","name":"tdd-guide","author":"@skillopedia","source":{"stars":209,"repo_name":"claude-skills","origin_url":"https://github.com/borghei/claude-skills/blob/HEAD/engineering/tdd-guide/SKILL.md","repo_owner":"borghei","body_sha256":"db9727cef234cae5638769f7e068e240fb503e175c0ed595d0c95b3fec9ef7ad","cluster_key":"63e5e34823f0b3206eef9686df28c3a313c3bfa3ff481f4063c53a5885c6061d","clean_bundle":{"format":"clean-skill-bundle-v1","source":"borghei/claude-skills/engineering/tdd-guide/SKILL.md","attachments":[{"id":"57937c8c-5e25-5cfb-ae77-7ffc0585b153","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/57937c8c-5e25-5cfb-ae77-7ffc0585b153/attachment.md","path":"HOW_TO_USE.md","size":7176,"sha256":"1257c94e7f8b1b06da85a11db49d3894fa76a7e633c24a17444612f88999fa65","contentType":"text/markdown; charset=utf-8"},{"id":"c688175d-3f92-5296-afa6-eca48bb6e68b","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/c688175d-3f92-5296-afa6-eca48bb6e68b/attachment.md","path":"README.md","size":18528,"sha256":"0d17c8ff5780c371d76a9e5caf026f145b007e0163fce4c6b5775c25df9cbc27","contentType":"text/markdown; charset=utf-8"},{"id":"3cd9ebfd-fd8f-5355-8539-82bb8bea8f34","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/3cd9ebfd-fd8f-5355-8539-82bb8bea8f34/attachment.json","path":"assets/expected_output.json","size":2404,"sha256":"03a146673c9743856f80654c27d1d9294f5c795d88b02901a305c0b8e49c7eb6","contentType":"application/json; charset=utf-8"},{"id":"9ad1d2b0-3606-5362-8178-7ee140fb4427","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/9ad1d2b0-3606-5362-8178-7ee140fb4427/attachment.lcov","path":"assets/sample_coverage_report.lcov","size":615,"sha256":"5d884784dcf4a2c1a952850194acc378c2018a75f2dff428ba28b13096b47d1c","contentType":"text/plain; charset=utf-8"},{"id":"fba78071-c752-5fb7-b77b-ab10130ba7f7","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/fba78071-c752-5fb7-b77b-ab10130ba7f7/attachment.json","path":"assets/sample_input_python.json","size":1443,"sha256":"be90a513e0a6cdf6db21bf89177421b3eeb6f53d642e3b13276c3c6ad7e537d0","contentType":"application/json; charset=utf-8"},{"id":"edf8955b-7bbd-5d03-afc4-621796a8d268","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/edf8955b-7bbd-5d03-afc4-621796a8d268/attachment.json","path":"assets/sample_input_typescript.json","size":1469,"sha256":"5dee32466f71080736418ad3a36d252d6f5b117df975ba682463688ce8e9128f","contentType":"application/json; charset=utf-8"},{"id":"46f7a663-dedd-54b0-9318-74f5d12c260b","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/46f7a663-dedd-54b0-9318-74f5d12c260b/attachment.md","path":"references/ci-integration.md","size":4017,"sha256":"47cfd82bd0287c9fc6cadd6bec35459571a2af162d3449a54bdd41e808949080","contentType":"text/markdown; charset=utf-8"},{"id":"1fc1db1c-ab48-5027-a760-b8ba72178a93","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/1fc1db1c-ab48-5027-a760-b8ba72178a93/attachment.md","path":"references/framework-guide.md","size":4316,"sha256":"1a4370676a8543aa7e4e6305a72ce164b8c5a921104112fac996d7c1a3f35466","contentType":"text/markdown; charset=utf-8"},{"id":"d2e4a516-d048-5f80-836e-b2926dd498ad","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/d2e4a516-d048-5f80-836e-b2926dd498ad/attachment.md","path":"references/tdd-best-practices.md","size":3516,"sha256":"ee7a8aaaf9381692e7b4d03b111c8300e6217a65f0a9effa7817d2cb9703a2d5","contentType":"text/markdown; charset=utf-8"},{"id":"2ba5c2cd-d85c-5054-a0fa-2091d82d8da1","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/2ba5c2cd-d85c-5054-a0fa-2091d82d8da1/attachment.py","path":"scripts/coverage_analyzer.py","size":15502,"sha256":"1da0290c739634b4da7f6e1515e5e11bc70cb9060cc67dde4c2c50b6777fd5e4","contentType":"text/x-python; charset=utf-8"},{"id":"0f35d229-55fb-5ff1-8ff9-ce1236abaf6d","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/0f35d229-55fb-5ff1-8ff9-ce1236abaf6d/attachment.py","path":"scripts/fixture_generator.py","size":14311,"sha256":"8ee81d35b6a72fc768038e30c0ef7b997c57165b5c428ef45b9aef1cd9fc5f0a","contentType":"text/x-python; charset=utf-8"},{"id":"61118998-2cca-5226-ba29-e4faaa473925","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/61118998-2cca-5226-ba29-e4faaa473925/attachment.py","path":"scripts/format_detector.py","size":12207,"sha256":"a12f1d016967fc0a8a3b3f68b28a172494c33c9252d72d662c7a37f765a6692d","contentType":"text/x-python; charset=utf-8"},{"id":"dd00105f-6a38-50b6-8e06-6739493275aa","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/dd00105f-6a38-50b6-8e06-6739493275aa/attachment.py","path":"scripts/framework_adapter.py","size":14834,"sha256":"03a189d01310f04cb025bb9498ecd6bdc7d16eef119e992ff513774939299c58","contentType":"text/x-python; charset=utf-8"},{"id":"9a7b93a9-976e-59bd-9aac-af1e404d2c5e","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/9a7b93a9-976e-59bd-9aac-af1e404d2c5e/attachment.py","path":"scripts/metrics_calculator.py","size":15476,"sha256":"8080b0daa70cb38114cf7937e3e8f942cef99b81db3fdd786e1ca44350bd57a8","contentType":"text/x-python; charset=utf-8"},{"id":"4a06d1dc-3be5-501b-90d6-023075bda21f","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/4a06d1dc-3be5-501b-90d6-023075bda21f/attachment.py","path":"scripts/output_formatter.py","size":12734,"sha256":"e92a7559ae39c9b144a55b2dfaf6f14d9137a7e37aa9ee07adaf7c4c346b21fd","contentType":"text/x-python; charset=utf-8"},{"id":"4ebd9aee-8815-54a3-88db-dcd9a4daf6be","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/4ebd9aee-8815-54a3-88db-dcd9a4daf6be/attachment.py","path":"scripts/tdd_workflow.py","size":16968,"sha256":"5048dda42125f9c95cd49dbf67816f5bc635fee0cc5938a74a4d1b59361f9095","contentType":"text/x-python; charset=utf-8"},{"id":"350d61a3-bae1-506c-86f3-7019d2b50638","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/350d61a3-bae1-506c-86f3-7019d2b50638/attachment.py","path":"scripts/test_generator.py","size":14617,"sha256":"6ec26f0f29339ab23f0ff65fd140eaec143751759c7ddf360ada988059959346","contentType":"text/x-python; charset=utf-8"}],"bundle_sha256":"0c60b1c39ebd55bae4a851fa8563183bc77a207321a2829b24d850e418185b6d","attachment_count":17,"text_attachments":16,"attachment_storage":"skillopedia-attachments-v1","binary_attachments":1,"excluded_attachments":[]},"cluster_size":1,"skill_md_path":"engineering/tdd-guide/SKILL.md","import_metadata":{"date":"2026-06-05","author":"@skillopedia","version":"v1","category":"testing-qa","category_label":"Testing"},"exact_dupes_collapsed_into_this":0},"license":"MIT + Commons Clause","version":"v1","category":"testing-qa","metadata":{"tags":["tdd","test-driven-development","testing","red-green-refactor"],"author":"borghei","domain":"testing","updated":"2026-03-31T00:00:00.000Z","version":"1.0.0","category":"engineering"},"import_tag":"clean-skills-v1","description":"Guides red-green-refactor TDD workflows with test generation, coverage gap analysis, and multi-framework support. Use when writing tests first, analyzing coverage reports, generating test stubs, or converting tests between Jest, Pytest, JUnit, and Vitest.\n"}},"renderedAt":1782980007485}

TDD Guide The agent guides red-green-refactor TDD workflows, generates framework-specific test stubs from requirements, parses coverage reports to identify prioritized gaps, and calculates test quality metrics including smell detection and assertion density. Supports Jest, Pytest, JUnit, Vitest, and Mocha. Quick Start --- Core Workflows Workflow 1: TDD a New Feature 1. Write a failing test for the feature requirement (RED phase) 2. Call -- confirms test exists and fails 3. Write minimal code to make the test pass (GREEN phase) 4. Call -- confirms all tests pass 5. Refactor while keeping tests…