| name | hammer-test-suite-generator |
| description | Generates complete test suite infrastructure (test scripts, functional tests, benchmark tests, output directories, CMake integration) for a new SDL3 HammerEngine system or manager following project conventions. Use when adding a new manager or system that needs testing infrastructure. |
| allowed-tools | ["Read","Write","Bash","Edit","Grep"] |
HammerEngine Test Suite Generator
This Skill automates the creation of standardized test infrastructure for new SDL3 HammerEngine systems. It generates all necessary files following the project's established patterns.
What This Skill Generates
- Test Script (
tests/test_scripts/run_<system>_tests.sh)
- Functional Test Source (
tests/<system>_tests.cpp)
- Benchmark Test Source (
tests/<system>_benchmark.cpp) - Optional
- CMakeLists.txt Updates - Add test executable targets
- Master Test Runner Update - Add to
run_all_tests.sh
- Output Directory Structure - Create
test_results/<system>/
- Documentation Stub - Basic testing documentation
User Input Collection
Ask the user for:
-
System Name (e.g., "AnimationManager", "SoundSystem")
- Used for file naming and test suite naming
- Must be PascalCase
-
Manager Class Name (e.g., "AnimationManager", "SoundManager")
- The actual C++ class being tested
- Must match existing class in codebase
-
Test Categories (checkboxes):
-
Integration Dependencies (if applicable):
- List of other systems this integrates with
- Example: "AIManager, CollisionManager"
-
Key Functionality (brief description):
- What does this system do?
- Used for test case generation
Generation Process
Step 1: Read Template Pattern
Reference Template:
Read: $PROJECT_ROOT/tests/test_scripts/run_ai_optimization_tests.sh
Common Pattern Elements:
- Shebang:
#!/bin/bash
- Color codes for output (RED, GREEN, YELLOW, RESET)
- Project root discovery
- Argument parsing (
--verbose, --help, --debug, --release)
- Test executable path resolution
- Timeout protection (default 30s for functional, 120s for benchmarks)
- Output redirection to
test_results/
- Success/failure status reporting
- Cleanup instructions
Step 2: Generate Test Script
Template:
#!/bin/bash
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
RESET='\033[0m'
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PROJECT_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
BUILD_TYPE="debug"
VERBOSE=""
TIMEOUT_DURATION=30
while [[ $# -gt 0 ]]; do
case $1 in
--verbose)
VERBOSE="--log_level=all"
shift
;;
--debug)
BUILD_TYPE="debug"
shift
;;
--release)
BUILD_TYPE="release"
shift
;;
--help)
echo "Usage: $0 [OPTIONS]"
echo ""
echo
0
;;
*)
1
;;
TEST_EXECUTABLE=
[ = ];
TEST_PATH=
TEST_PATH=
[ ! -f ];
-e
1
OUTPUT_DIR=
-p
OUTPUT_FILE=
-e
-v &> /dev/null;
s 2>&1 |
TEST_EXIT_CODE=
-v gtimeout &> /dev/null;
gtimeout s 2>&1 |
TEST_EXIT_CODE=
2>&1 |
TEST_EXIT_CODE=$?
[ -eq 0 ];
-e
0
[ -eq 124 ];
-e
3
-e
1
Substitutions:
<SystemName> → User-provided system name (e.g., "AnimationManager")
<system> → Lowercase system name (e.g., "animation_manager")
<brief-description> → User-provided key functionality
${TIMEOUT_DURATION} → 30s for functional, 120s for benchmarks
Save to:
$PROJECT_ROOT/tests/test_scripts/run_<system>_tests.sh
Make executable:
chmod +x tests/test_scripts/run_<system>_tests.sh
Step 3: Generate Functional Test Source
Reference Template:
Read: $PROJECT_ROOT/tests/ai_optimization_tests.cpp
Template:
#define BOOST_TEST_MODULE <SystemName>Tests
#include <boost/test/included/unit_test.hpp>
#include "<SystemName>.hpp"
struct <SystemName>Fixture
{
<SystemName>Fixture()
{
BOOST_TEST_MESSAGE("Setting up <SystemName> test fixture");
}
~<SystemName>Fixture()
{
BOOST_TEST_MESSAGE("Tearing down <SystemName> test fixture");
}
};
BOOST_FIXTURE_TEST_SUITE(<SystemName>TestSuite, <SystemName>Fixture)
BOOST_AUTO_TEST_CASE(TestConstruction)
{
BOOST_TEST_MESSAGE("Testing <SystemName> construction");
<SystemName> system;
();
}
(TestDestruction)
{
();
{
<SystemName> system;
}
();
();
}
(TestBasicFunctionality)
{
();
<SystemName> system;
();
}
(TestEdgeCases)
{
();
<SystemName> system;
();
();
}
(TestErrorHandling)
{
();
<SystemName> system;
();
}
(TestThreadSafety)
{
();
<SystemName> system;
();
();
}
(TestIntegrationWith<OtherSystem>)
{
();
<SystemName> system;
();
();
}
()
Substitutions:
<SystemName> → User-provided class name (PascalCase)
<system> → Lowercase system name
<OtherSystem> → Integration dependency names (if applicable)
Customization Based on User Input:
- If "Integration Tests" selected, include
#define INTEGRATION_TESTS
- If system is manager (multi-threaded), include
#define THREAD_SAFETY_TESTS
- Generate specific test cases based on "Key Functionality" description
Save to:
$PROJECT_ROOT/tests/<system>_tests.cpp
Step 4: Generate Benchmark Test Source (Optional)
Only if user selects "Benchmark Tests"
Template:
#define BOOST_TEST_MODULE <SystemName>Benchmark
#include <boost/test/included/unit_test.hpp>
#include "<SystemName>.hpp"
#include <chrono>
#include <iostream>
#include <fstream>
class BenchmarkTimer
{
public:
void start()
{
m_start = std::chrono::high_resolution_clock::now();
}
double stop()
{
auto end = std::chrono::high_resolution_clock::now();
std::chrono::duration<double, std::milli> duration = end - m_start;
return duration.count();
}
private:
std::chrono::high_resolution_clock::time_point m_start;
};
void saveMetric( std::string& name, value, std::string& unit)
{
* root = std::();
std::string path = root ? std::(root) +
: ;
;
file << name << << value << << unit << std::endl;
std::cout << name << << value << << unit << std::endl;
}
<SystemName>BenchmarkFixture
{
<SystemName>()
{
();
();
();
}
~<SystemName>()
{
();
}
BenchmarkTimer timer;
};
(<SystemName>BenchmarkSuite, <SystemName>BenchmarkFixture)
(BenchmarkThroughput_1K)
{
();
OPERATIONS = ;
<SystemName> system;
timer.();
( i = ; i < OPERATIONS; i++)
{
}
elapsed = timer.();
throughput = OPERATIONS / (elapsed / );
(, throughput, );
(, elapsed / OPERATIONS, );
( << throughput << );
}
(BenchmarkThroughput_10K)
{
();
OPERATIONS = ;
<SystemName> system;
timer.();
( i = ; i < OPERATIONS; i++)
{
}
elapsed = timer.();
throughput = OPERATIONS / (elapsed / );
(, throughput, );
(, elapsed / OPERATIONS, );
( << throughput << );
}
(BenchmarkScaling)
{
();
<SystemName> system;
std::vector<> sizes = {, , , , };
( size : sizes)
{
timer.();
( i = ; i < size; i++)
{
}
elapsed = timer.();
throughput = size / (elapsed / );
std::string metricName = + std::(size);
(metricName, throughput, );
}
();
}
(BenchmarkMemoryUsage)
{
();
<SystemName> system;
(, , );
();
}
()
{
~()
{
* root = std::();
std::string resultsPath = root ? std::(root) +
: ;
();
( << resultsPath);
();
}
};
(SummaryGeneration, BenchmarkSummaryFixture)
(GenerateSummary)
{
* root = std::();
std::string reportPath = root ? std::(root) +
: ;
;
report << ;
report << << __DATE__ << << __TIME__ << ;
report << ;
report << ;
report << ;
report << ;
report.();
();
}
()
Save to:
$PROJECT_ROOT/tests/<system>_benchmark.cpp
Step 5: Update CMakeLists.txt
Read CMakeLists.txt:
Read: $PROJECT_ROOT/CMakeLists.txt
Add Test Executables:
Find the section with test executable definitions (look for pattern like add_executable(<test_name> tests/...)).
Add entries:
# <SystemName> Tests
add_executable(<system>_tests
tests/<system>_tests.cpp
# Add source files being tested
src/managers/<SystemName>.cpp # Adjust path as needed
)
target_link_libraries(<system>_tests PRIVATE ${SDL3_LIBRARY} Boost::unit_test_framework)
set_target_properties(<system>_tests PROPERTIES
RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/../bin/${CMAKE_BUILD_TYPE_LOWER}"
)
# <SystemName> Benchmark (if applicable)
add_executable(<system>_benchmark
tests/<system>_benchmark.cpp
src/managers/<SystemName>.cpp
)
target_link_libraries(<system>_benchmark PRIVATE ${SDL3_LIBRARY} Boost::unit_test_framework)
set_target_properties(<system>_benchmark PROPERTIES
RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/../bin/${CMAKE_BUILD_TYPE_LOWER}"
)
Use Edit tool to add these entries after existing test definitions.
Step 6: Update Master Test Runner
Read run_all_tests.sh:
Read: $PROJECT_ROOT/run_all_tests.sh
Add test to appropriate section:
For Functional Tests (--core-only section):
echo -e "${BLUE}Running <SystemName> Tests...${RESET}"
./tests/test_scripts/run_<system>_tests.sh
check_status $? "<SystemName> Tests"
For Benchmark Tests (--benchmarks-only section):
echo -e "${BLUE}Running <SystemName> Benchmark...${RESET}"
./tests/test_scripts/run_<system>_benchmark.sh
check_status $? "<SystemName> Benchmark"
Use Edit tool to add these entries in appropriate sections.
Step 7: Create Output Directory Structure
Create directories:
mkdir -p "$PROJECT_ROOT/test_results/<system>"
touch "$PROJECT_ROOT/test_results/<system>/.gitkeep"
Step 8: Generate Documentation Stub
Create test documentation:
# <SystemName> Testing
## Overview
Tests for <SystemName> functionality and performance.
## Test Suites
### Functional Tests
- **Location:** `tests/<system>_tests.cpp`
- **Runner:** `tests/test_scripts/run_<system>_tests.sh`
- **Coverage:**
- Construction/Destruction
- Basic Functionality
- Edge Cases
- Error Handling
- Thread Safety (if applicable)
### Benchmark Tests
- **Location:** `tests/<system>_benchmark.cpp`
- **Runner:** `tests/test_scripts/run_<system>_benchmark.sh`
- **Metrics:**
- Throughput (ops/sec)
- Latency (ms/op)
- Scaling characteristics
- Resource usage
## Running Tests
```bash
# Functional tests
./tests/test_scripts/run_<system>_tests.sh --verbose
# Benchmarks
./tests/test_scripts/run_<system>_benchmark.sh --verbose
# All tests (included in master runner)
./run_all_tests.sh --core-only
./run_all_tests.sh --benchmarks-only
Test Results
Results are saved to:
test_results/<system>/<system>_test_results.txt
test_results/<system>/performance_metrics.txt
test_results/<system>/performance_report.md
Adding New Tests
- Add test case to
tests/<system>_tests.cpp
- Use
BOOST_AUTO_TEST_CASE macro
- Follow existing test patterns
- Run tests to verify
Performance Baselines
TODO: Document expected performance baselines for benchmarks.
Known Issues
TODO: Document any known test issues or limitations.
**Save to:**
$PROJECT_ROOT/tests/docs/_Testing.md
### Step 9: Verification Build
**Build new test executables:**
```bash
cd $PROJECT_ROOT
cmake -B build/ -G Ninja -DCMAKE_BUILD_TYPE=Debug && ninja -C build
Verify executables created:
ls -lh bin/debug/<system>_tests
ls -lh bin/debug/<system>_benchmark
Run initial test:
./tests/test_scripts/run_<system>_tests.sh --verbose
Output Summary
Report to user:
# Test Suite Generated Successfully
## Files Created
### Test Scripts
- ✓ `tests/test_scripts/run_<system>_tests.sh`
- ✓ `tests/test_scripts/run_<system>_benchmark.sh` (if applicable)
### Test Source Files
- ✓ `tests/<system>_tests.cpp`
- ✓ `tests/<system>_benchmark.cpp` (if applicable)
### Documentation
- ✓ `tests/docs/<SystemName>_Testing.md`
### Directory Structure
- ✓ `test_results/<system>/`
## Files Modified
- ✓ `CMakeLists.txt` - Added test executable targets
- ✓ `run_all_tests.sh` - Added test to master runner
## Next Steps
1. **Implement Test Cases:**
- Edit `tests/<system>_tests.cpp`
- Replace placeholder tests with actual functionality tests
- Based on: <user-provided-key-functionality>
2. **Build Tests:**
```bash
cmake -B build/ -G Ninja -DCMAKE_BUILD_TYPE=Debug && ninja -C build
-
Run Tests:
./tests/test_scripts/run_<system>_tests.sh --verbose
-
Customize Benchmarks (if applicable):
- Edit
tests/<system>_benchmark.cpp
- Add performance-specific test cases
- Define performance baselines
-
Add to CI/CD:
- Tests are automatically included in
run_all_tests.sh
- Will run with
--core-only flag
Test Executable Locations
- Debug:
bin/debug/<system>_tests
- Release:
bin/release/<system>_tests
- Benchmark:
bin/debug/<system>_benchmark
Running Generated Tests
./tests/test_scripts/run_<system>_tests.sh
./tests/test_scripts/run_<system>_tests.sh --verbose
./run_all_tests.sh --core-only
./tests/test_scripts/run_<system>_benchmark.sh
./run_all_tests.sh --benchmarks-only
Verification
Build status: <SUCCESS/FAILED>
Initial test run: <PASSED/FAILED/SKIPPED>
Generated by: hammer-test-suite-generator Skill
Time saved: ~30-45 minutes of manual scaffolding
## Usage Examples
When the user says:
- "generate tests for NewManager"
- "create test suite for AnimationSystem"
- "set up testing for SoundManager"
- "scaffold tests for new system"
Activate this Skill automatically.
## Important Notes
1. **Always ask for user input** before generating
2. **Verify class exists** in codebase before generating
3. **Follow naming conventions** (PascalCase classes, snake_case files)
4. **Include copyright headers** on all generated files
5. **Make scripts executable** after creation
6. **Verify CMake syntax** after modifications
7. **Test build** after generation to catch errors early
## Error Handling
**If system already has tests:**
- Ask user if they want to regenerate (will overwrite)
- Offer to add additional test cases instead
**If CMakeLists.txt modification fails:**
- Show generated CMake snippet
- Instruct user to add manually
**If build fails:**
- Show compilation errors
- Suggest fixes for common issues
- Offer to help debug
## Integration with Development Workflow
Use this Skill when:
- Adding new manager to project
- Creating new game system
- Implementing new feature that needs testing
- Standardizing existing tests to match project conventions
## Time Savings
**Manual Process:** ~30-45 minutes
- Write test script: 10-15 min
- Write test source: 15-20 min
- Update CMake: 5 min
- Update master runner: 3 min
- Create directories: 2 min
- Debug issues: 5-10 min
**With This Skill:** ~2-5 minutes
- Answer questions: 1-2 min
- Review generated code: 1-2 min
- Customize tests: 1 min
**Total Time Saved:** ~25-40 minutes per system