Generate comprehensive, maintainable unit tests across languages with strong coverage and edge case focus.
Add this skill
npx mdskills install sickn33/unit-testing-test-generateComprehensive test generation with multi-language support, framework-specific patterns, and coverage analysis
1---2name: unit-testing-test-generate3description: Generate comprehensive, maintainable unit tests across languages with strong coverage and edge case focus.4---56# Automated Unit Test Generation78You are a test automation expert specializing in generating comprehensive, maintainable unit tests across multiple languages and frameworks. Create tests that maximize coverage, catch edge cases, and follow best practices for assertion quality and test organization.910## Use this skill when1112- You need unit tests for existing code13- You want consistent test structure and coverage14- You need mocks, fixtures, and edge-case validation1516## Do not use this skill when1718- You only need integration or E2E tests19- You cannot access the source code under test20- Tests must be hand-written for compliance reasons2122## Context2324The user needs automated test generation that analyzes code structure, identifies test scenarios, and creates high-quality unit tests with proper mocking, assertions, and edge case coverage. Focus on framework-specific patterns and maintainable test suites.2526## Requirements2728$ARGUMENTS2930## Instructions3132### 1. Analyze Code for Test Generation3334Scan codebase to identify untested code and generate comprehensive test suites:3536```python37import ast38from pathlib import Path39from typing import Dict, List, Any4041class TestGenerator:42 def __init__(self, language: str):43 self.language = language44 self.framework_map = {45 'python': 'pytest',46 'javascript': 'jest',47 'typescript': 'jest',48 'java': 'junit',49 'go': 'testing'50 }5152 def analyze_file(self, file_path: str) -> Dict[str, Any]:53 """Extract testable units from source file"""54 if self.language == 'python':55 return self._analyze_python(file_path)56 elif self.language in ['javascript', 'typescript']:57 return self._analyze_javascript(file_path)5859 def _analyze_python(self, file_path: str) -> Dict:60 with open(file_path) as f:61 tree = ast.parse(f.read())6263 functions = []64 classes = []6566 for node in ast.walk(tree):67 if isinstance(node, ast.FunctionDef):68 functions.append({69 'name': node.name,70 'args': [arg.arg for arg in node.args.args],71 'returns': ast.unparse(node.returns) if node.returns else None,72 'decorators': [ast.unparse(d) for d in node.decorator_list],73 'docstring': ast.get_docstring(node),74 'complexity': self._calculate_complexity(node)75 })76 elif isinstance(node, ast.ClassDef):77 methods = [n.name for n in node.body if isinstance(n, ast.FunctionDef)]78 classes.append({79 'name': node.name,80 'methods': methods,81 'bases': [ast.unparse(base) for base in node.bases]82 })8384 return {'functions': functions, 'classes': classes, 'file': file_path}85```8687### 2. Generate Python Tests with pytest8889```python90def generate_pytest_tests(self, analysis: Dict) -> str:91 """Generate pytest test file from code analysis"""92 tests = ['import pytest', 'from unittest.mock import Mock, patch', '']9394 module_name = Path(analysis['file']).stem95 tests.append(f"from {module_name} import *\n")9697 for func in analysis['functions']:98 if func['name'].startswith('_'):99 continue100101 test_class = self._generate_function_tests(func)102 tests.append(test_class)103104 for cls in analysis['classes']:105 test_class = self._generate_class_tests(cls)106 tests.append(test_class)107108 return '\n'.join(tests)109110def _generate_function_tests(self, func: Dict) -> str:111 """Generate test cases for a function"""112 func_name = func['name']113 tests = [f"\n\nclass Test{func_name.title()}:"]114115 # Happy path test116 tests.append(f" def test_{func_name}_success(self):")117 tests.append(f" result = {func_name}({self._generate_mock_args(func['args'])})")118 tests.append(f" assert result is not None\n")119120 # Edge case tests121 if len(func['args']) > 0:122 tests.append(f" def test_{func_name}_with_empty_input(self):")123 tests.append(f" with pytest.raises((ValueError, TypeError)):")124 tests.append(f" {func_name}({self._generate_empty_args(func['args'])})\n")125126 # Exception handling test127 tests.append(f" def test_{func_name}_handles_errors(self):")128 tests.append(f" with pytest.raises(Exception):")129 tests.append(f" {func_name}({self._generate_invalid_args(func['args'])})\n")130131 return '\n'.join(tests)132133def _generate_class_tests(self, cls: Dict) -> str:134 """Generate test cases for a class"""135 tests = [f"\n\nclass Test{cls['name']}:"]136 tests.append(f" @pytest.fixture")137 tests.append(f" def instance(self):")138 tests.append(f" return {cls['name']}()\n")139140 for method in cls['methods']:141 if method.startswith('_') and method != '__init__':142 continue143144 tests.append(f" def test_{method}(self, instance):")145 tests.append(f" result = instance.{method}()")146 tests.append(f" assert result is not None\n")147148 return '\n'.join(tests)149```150151### 3. Generate JavaScript/TypeScript Tests with Jest152153```typescript154interface TestCase {155 name: string;156 setup?: string;157 execution: string;158 assertions: string[];159}160161class JestTestGenerator {162 generateTests(functionName: string, params: string[]): string {163 const tests: TestCase[] = [164 {165 name: `${functionName} returns expected result with valid input`,166 execution: `const result = ${functionName}(${this.generateMockParams(params)})`,167 assertions: ['expect(result).toBeDefined()', 'expect(result).not.toBeNull()']168 },169 {170 name: `${functionName} handles null input gracefully`,171 execution: `const result = ${functionName}(null)`,172 assertions: ['expect(result).toBeDefined()']173 },174 {175 name: `${functionName} throws error for invalid input`,176 execution: `() => ${functionName}(undefined)`,177 assertions: ['expect(execution).toThrow()']178 }179 ];180181 return this.formatJestSuite(functionName, tests);182 }183184 formatJestSuite(name: string, cases: TestCase[]): string {185 let output = `describe('${name}', () => {\n`;186187 for (const testCase of cases) {188 output += ` it('${testCase.name}', () => {\n`;189 if (testCase.setup) {190 output += ` ${testCase.setup}\n`;191 }192 output += ` const execution = ${testCase.execution};\n`;193 for (const assertion of testCase.assertions) {194 output += ` ${assertion};\n`;195 }196 output += ` });\n\n`;197 }198199 output += '});\n';200 return output;201 }202203 generateMockParams(params: string[]): string {204 return params.map(p => `mock${p.charAt(0).toUpperCase() + p.slice(1)}`).join(', ');205 }206}207```208209### 4. Generate React Component Tests210211```typescript212function generateReactComponentTest(componentName: string): string {213 return `214import { render, screen, fireEvent } from '@testing-library/react';215import { ${componentName} } from './${componentName}';216217describe('${componentName}', () => {218 it('renders without crashing', () => {219 render(<${componentName} />);220 expect(screen.getByRole('main')).toBeInTheDocument();221 });222223 it('displays correct initial state', () => {224 render(<${componentName} />);225 const element = screen.getByTestId('${componentName.toLowerCase()}');226 expect(element).toBeVisible();227 });228229 it('handles user interaction', () => {230 render(<${componentName} />);231 const button = screen.getByRole('button');232 fireEvent.click(button);233 expect(screen.getByText(/clicked/i)).toBeInTheDocument();234 });235236 it('updates props correctly', () => {237 const { rerender } = render(<${componentName} value="initial" />);238 expect(screen.getByText('initial')).toBeInTheDocument();239240 rerender(<${componentName} value="updated" />);241 expect(screen.getByText('updated')).toBeInTheDocument();242 });243});244`;245}246```247248### 5. Coverage Analysis and Gap Detection249250```python251import subprocess252import json253254class CoverageAnalyzer:255 def analyze_coverage(self, test_command: str) -> Dict:256 """Run tests with coverage and identify gaps"""257 result = subprocess.run(258 [test_command, '--coverage', '--json'],259 capture_output=True,260 text=True261 )262263 coverage_data = json.loads(result.stdout)264 gaps = self.identify_coverage_gaps(coverage_data)265266 return {267 'overall_coverage': coverage_data.get('totals', {}).get('percent_covered', 0),268 'uncovered_lines': gaps,269 'files_below_threshold': self.find_low_coverage_files(coverage_data, 80)270 }271272 def identify_coverage_gaps(self, coverage: Dict) -> List[Dict]:273 """Find specific lines/functions without test coverage"""274 gaps = []275 for file_path, data in coverage.get('files', {}).items():276 missing_lines = data.get('missing_lines', [])277 if missing_lines:278 gaps.append({279 'file': file_path,280 'lines': missing_lines,281 'functions': data.get('excluded_lines', [])282 })283 return gaps284285 def generate_tests_for_gaps(self, gaps: List[Dict]) -> str:286 """Generate tests specifically for uncovered code"""287 tests = []288 for gap in gaps:289 test_code = self.create_targeted_test(gap)290 tests.append(test_code)291 return '\n\n'.join(tests)292```293294### 6. Mock Generation295296```python297def generate_mock_objects(self, dependencies: List[str]) -> str:298 """Generate mock objects for external dependencies"""299 mocks = ['from unittest.mock import Mock, MagicMock, patch\n']300301 for dep in dependencies:302 mocks.append(f"@pytest.fixture")303 mocks.append(f"def mock_{dep}():")304 mocks.append(f" mock = Mock(spec={dep})")305 mocks.append(f" mock.method.return_value = 'mocked_result'")306 mocks.append(f" return mock\n")307308 return '\n'.join(mocks)309```310311## Output Format3123131. **Test Files**: Complete test suites ready to run3142. **Coverage Report**: Current coverage with gaps identified3153. **Mock Objects**: Fixtures for external dependencies3164. **Test Documentation**: Explanation of test scenarios3175. **CI Integration**: Commands to run tests in pipeline318319Focus on generating maintainable, comprehensive tests that catch bugs early and provide confidence in code changes.320
Full transparency — inspect the skill content before installing.