8.6 KiB
Testing Guide for ESP32 Dimmer Driver
Overview
This guide provides instructions for running and extending the unit tests for the ESP32 Dimmer Driver library.
Test Coverage Summary
The unit test suite covers 19 test cases across the following categories:
1. Dimmer Creation (2 tests)
- Creating a single dimmer instance
- Creating multiple dimmer instances with different GPIO pins
2. Power Control (3 tests)
- Setting and getting power with normal values (0, 50, 99)
- Boundary value testing (values >99 are clamped)
- Power retrieval when dimmer is OFF
3. State Management (3 tests)
- Setting and getting ON/OFF state
- Toggling state with changeState()
- State's effect on getPower() return value
4. Mode Management (3 tests)
- Setting and getting NORMAL/TOGGLE modes
- Toggle settings with valid ranges
- Toggle settings with boundary values
5. Initialization (2 tests)
- Initialization with NORMAL_MODE
- Initialization with TOGGLE_MODE
6. Multiple Dimmers (1 test)
- Independent operation of multiple dimmers
7. GPIO and Timer ISR (5 tests)
- GPIO output timing after zero-crossing events
- Pulse width timing on GPIO output
- Dimmer response to zero-crossing interrupts
- Multiple dimmers controlling GPIO pins independently
- Timer ISR respecting dimmer state changes (ON/OFF)
8. Integration (1 test)
- State changes affecting power reporting
Prerequisites
Software Requirements
- ESP-IDF v5.0 or higher
- Python 3.7 or higher (for ESP-IDF)
- CMake 3.16 or higher
- Appropriate compiler toolchain for your platform
Hardware Requirements
- ESP32 development board (any variant: ESP32, ESP32-S2, ESP32-C3, etc.)
- USB cable for flashing and monitoring
- (Optional) Oscilloscope for hardware validation
Installation
-
Install ESP-IDF v5.0 or higher following the official guide
-
Clone this repository:
git clone https://github.com/pmarchini/Esp32Dimmer.git cd Esp32Dimmer
Running Tests
Quick Start
# Navigate to test application
cd test_app
# Set target (choose your ESP32 variant)
idf.py set-target esp32
# Build the tests
idf.py build
# Flash and monitor (replace with your serial port)
idf.py -p /dev/ttyUSB0 flash monitor
Supported Targets
The tests can run on any ESP32 variant:
- ESP32 (default)
- ESP32-S2
- ESP32-C3
- ESP32-S3
To set a specific target:
idf.py set-target esp32s3
Build Options
For verbose build output:
idf.py -v build
For clean build:
idf.py fullclean
idf.py build
Understanding Test Output
Successful Test Run
========================================
ESP32 Dimmer Driver Unit Tests
========================================
Running test_createDimmer_returns_valid_pointer...
PASS
Running test_createDimmer_with_different_pins...
PASS
[... more tests ...]
========================================
All tests completed!
========================================
16 Tests 0 Failures 0 Ignored
OK
Failed Test Example
If a test fails, you'll see:
Running test_setPower_getPower_normal_values...
test_main.c:56:test_setPower_getPower_normal_values:FAIL: Expected 50 Was 0
16 Tests 1 Failures 0 Ignored
FAIL
Writing New Tests
Test Function Template
void test_your_feature_description(void)
{
// 1. Setup - Create dimmer and initialize
dimmertyp *dimmer = createDimmer(TEST_TRIAC_GPIO, TEST_ZC_GPIO);
TEST_ASSERT_NOT_NULL(dimmer);
begin(dimmer, NORMAL_MODE, ON, 50);
// 2. Execute - Perform the operation you're testing
setPower(dimmer, 42);
vTaskDelay(pdMS_TO_TICKS(10));
// 3. Verify - Check the results
TEST_ASSERT_EQUAL(42, getPower(dimmer));
// 4. Cleanup (if needed)
// Note: Library doesn't provide cleanup functions
}
Unity Assertion Macros
Common assertions used in the tests:
TEST_ASSERT_TRUE(condition) // Verify condition is true
TEST_ASSERT_FALSE(condition) // Verify condition is false
TEST_ASSERT_EQUAL(expected, actual) // Verify values are equal
TEST_ASSERT_NOT_EQUAL(val1, val2) // Verify values are different
TEST_ASSERT_NULL(pointer) // Verify pointer is NULL
TEST_ASSERT_NOT_NULL(pointer) // Verify pointer is not NULL
TEST_ASSERT_EQUAL_INT(exp, act) // Compare integers
TEST_ASSERT_GREATER_THAN(threshold, actual) // Verify actual > threshold
TEST_ASSERT_LESS_THAN(threshold, actual) // Verify actual < threshold
Adding a New Test
-
Add test function to
test_app/main/test_main.c:void test_my_new_feature(void) { // Your test code here } -
Register it in
app_main():void app_main(void) { UNITY_BEGIN(); // Existing tests... RUN_TEST(test_my_new_feature); // Add this line UNITY_END(); } -
Rebuild and test:
idf.py build flash monitor
Test Best Practices
1. Test Independence
Each test should be independent and not rely on state from other tests.
2. Descriptive Names
Use clear, descriptive test names: test_<component>_<scenario>
- Good:
test_setPower_boundary_values - Bad:
test_power_1
3. Test One Thing
Each test should verify one specific behavior.
4. Use Delays
When testing asynchronous operations, add small delays:
setPower(dimmer, 50);
vTaskDelay(pdMS_TO_TICKS(10)); // Allow setting to take effect
TEST_ASSERT_EQUAL(50, getPower(dimmer));
5. Document Edge Cases
Add comments for non-obvious test cases:
// Test that power values above 99 are clamped to 99
setPower(dimmer, 150);
TEST_ASSERT_EQUAL(99, getPower(dimmer));
Continuous Integration
GitHub Actions Example
Create .github/workflows/test.yml:
name: ESP32 Dimmer Tests
on: [push, pull_request]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Setup ESP-IDF
uses: espressif/esp-idf-ci-action@v1
with:
esp_idf_version: v5.0
target: esp32
- name: Build Tests
run: |
cd test_app
idf.py build
Troubleshooting
Build Errors
Error: "No such file or directory" for esp32-triac-dimmer-driver.h
- Solution: Ensure EXTRA_COMPONENT_DIRS is set correctly in test_app/CMakeLists.txt
Error: "undefined reference to unity_*"
- Solution: Ensure unity is in the REQUIRES list in main/CMakeLists.txt
Runtime Issues
Tests fail to start
- Check serial port permissions:
sudo usermod -a -G dialout $USER - Verify correct serial port:
ls /dev/tty*
Random test failures
- Hardware interference - ensure stable power supply
- Increase delay times in tests
- Check for race conditions in test logic
Memory Issues
Stack overflow in tests
- Increase CONFIG_ESP_MAIN_TASK_STACK_SIZE in sdkconfig.defaults
Heap allocation failures
- Tests may exceed ALL_DIMMERS limit (50)
- Reset the board between test runs
Hardware Validation Testing
While unit tests validate software behavior, hardware testing validates actual dimmer operation:
Setup for Hardware Tests
- Connect zero-crossing detector to GPIO_NUM_21
- Connect TRIAC outputs to GPIO_NUM_22 and GPIO_NUM_23
- Connect dimmable AC load (e.g., incandescent bulb)
- Use oscilloscope to monitor TRIAC firing pulses
Safety Warnings
⚠️ AC VOLTAGE HAZARD ⚠️
- Only qualified personnel should work with AC circuits
- Ensure proper isolation and grounding
- Use current-limited test circuits
- Never touch circuits while powered
Future Enhancements
Potential areas for test expansion:
-
Performance Tests
- Measure ISR timing
- Verify zero-crossing detection accuracy
- Test rapid power changes
-
Stress Tests
- Maximum dimmer count (50 dimmers)
- Continuous operation for extended periods
- Rapid state/mode changes
-
Hardware-in-the-Loop Tests
- Actual zero-crossing signal simulation
- TRIAC timing verification
- Multi-frequency testing (50Hz/60Hz)
-
Error Handling Tests
- Invalid GPIO pins
- Null pointer handling
- Resource exhaustion scenarios
References
Support
For questions or issues:
- Open an issue on GitHub
- Check existing issues and discussions
- Review the test code for examples