From test-engineering
Guide automated generation of high-quality unit, integration, and E2E tests. Use when writing test code to apply language-specific patterns, mocking strategies, async test patterns, and best practices for Python, JavaScript, TypeScript, Java, C#, Go, and C++.
npx claudepluginhub issacchaos/local-marketplace --plugin test-engineeringThis skill uses the workspace's default tool permissions.
**Skill Type**: Test Generation
Generates design tokens/docs from CSS/Tailwind/styled-components codebases, audits visual consistency across 10 dimensions, detects AI slop in UI.
Records polished WebM UI demo videos of web apps using Playwright with cursor overlay, natural pacing, and three-phase scripting. Activates for demo, walkthrough, screen recording, or tutorial requests.
Delivers idiomatic Kotlin patterns for null safety, immutability, sealed classes, coroutines, Flows, extensions, DSL builders, and Gradle DSL. Use when writing, reviewing, refactoring, or designing Kotlin code.
Skill Type: Test Generation Purpose: Guide automated generation of high-quality unit, integration, and E2E tests Target Users: Write Agent, test-generation workflows Version: 1.0.0
This skill provides knowledge and patterns for generating comprehensive test suites across multiple programming languages and testing frameworks. It focuses on creating maintainable, readable, and effective tests that validate functionality while catching regressions.
The test generation skill expects the following context:
**Analysis Context**:
- Language: [e.g., Python, JavaScript, Java]
- Framework: [e.g., pytest, Jest, JUnit]
- Test Type: [unit, integration, e2e]
- Target Code: [function, class, module to test]
- Dependencies: [external services, databases, APIs]
- Complexity Score: [low, medium, high]
**Code to Test**:
[Source code that needs tests]
**Requirements**:
- Coverage Goals: [e.g., >80% line coverage, all public methods]
- Edge Cases: [specific scenarios to test]
- Mock Strategy: [what should be mocked vs real]
The skill guides generation of:
**Generated Tests**:
- Test File Path: [where to create the test]
- Test Structure: [classes, functions, fixtures]
- Test Cases: [individual test methods with AAA pattern]
- Mocks & Fixtures: [setup code and dependencies]
- Assertions: [validation logic]
- Edge Cases: [boundary and error conditions]
**Test Metadata**:
- Test Count: [number of tests generated]
- Coverage Estimate: [expected coverage %]
- Requires Review: [true/false - needs human review]
- Complexity: [test maintenance complexity]
Principle: Each test should run independently and not rely on execution order.
Guidelines:
Example (Python):
# ❌ Bad - Tests depend on order
class TestUserService:
user_id = None
def test_create_user(self):
self.user_id = create_user("Alice")
assert self.user_id is not None
def test_get_user(self):
# Depends on test_create_user running first!
user = get_user(self.user_id)
assert user.name == "Alice"
# ✅ Good - Tests are independent
class TestUserService:
@pytest.fixture
def user_id(self):
return create_user("Alice")
def test_create_user(self):
user_id = create_user("Alice")
assert user_id is not None
def test_get_user(self, user_id):
user = get_user(user_id)
assert user.name == "Alice"
Principle: Tests should follow a clear, readable pattern (AAA: Arrange-Act-Assert).
Pattern:
def test_what_when_then():
"""Describe what is being tested."""
# Arrange - Set up test data and conditions
[setup code]
# Act - Execute the code under test
[action code]
# Assert - Verify the results
[assertion code]
Benefits:
Principle: Test names should clearly describe what is being tested and expected outcome.
Format: test_<function>_<condition>_<expected_result>
Examples:
test_add_positive_numbers_returns_sumtest_divide_by_zero_raises_value_errortest_login_invalid_credentials_returns_falsetest_fetch_user_nonexistent_id_returns_nonePrinciple: Focus on testing what the code does (behavior), not how it does it (implementation).
Guidelines:
Example (Python):
# ❌ Bad - Tests implementation details
def test_calculator_uses_correct_algorithm(self):
calc = Calculator()
calc.add(2, 3)
assert calc._intermediate_result == 2 # Testing internal state
assert calc._operation_count == 1 # Testing implementation
# ✅ Good - Tests behavior
def test_add_returns_correct_sum(self):
calc = Calculator()
result = calc.add(2, 3)
assert result == 5 # Testing the observable behavior
Principle: Each test should verify one specific behavior or concept.
Guidelines:
Example (Python):
# ❌ Bad - Testing multiple concepts
def test_user_service(self):
# Testing creation
user_id = create_user("Alice")
assert user_id is not None
# Testing retrieval
user = get_user(user_id)
assert user.name == "Alice"
# Testing update
update_user(user_id, name="Bob")
user = get_user(user_id)
assert user.name == "Bob"
# Testing deletion
delete_user(user_id)
user = get_user(user_id)
assert user is None
# ✅ Good - Each test verifies one concept
def test_create_user_returns_valid_id(self):
user_id = create_user("Alice")
assert user_id is not None
def test_get_user_returns_correct_user(self):
user_id = create_user("Alice")
user = get_user(user_id)
assert user.name == "Alice"
def test_update_user_changes_name(self):
user_id = create_user("Alice")
update_user(user_id, name="Bob")
user = get_user(user_id)
assert user.name == "Bob"
def test_delete_user_removes_user(self):
user_id = create_user("Alice")
delete_user(user_id)
user = get_user(user_id)
assert user is None
Principle: Don't just test the happy path; test boundary conditions and error cases.
Categories:
None, null, empty strings, empty arraysExample (Python):
class TestCalculator:
# Happy path
def test_add_positive_numbers(self):
assert Calculator().add(2, 3) == 5
# Edge cases
def test_add_zero(self):
assert Calculator().add(5, 0) == 5
def test_add_negative_numbers(self):
assert Calculator().add(-2, -3) == -5
def test_add_large_numbers(self):
result = Calculator().add(10**100, 10**100)
assert result == 2 * (10**100)
# Error cases
def test_add_invalid_type_raises_error(self):
with pytest.raises(TypeError):
Calculator().add("2", 3)
Principle: Isolate the code under test by mocking external dependencies.
Mock When:
Don't Mock:
Principle: Extract common setup code into reusable fixtures.
Benefits:
Purpose: Test individual functions, methods, or classes in isolation.
Characteristics:
When to Generate:
Purpose: Test how multiple components work together.
Characteristics:
When to Generate:
Purpose: Test complete user workflows from start to finish.
Characteristics:
When to Generate:
This skill includes detailed patterns for:
python-patterns.md - pytest, unittest, fixtures, mockingThis skill includes detailed patterns for:
unit-test-patterns.md - AAA pattern, isolation, fast testsmocking-strategies.md - When, what, and how to mockActions:
Output: Analysis report with test targets prioritized
Actions:
Output: Test plan with patterns to use
Actions:
Output: Syntactically valid test code
Actions:
Output: Validated test code ready for execution
Generated tests should meet these criteria:
**Context**:
- Language: Python
- Framework: pytest
- Test Type: unit
- Target: `calculator.py` - `add()` function
**Code**:
```python
def add(a: int, b: int) -> int:
"""Add two numbers and return the sum."""
if not isinstance(a, int) or not isinstance(b, int):
raise TypeError("Both arguments must be integers")
return a + b
Requirements:
### Output from Skill
```python
import pytest
from calculator import add
class TestAdd:
"""Test suite for add() function."""
def test_add_positive_numbers_returns_sum(self):
"""Test adding two positive integers."""
# Arrange
a = 5
b = 3
expected = 8
# Act
result = add(a, b)
# Assert
assert result == expected
def test_add_negative_numbers_returns_sum(self):
"""Test adding two negative integers."""
# Arrange
a = -5
b = -3
expected = -8
# Act
result = add(a, b)
# Assert
assert result == expected
def test_add_with_zero_returns_other_number(self):
"""Test adding zero returns the other number."""
# Arrange
a = 5
b = 0
expected = 5
# Act
result = add(a, b)
# Assert
assert result == expected
def test_add_invalid_type_raises_type_error(self):
"""Test that invalid types raise TypeError."""
# Arrange & Act & Assert
with pytest.raises(TypeError, match="Both arguments must be integers"):
add("5", 3)
@pytest.mark.parametrize("a, b, expected", [
(0, 0, 0),
(1, 1, 2),
(100, 200, 300),
(-1, 1, 0),
(10**6, 10**6, 2 * 10**6),
], ids=[
"both_zero",
"small_positive",
"large_positive",
"opposite_signs",
"very_large_numbers"
])
def test_add_various_inputs(self, a, b, expected):
"""Test add() with various input combinations."""
result = add(a, b)
assert result == expected
# Don't test that the framework works
def test_pytest_fixture_works(self, database):
assert database is not None
# Don't mock everything, including simple objects
def test_user_name(self):
mock_user = Mock()
mock_user.name = "Alice"
assert mock_user.name == "Alice" # Useless test
# Names should be descriptive
def test_1(self): # What does this test?
pass
def test_user(self): # Too vague
pass
# Each test should verify one concept
def test_everything(self):
assert add(1, 2) == 3
assert subtract(5, 3) == 2
assert multiply(2, 3) == 6
assert divide(6, 2) == 3
# Test behavior, not implementation
def test_uses_correct_algorithm(self):
calc = Calculator()
assert calc._algorithm == "fast_add" # Internal detail
When a method does nothing but forward a call to one dependency and return the result unchanged, the test exercises the mock, not the production code. Only test delegation when the method adds routing, transformation, error handling, or business logic on top of the forwarded call.
// source: fun setPendingItemsCount(n: Int) = repository.setPendingItemsCount(n)
// ❌ no logic here — this test covers the mock, not the class under test
fun test_setPendingItemsCount_delegates() = runTest {
sut.setPendingItemsCount(42)
coVerify { repository.setPendingItemsCount(42) }
}
Verifying that a constructor argument ends up in a property or URL as-is tests the language runtime, not application behaviour. Skip unless the value is transformed (formatted, encoded, combined with other fields, validated, etc.).
A test whose only assertion is assertEquals("SomeString", sut.someConstant) will never catch a real bug — it fails only if someone renames the constant, which is a refactor, not a regression. Remove it.
When two methods (e.g. startedSpeaking / stoppedSpeaking, enabled / disabled variants) share the same internal logic, one test is sufficient. The second adds noise without covering a new code path. Only add the second test when the assertion is different — a different output value, a different event type, or a different side-effect.
When multiple handlers (e.g. different notification types) share an identical early-return guard (if (account == null) return), test that guard once on a representative handler. Duplicating the identical arrange/act/assert across every sibling produces correlated failures and adds no safety.
Version: 1.0.0 (Phase 1 - Python/pytest focus)
Future Enhancements:
Related Skills:
skills/framework-detection/SKILL.mdskills/result-parsing/SKILL.mdskills/templates/python-pytest-template.mdCreated: 2025-12-05 Last Updated: 2025-12-05 Maintained By: Dante Automated Testing Plugin