mirror of
https://github.com/pmarchini/Esp32Dimmer.git
synced 2026-02-07 03:08:07 +03:00
Add comprehensive unit tests for ESP32 Dimmer Driver library
Co-authored-by: pmarchini <49943249+pmarchini@users.noreply.github.com>
This commit is contained in:
23
README.md
23
README.md
@@ -71,6 +71,29 @@ To use the basic example, add the component to your project's components directo
|
|||||||
|
|
||||||
If you are using the library in a project that is not using ESP-IDF 5.x, you can still use the old version of the library (v1.0.0) which is compatible with ESP-IDF 4.x.
|
If you are using the library in a project that is not using ESP-IDF 5.x, you can still use the old version of the library (v1.0.0) which is compatible with ESP-IDF 4.x.
|
||||||
|
|
||||||
|
## Testing
|
||||||
|
|
||||||
|
This library includes comprehensive unit tests to ensure reliability and enable safe refactoring. The tests cover all public API functions including:
|
||||||
|
|
||||||
|
- Dimmer creation and initialization
|
||||||
|
- Power control with boundary conditions
|
||||||
|
- State management (ON/OFF)
|
||||||
|
- Mode management (NORMAL/TOGGLE)
|
||||||
|
- Multiple independent dimmers
|
||||||
|
|
||||||
|
### Running Tests
|
||||||
|
|
||||||
|
To run the unit tests:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd test_app
|
||||||
|
idf.py set-target esp32
|
||||||
|
idf.py build
|
||||||
|
idf.py -p /dev/ttyUSB0 flash monitor
|
||||||
|
```
|
||||||
|
|
||||||
|
See [test_app/README.md](test_app/README.md) for detailed testing documentation.
|
||||||
|
|
||||||
## Contributing
|
## Contributing
|
||||||
|
|
||||||
We welcome contributions to this library. Please open a pull request or an issue to get started.
|
We welcome contributions to this library. Please open a pull request or an issue to get started.
|
||||||
|
|||||||
@@ -0,0 +1,5 @@
|
|||||||
|
idf_component_register(
|
||||||
|
SRCS "test_esp32_dimmer.c"
|
||||||
|
INCLUDE_DIRS "."
|
||||||
|
REQUIRES unity esp32-triac-dimmer-driver
|
||||||
|
)
|
||||||
@@ -0,0 +1,315 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include "unity.h"
|
||||||
|
#include "esp32-triac-dimmer-driver.h"
|
||||||
|
#include "freertos/FreeRTOS.h"
|
||||||
|
#include "freertos/task.h"
|
||||||
|
#include "driver/gpio.h"
|
||||||
|
|
||||||
|
// Test GPIO pins (using safe GPIO pins for testing)
|
||||||
|
#define TEST_TRIAC_GPIO GPIO_NUM_22
|
||||||
|
#define TEST_TRIAC_GPIO_2 GPIO_NUM_23
|
||||||
|
#define TEST_ZC_GPIO GPIO_NUM_21
|
||||||
|
|
||||||
|
// External variable to reset dimmer count for testing
|
||||||
|
extern int current_dim;
|
||||||
|
|
||||||
|
void setUp(void)
|
||||||
|
{
|
||||||
|
// This is run before each test
|
||||||
|
}
|
||||||
|
|
||||||
|
void tearDown(void)
|
||||||
|
{
|
||||||
|
// This is run after each test
|
||||||
|
// Note: We cannot easily reset the dimmer state between tests due to
|
||||||
|
// hardware initialization, so tests should be designed to be independent
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test: createDimmer function creates a valid dimmer object
|
||||||
|
void test_createDimmer_returns_valid_pointer(void)
|
||||||
|
{
|
||||||
|
dimmertyp *dimmer = createDimmer(TEST_TRIAC_GPIO, TEST_ZC_GPIO);
|
||||||
|
|
||||||
|
TEST_ASSERT_NOT_NULL(dimmer);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test: createDimmer with different GPIO pins
|
||||||
|
void test_createDimmer_with_different_pins(void)
|
||||||
|
{
|
||||||
|
dimmertyp *dimmer1 = createDimmer(TEST_TRIAC_GPIO, TEST_ZC_GPIO);
|
||||||
|
dimmertyp *dimmer2 = createDimmer(TEST_TRIAC_GPIO_2, TEST_ZC_GPIO);
|
||||||
|
|
||||||
|
TEST_ASSERT_NOT_NULL(dimmer1);
|
||||||
|
TEST_ASSERT_NOT_NULL(dimmer2);
|
||||||
|
TEST_ASSERT_NOT_EQUAL(dimmer1, dimmer2);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test: setPower and getPower functions
|
||||||
|
void test_setPower_getPower_normal_values(void)
|
||||||
|
{
|
||||||
|
dimmertyp *dimmer = createDimmer(TEST_TRIAC_GPIO, TEST_ZC_GPIO);
|
||||||
|
TEST_ASSERT_NOT_NULL(dimmer);
|
||||||
|
|
||||||
|
// Initialize the dimmer
|
||||||
|
begin(dimmer, NORMAL_MODE, ON, 50);
|
||||||
|
|
||||||
|
// Test setting power to 50
|
||||||
|
setPower(dimmer, 50);
|
||||||
|
vTaskDelay(pdMS_TO_TICKS(10)); // Allow time for setting
|
||||||
|
TEST_ASSERT_EQUAL(50, getPower(dimmer));
|
||||||
|
|
||||||
|
// Test setting power to 0
|
||||||
|
setPower(dimmer, 0);
|
||||||
|
vTaskDelay(pdMS_TO_TICKS(10));
|
||||||
|
TEST_ASSERT_EQUAL(0, getPower(dimmer));
|
||||||
|
|
||||||
|
// Test setting power to 99 (max valid value)
|
||||||
|
setPower(dimmer, 99);
|
||||||
|
vTaskDelay(pdMS_TO_TICKS(10));
|
||||||
|
TEST_ASSERT_EQUAL(99, getPower(dimmer));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test: setPower with boundary values
|
||||||
|
void test_setPower_boundary_values(void)
|
||||||
|
{
|
||||||
|
dimmertyp *dimmer = createDimmer(TEST_TRIAC_GPIO, TEST_ZC_GPIO);
|
||||||
|
TEST_ASSERT_NOT_NULL(dimmer);
|
||||||
|
|
||||||
|
begin(dimmer, NORMAL_MODE, ON, 50);
|
||||||
|
|
||||||
|
// Test setting power above maximum (should be clamped to 99)
|
||||||
|
setPower(dimmer, 100);
|
||||||
|
vTaskDelay(pdMS_TO_TICKS(10));
|
||||||
|
TEST_ASSERT_EQUAL(99, getPower(dimmer));
|
||||||
|
|
||||||
|
// Test setting power way above maximum
|
||||||
|
setPower(dimmer, 150);
|
||||||
|
vTaskDelay(pdMS_TO_TICKS(10));
|
||||||
|
TEST_ASSERT_EQUAL(99, getPower(dimmer));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test: getPower returns 0 when dimmer is OFF
|
||||||
|
void test_getPower_when_dimmer_off(void)
|
||||||
|
{
|
||||||
|
dimmertyp *dimmer = createDimmer(TEST_TRIAC_GPIO, TEST_ZC_GPIO);
|
||||||
|
TEST_ASSERT_NOT_NULL(dimmer);
|
||||||
|
|
||||||
|
begin(dimmer, NORMAL_MODE, OFF, 50);
|
||||||
|
|
||||||
|
setPower(dimmer, 50);
|
||||||
|
vTaskDelay(pdMS_TO_TICKS(10));
|
||||||
|
|
||||||
|
// When dimmer is OFF, getPower should return 0
|
||||||
|
TEST_ASSERT_EQUAL(0, getPower(dimmer));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test: setState and getState functions
|
||||||
|
void test_setState_getState(void)
|
||||||
|
{
|
||||||
|
dimmertyp *dimmer = createDimmer(TEST_TRIAC_GPIO, TEST_ZC_GPIO);
|
||||||
|
TEST_ASSERT_NOT_NULL(dimmer);
|
||||||
|
|
||||||
|
begin(dimmer, NORMAL_MODE, ON, 50);
|
||||||
|
|
||||||
|
// Test setting state to ON
|
||||||
|
setState(dimmer, ON);
|
||||||
|
TEST_ASSERT_TRUE(getState(dimmer));
|
||||||
|
|
||||||
|
// Test setting state to OFF
|
||||||
|
setState(dimmer, OFF);
|
||||||
|
TEST_ASSERT_FALSE(getState(dimmer));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test: changeState function toggles state
|
||||||
|
void test_changeState_toggles_state(void)
|
||||||
|
{
|
||||||
|
dimmertyp *dimmer = createDimmer(TEST_TRIAC_GPIO, TEST_ZC_GPIO);
|
||||||
|
TEST_ASSERT_NOT_NULL(dimmer);
|
||||||
|
|
||||||
|
begin(dimmer, NORMAL_MODE, ON, 50);
|
||||||
|
|
||||||
|
// Initial state is ON
|
||||||
|
TEST_ASSERT_TRUE(getState(dimmer));
|
||||||
|
|
||||||
|
// Change state should toggle to OFF
|
||||||
|
changeState(dimmer);
|
||||||
|
TEST_ASSERT_FALSE(getState(dimmer));
|
||||||
|
|
||||||
|
// Change state again should toggle back to ON
|
||||||
|
changeState(dimmer);
|
||||||
|
TEST_ASSERT_TRUE(getState(dimmer));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test: setMode and getMode functions
|
||||||
|
void test_setMode_getMode(void)
|
||||||
|
{
|
||||||
|
dimmertyp *dimmer = createDimmer(TEST_TRIAC_GPIO, TEST_ZC_GPIO);
|
||||||
|
TEST_ASSERT_NOT_NULL(dimmer);
|
||||||
|
|
||||||
|
begin(dimmer, NORMAL_MODE, ON, 50);
|
||||||
|
|
||||||
|
// Test setting to NORMAL_MODE
|
||||||
|
setMode(dimmer, NORMAL_MODE);
|
||||||
|
TEST_ASSERT_EQUAL(NORMAL_MODE, getMode(dimmer));
|
||||||
|
|
||||||
|
// Test setting to TOGGLE_MODE
|
||||||
|
setMode(dimmer, TOGGLE_MODE);
|
||||||
|
TEST_ASSERT_EQUAL(TOGGLE_MODE, getMode(dimmer));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test: toggleSettings function
|
||||||
|
void test_toggleSettings_with_valid_values(void)
|
||||||
|
{
|
||||||
|
dimmertyp *dimmer = createDimmer(TEST_TRIAC_GPIO, TEST_ZC_GPIO);
|
||||||
|
TEST_ASSERT_NOT_NULL(dimmer);
|
||||||
|
|
||||||
|
begin(dimmer, NORMAL_MODE, ON, 50);
|
||||||
|
|
||||||
|
// Test toggle settings with valid range
|
||||||
|
toggleSettings(dimmer, 10, 90);
|
||||||
|
|
||||||
|
// After toggleSettings, mode should be TOGGLE_MODE
|
||||||
|
TEST_ASSERT_EQUAL(TOGGLE_MODE, getMode(dimmer));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test: toggleSettings with boundary values
|
||||||
|
void test_toggleSettings_boundary_values(void)
|
||||||
|
{
|
||||||
|
dimmertyp *dimmer = createDimmer(TEST_TRIAC_GPIO, TEST_ZC_GPIO);
|
||||||
|
TEST_ASSERT_NOT_NULL(dimmer);
|
||||||
|
|
||||||
|
begin(dimmer, NORMAL_MODE, ON, 50);
|
||||||
|
|
||||||
|
// Test toggle settings with max value above 99 (should be clamped)
|
||||||
|
toggleSettings(dimmer, 5, 100);
|
||||||
|
TEST_ASSERT_EQUAL(TOGGLE_MODE, getMode(dimmer));
|
||||||
|
|
||||||
|
// Test toggle settings with min value below 1 (should be clamped)
|
||||||
|
toggleSettings(dimmer, 0, 80);
|
||||||
|
TEST_ASSERT_EQUAL(TOGGLE_MODE, getMode(dimmer));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test: begin function with NORMAL_MODE
|
||||||
|
void test_begin_with_normal_mode(void)
|
||||||
|
{
|
||||||
|
dimmertyp *dimmer = createDimmer(TEST_TRIAC_GPIO, TEST_ZC_GPIO);
|
||||||
|
TEST_ASSERT_NOT_NULL(dimmer);
|
||||||
|
|
||||||
|
// Begin with NORMAL_MODE, ON state, 50Hz
|
||||||
|
begin(dimmer, NORMAL_MODE, ON, 50);
|
||||||
|
|
||||||
|
TEST_ASSERT_EQUAL(NORMAL_MODE, getMode(dimmer));
|
||||||
|
TEST_ASSERT_TRUE(getState(dimmer));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test: begin function with TOGGLE_MODE
|
||||||
|
void test_begin_with_toggle_mode(void)
|
||||||
|
{
|
||||||
|
dimmertyp *dimmer = createDimmer(TEST_TRIAC_GPIO, TEST_ZC_GPIO);
|
||||||
|
TEST_ASSERT_NOT_NULL(dimmer);
|
||||||
|
|
||||||
|
// Begin with TOGGLE_MODE, OFF state, 60Hz
|
||||||
|
begin(dimmer, TOGGLE_MODE, OFF, 60);
|
||||||
|
|
||||||
|
TEST_ASSERT_EQUAL(TOGGLE_MODE, getMode(dimmer));
|
||||||
|
TEST_ASSERT_FALSE(getState(dimmer));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test: Multiple dimmers can be created and managed independently
|
||||||
|
void test_multiple_dimmers_independent(void)
|
||||||
|
{
|
||||||
|
dimmertyp *dimmer1 = createDimmer(TEST_TRIAC_GPIO, TEST_ZC_GPIO);
|
||||||
|
dimmertyp *dimmer2 = createDimmer(TEST_TRIAC_GPIO_2, TEST_ZC_GPIO);
|
||||||
|
|
||||||
|
TEST_ASSERT_NOT_NULL(dimmer1);
|
||||||
|
TEST_ASSERT_NOT_NULL(dimmer2);
|
||||||
|
|
||||||
|
begin(dimmer1, NORMAL_MODE, ON, 50);
|
||||||
|
begin(dimmer2, TOGGLE_MODE, OFF, 50);
|
||||||
|
|
||||||
|
setPower(dimmer1, 30);
|
||||||
|
setPower(dimmer2, 70);
|
||||||
|
|
||||||
|
vTaskDelay(pdMS_TO_TICKS(10));
|
||||||
|
|
||||||
|
// Verify each dimmer maintains independent state
|
||||||
|
TEST_ASSERT_EQUAL(NORMAL_MODE, getMode(dimmer1));
|
||||||
|
TEST_ASSERT_EQUAL(TOGGLE_MODE, getMode(dimmer2));
|
||||||
|
|
||||||
|
TEST_ASSERT_EQUAL(30, getPower(dimmer1));
|
||||||
|
TEST_ASSERT_EQUAL(0, getPower(dimmer2)); // dimmer2 is OFF, so getPower returns 0
|
||||||
|
|
||||||
|
TEST_ASSERT_TRUE(getState(dimmer1));
|
||||||
|
TEST_ASSERT_FALSE(getState(dimmer2));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test: State changes affect getPower behavior
|
||||||
|
void test_state_affects_getPower(void)
|
||||||
|
{
|
||||||
|
dimmertyp *dimmer = createDimmer(TEST_TRIAC_GPIO, TEST_ZC_GPIO);
|
||||||
|
TEST_ASSERT_NOT_NULL(dimmer);
|
||||||
|
|
||||||
|
begin(dimmer, NORMAL_MODE, ON, 50);
|
||||||
|
|
||||||
|
// Set power and verify when ON
|
||||||
|
setPower(dimmer, 75);
|
||||||
|
vTaskDelay(pdMS_TO_TICKS(10));
|
||||||
|
TEST_ASSERT_EQUAL(75, getPower(dimmer));
|
||||||
|
|
||||||
|
// Turn OFF and verify getPower returns 0
|
||||||
|
setState(dimmer, OFF);
|
||||||
|
TEST_ASSERT_EQUAL(0, getPower(dimmer));
|
||||||
|
|
||||||
|
// Turn back ON and verify power is still 75
|
||||||
|
setState(dimmer, ON);
|
||||||
|
TEST_ASSERT_EQUAL(75, getPower(dimmer));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Main test runner
|
||||||
|
void app_main(void)
|
||||||
|
{
|
||||||
|
printf("\n\n");
|
||||||
|
printf("========================================\n");
|
||||||
|
printf("ESP32 Dimmer Driver Unit Tests\n");
|
||||||
|
printf("========================================\n\n");
|
||||||
|
|
||||||
|
UNITY_BEGIN();
|
||||||
|
|
||||||
|
// Dimmer creation tests
|
||||||
|
RUN_TEST(test_createDimmer_returns_valid_pointer);
|
||||||
|
RUN_TEST(test_createDimmer_with_different_pins);
|
||||||
|
|
||||||
|
// Power control tests
|
||||||
|
RUN_TEST(test_setPower_getPower_normal_values);
|
||||||
|
RUN_TEST(test_setPower_boundary_values);
|
||||||
|
RUN_TEST(test_getPower_when_dimmer_off);
|
||||||
|
|
||||||
|
// State management tests
|
||||||
|
RUN_TEST(test_setState_getState);
|
||||||
|
RUN_TEST(test_changeState_toggles_state);
|
||||||
|
RUN_TEST(test_state_affects_getPower);
|
||||||
|
|
||||||
|
// Mode management tests
|
||||||
|
RUN_TEST(test_setMode_getMode);
|
||||||
|
RUN_TEST(test_toggleSettings_with_valid_values);
|
||||||
|
RUN_TEST(test_toggleSettings_boundary_values);
|
||||||
|
|
||||||
|
// Initialization tests
|
||||||
|
RUN_TEST(test_begin_with_normal_mode);
|
||||||
|
RUN_TEST(test_begin_with_toggle_mode);
|
||||||
|
|
||||||
|
// Multiple dimmer tests
|
||||||
|
RUN_TEST(test_multiple_dimmers_independent);
|
||||||
|
|
||||||
|
UNITY_END();
|
||||||
|
|
||||||
|
printf("\n========================================\n");
|
||||||
|
printf("All tests completed!\n");
|
||||||
|
printf("========================================\n\n");
|
||||||
|
|
||||||
|
// Keep the app running
|
||||||
|
while(1) {
|
||||||
|
vTaskDelay(pdMS_TO_TICKS(1000));
|
||||||
|
}
|
||||||
|
}
|
||||||
8
test_app/.gitignore
vendored
Normal file
8
test_app/.gitignore
vendored
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
build/
|
||||||
|
sdkconfig
|
||||||
|
sdkconfig.old
|
||||||
|
*.swp
|
||||||
|
*.swo
|
||||||
|
*.pyc
|
||||||
|
dependencies.lock
|
||||||
|
managed_components/
|
||||||
8
test_app/CMakeLists.txt
Normal file
8
test_app/CMakeLists.txt
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
cmake_minimum_required(VERSION 3.16)
|
||||||
|
|
||||||
|
# Add the component directory to the component search path
|
||||||
|
set(EXTRA_COMPONENT_DIRS ../src/components)
|
||||||
|
|
||||||
|
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
|
||||||
|
|
||||||
|
project(esp32_dimmer_tests)
|
||||||
147
test_app/README.md
Normal file
147
test_app/README.md
Normal file
@@ -0,0 +1,147 @@
|
|||||||
|
# ESP32 Dimmer Driver Unit Tests
|
||||||
|
|
||||||
|
This directory contains unit tests for the ESP32 Dimmer Driver library.
|
||||||
|
|
||||||
|
## Test Structure
|
||||||
|
|
||||||
|
The tests are organized using the ESP-IDF Unity testing framework and cover the following functionality:
|
||||||
|
|
||||||
|
### Test Categories
|
||||||
|
|
||||||
|
1. **Dimmer Creation Tests**
|
||||||
|
- `test_createDimmer_returns_valid_pointer`: Verifies that createDimmer returns a valid pointer
|
||||||
|
- `test_createDimmer_with_different_pins`: Tests creating multiple dimmers with different GPIO pins
|
||||||
|
|
||||||
|
2. **Power Control Tests**
|
||||||
|
- `test_setPower_getPower_normal_values`: Tests setting and getting power with normal values (0, 50, 99)
|
||||||
|
- `test_setPower_boundary_values`: Tests boundary conditions (values above 99 are clamped)
|
||||||
|
- `test_getPower_when_dimmer_off`: Verifies getPower returns 0 when dimmer is OFF
|
||||||
|
|
||||||
|
3. **State Management Tests**
|
||||||
|
- `test_setState_getState`: Tests setting and getting the dimmer state (ON/OFF)
|
||||||
|
- `test_changeState_toggles_state`: Verifies changeState toggles between ON and OFF
|
||||||
|
- `test_state_affects_getPower`: Tests that state changes affect getPower behavior
|
||||||
|
|
||||||
|
4. **Mode Management Tests**
|
||||||
|
- `test_setMode_getMode`: Tests setting and getting dimmer modes (NORMAL/TOGGLE)
|
||||||
|
- `test_toggleSettings_with_valid_values`: Tests toggle settings with valid range
|
||||||
|
- `test_toggleSettings_boundary_values`: Tests toggle settings with boundary values
|
||||||
|
|
||||||
|
5. **Initialization Tests**
|
||||||
|
- `test_begin_with_normal_mode`: Tests initialization with NORMAL_MODE
|
||||||
|
- `test_begin_with_toggle_mode`: Tests initialization with TOGGLE_MODE
|
||||||
|
|
||||||
|
6. **Multiple Dimmer Tests**
|
||||||
|
- `test_multiple_dimmers_independent`: Verifies multiple dimmers operate independently
|
||||||
|
|
||||||
|
## Running the Tests
|
||||||
|
|
||||||
|
### Prerequisites
|
||||||
|
|
||||||
|
- ESP-IDF v5.0 or higher installed
|
||||||
|
- ESP32 development board (tests can run without actual hardware connected)
|
||||||
|
|
||||||
|
### Build and Flash
|
||||||
|
|
||||||
|
1. Navigate to the test_app directory:
|
||||||
|
```bash
|
||||||
|
cd test_app
|
||||||
|
```
|
||||||
|
|
||||||
|
2. Set the target (if not already set):
|
||||||
|
```bash
|
||||||
|
idf.py set-target esp32
|
||||||
|
```
|
||||||
|
|
||||||
|
3. Build the test application:
|
||||||
|
```bash
|
||||||
|
idf.py build
|
||||||
|
```
|
||||||
|
|
||||||
|
4. Flash to your ESP32 board:
|
||||||
|
```bash
|
||||||
|
idf.py -p /dev/ttyUSB0 flash monitor
|
||||||
|
```
|
||||||
|
Replace `/dev/ttyUSB0` with your serial port.
|
||||||
|
|
||||||
|
### Expected Output
|
||||||
|
|
||||||
|
When the tests run successfully, you should see output similar to:
|
||||||
|
|
||||||
|
```
|
||||||
|
========================================
|
||||||
|
ESP32 Dimmer Driver Unit Tests
|
||||||
|
========================================
|
||||||
|
|
||||||
|
Running test_createDimmer_returns_valid_pointer...
|
||||||
|
PASS
|
||||||
|
|
||||||
|
Running test_createDimmer_with_different_pins...
|
||||||
|
PASS
|
||||||
|
|
||||||
|
...
|
||||||
|
|
||||||
|
========================================
|
||||||
|
All tests completed!
|
||||||
|
========================================
|
||||||
|
|
||||||
|
16 Tests 0 Failures 0 Ignored
|
||||||
|
OK
|
||||||
|
```
|
||||||
|
|
||||||
|
## Test Coverage
|
||||||
|
|
||||||
|
The unit tests cover:
|
||||||
|
|
||||||
|
- ✅ Dimmer object creation
|
||||||
|
- ✅ Power setting and retrieval with boundary conditions
|
||||||
|
- ✅ State management (ON/OFF)
|
||||||
|
- ✅ Mode management (NORMAL/TOGGLE)
|
||||||
|
- ✅ Toggle settings configuration
|
||||||
|
- ✅ Multiple independent dimmers
|
||||||
|
- ✅ State-dependent behavior
|
||||||
|
|
||||||
|
## Notes for Future Refactoring
|
||||||
|
|
||||||
|
These unit tests are designed to:
|
||||||
|
|
||||||
|
1. **Enable safe refactoring**: The tests verify the API contract, allowing you to refactor internal implementation while ensuring the public API behavior remains consistent.
|
||||||
|
|
||||||
|
2. **Document expected behavior**: Each test serves as executable documentation of how the library should behave.
|
||||||
|
|
||||||
|
3. **Catch regressions**: Running these tests after changes helps catch any unintended behavior changes.
|
||||||
|
|
||||||
|
4. **Hardware independence**: These tests focus on the software logic and can run without actual dimmer hardware connected. They test the API layer and state management.
|
||||||
|
|
||||||
|
## Limitations
|
||||||
|
|
||||||
|
- These tests do not verify actual hardware functionality (zero-crossing detection, TRIAC firing)
|
||||||
|
- ISR behavior is not directly tested (requires hardware/simulation)
|
||||||
|
- Timing-critical code paths are not fully tested without hardware
|
||||||
|
|
||||||
|
For hardware integration testing, additional tests would be needed with actual hardware or simulation.
|
||||||
|
|
||||||
|
## Adding New Tests
|
||||||
|
|
||||||
|
To add new tests:
|
||||||
|
|
||||||
|
1. Add new test functions to `main/test_main.c`
|
||||||
|
2. Use the Unity assertion macros (TEST_ASSERT_*, etc.)
|
||||||
|
3. Register the test with `RUN_TEST()` in the `app_main()` function
|
||||||
|
4. Follow the naming convention: `test_<functionality>_<scenario>`
|
||||||
|
|
||||||
|
Example:
|
||||||
|
```c
|
||||||
|
void test_new_feature_basic_functionality(void)
|
||||||
|
{
|
||||||
|
dimmertyp *dimmer = createDimmer(TEST_TRIAC_GPIO, TEST_ZC_GPIO);
|
||||||
|
TEST_ASSERT_NOT_NULL(dimmer);
|
||||||
|
|
||||||
|
// Your test code here
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Then add to `app_main()`:
|
||||||
|
```c
|
||||||
|
RUN_TEST(test_new_feature_basic_functionality);
|
||||||
|
```
|
||||||
4
test_app/main/CMakeLists.txt
Normal file
4
test_app/main/CMakeLists.txt
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
idf_component_register(
|
||||||
|
SRCS "test_main.c"
|
||||||
|
INCLUDE_DIRS "."
|
||||||
|
)
|
||||||
313
test_app/main/test_main.c
Normal file
313
test_app/main/test_main.c
Normal file
@@ -0,0 +1,313 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include "unity.h"
|
||||||
|
#include "esp32-triac-dimmer-driver.h"
|
||||||
|
#include "freertos/FreeRTOS.h"
|
||||||
|
#include "freertos/task.h"
|
||||||
|
#include "driver/gpio.h"
|
||||||
|
|
||||||
|
// Test GPIO pins (using safe GPIO pins for testing)
|
||||||
|
#define TEST_TRIAC_GPIO GPIO_NUM_22
|
||||||
|
#define TEST_TRIAC_GPIO_2 GPIO_NUM_23
|
||||||
|
#define TEST_ZC_GPIO GPIO_NUM_21
|
||||||
|
|
||||||
|
// External variable to reset dimmer count for testing
|
||||||
|
extern int current_dim;
|
||||||
|
|
||||||
|
void setUp(void)
|
||||||
|
{
|
||||||
|
// This is run before each test
|
||||||
|
}
|
||||||
|
|
||||||
|
void tearDown(void)
|
||||||
|
{
|
||||||
|
// This is run after each test
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test: createDimmer function creates a valid dimmer object
|
||||||
|
void test_createDimmer_returns_valid_pointer(void)
|
||||||
|
{
|
||||||
|
dimmertyp *dimmer = createDimmer(TEST_TRIAC_GPIO, TEST_ZC_GPIO);
|
||||||
|
|
||||||
|
TEST_ASSERT_NOT_NULL(dimmer);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test: createDimmer with different GPIO pins
|
||||||
|
void test_createDimmer_with_different_pins(void)
|
||||||
|
{
|
||||||
|
dimmertyp *dimmer1 = createDimmer(TEST_TRIAC_GPIO, TEST_ZC_GPIO);
|
||||||
|
dimmertyp *dimmer2 = createDimmer(TEST_TRIAC_GPIO_2, TEST_ZC_GPIO);
|
||||||
|
|
||||||
|
TEST_ASSERT_NOT_NULL(dimmer1);
|
||||||
|
TEST_ASSERT_NOT_NULL(dimmer2);
|
||||||
|
TEST_ASSERT_NOT_EQUAL(dimmer1, dimmer2);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test: setPower and getPower functions
|
||||||
|
void test_setPower_getPower_normal_values(void)
|
||||||
|
{
|
||||||
|
dimmertyp *dimmer = createDimmer(TEST_TRIAC_GPIO, TEST_ZC_GPIO);
|
||||||
|
TEST_ASSERT_NOT_NULL(dimmer);
|
||||||
|
|
||||||
|
// Initialize the dimmer
|
||||||
|
begin(dimmer, NORMAL_MODE, ON, 50);
|
||||||
|
|
||||||
|
// Test setting power to 50
|
||||||
|
setPower(dimmer, 50);
|
||||||
|
vTaskDelay(pdMS_TO_TICKS(10));
|
||||||
|
TEST_ASSERT_EQUAL(50, getPower(dimmer));
|
||||||
|
|
||||||
|
// Test setting power to 0
|
||||||
|
setPower(dimmer, 0);
|
||||||
|
vTaskDelay(pdMS_TO_TICKS(10));
|
||||||
|
TEST_ASSERT_EQUAL(0, getPower(dimmer));
|
||||||
|
|
||||||
|
// Test setting power to 99 (max valid value)
|
||||||
|
setPower(dimmer, 99);
|
||||||
|
vTaskDelay(pdMS_TO_TICKS(10));
|
||||||
|
TEST_ASSERT_EQUAL(99, getPower(dimmer));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test: setPower with boundary values
|
||||||
|
void test_setPower_boundary_values(void)
|
||||||
|
{
|
||||||
|
dimmertyp *dimmer = createDimmer(TEST_TRIAC_GPIO, TEST_ZC_GPIO);
|
||||||
|
TEST_ASSERT_NOT_NULL(dimmer);
|
||||||
|
|
||||||
|
begin(dimmer, NORMAL_MODE, ON, 50);
|
||||||
|
|
||||||
|
// Test setting power above maximum (should be clamped to 99)
|
||||||
|
setPower(dimmer, 100);
|
||||||
|
vTaskDelay(pdMS_TO_TICKS(10));
|
||||||
|
TEST_ASSERT_EQUAL(99, getPower(dimmer));
|
||||||
|
|
||||||
|
// Test setting power way above maximum
|
||||||
|
setPower(dimmer, 150);
|
||||||
|
vTaskDelay(pdMS_TO_TICKS(10));
|
||||||
|
TEST_ASSERT_EQUAL(99, getPower(dimmer));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test: getPower returns 0 when dimmer is OFF
|
||||||
|
void test_getPower_when_dimmer_off(void)
|
||||||
|
{
|
||||||
|
dimmertyp *dimmer = createDimmer(TEST_TRIAC_GPIO, TEST_ZC_GPIO);
|
||||||
|
TEST_ASSERT_NOT_NULL(dimmer);
|
||||||
|
|
||||||
|
begin(dimmer, NORMAL_MODE, OFF, 50);
|
||||||
|
|
||||||
|
setPower(dimmer, 50);
|
||||||
|
vTaskDelay(pdMS_TO_TICKS(10));
|
||||||
|
|
||||||
|
// When dimmer is OFF, getPower should return 0
|
||||||
|
TEST_ASSERT_EQUAL(0, getPower(dimmer));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test: setState and getState functions
|
||||||
|
void test_setState_getState(void)
|
||||||
|
{
|
||||||
|
dimmertyp *dimmer = createDimmer(TEST_TRIAC_GPIO, TEST_ZC_GPIO);
|
||||||
|
TEST_ASSERT_NOT_NULL(dimmer);
|
||||||
|
|
||||||
|
begin(dimmer, NORMAL_MODE, ON, 50);
|
||||||
|
|
||||||
|
// Test setting state to ON
|
||||||
|
setState(dimmer, ON);
|
||||||
|
TEST_ASSERT_TRUE(getState(dimmer));
|
||||||
|
|
||||||
|
// Test setting state to OFF
|
||||||
|
setState(dimmer, OFF);
|
||||||
|
TEST_ASSERT_FALSE(getState(dimmer));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test: changeState function toggles state
|
||||||
|
void test_changeState_toggles_state(void)
|
||||||
|
{
|
||||||
|
dimmertyp *dimmer = createDimmer(TEST_TRIAC_GPIO, TEST_ZC_GPIO);
|
||||||
|
TEST_ASSERT_NOT_NULL(dimmer);
|
||||||
|
|
||||||
|
begin(dimmer, NORMAL_MODE, ON, 50);
|
||||||
|
|
||||||
|
// Initial state is ON
|
||||||
|
TEST_ASSERT_TRUE(getState(dimmer));
|
||||||
|
|
||||||
|
// Change state should toggle to OFF
|
||||||
|
changeState(dimmer);
|
||||||
|
TEST_ASSERT_FALSE(getState(dimmer));
|
||||||
|
|
||||||
|
// Change state again should toggle back to ON
|
||||||
|
changeState(dimmer);
|
||||||
|
TEST_ASSERT_TRUE(getState(dimmer));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test: setMode and getMode functions
|
||||||
|
void test_setMode_getMode(void)
|
||||||
|
{
|
||||||
|
dimmertyp *dimmer = createDimmer(TEST_TRIAC_GPIO, TEST_ZC_GPIO);
|
||||||
|
TEST_ASSERT_NOT_NULL(dimmer);
|
||||||
|
|
||||||
|
begin(dimmer, NORMAL_MODE, ON, 50);
|
||||||
|
|
||||||
|
// Test setting to NORMAL_MODE
|
||||||
|
setMode(dimmer, NORMAL_MODE);
|
||||||
|
TEST_ASSERT_EQUAL(NORMAL_MODE, getMode(dimmer));
|
||||||
|
|
||||||
|
// Test setting to TOGGLE_MODE
|
||||||
|
setMode(dimmer, TOGGLE_MODE);
|
||||||
|
TEST_ASSERT_EQUAL(TOGGLE_MODE, getMode(dimmer));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test: toggleSettings function
|
||||||
|
void test_toggleSettings_with_valid_values(void)
|
||||||
|
{
|
||||||
|
dimmertyp *dimmer = createDimmer(TEST_TRIAC_GPIO, TEST_ZC_GPIO);
|
||||||
|
TEST_ASSERT_NOT_NULL(dimmer);
|
||||||
|
|
||||||
|
begin(dimmer, NORMAL_MODE, ON, 50);
|
||||||
|
|
||||||
|
// Test toggle settings with valid range
|
||||||
|
toggleSettings(dimmer, 10, 90);
|
||||||
|
|
||||||
|
// After toggleSettings, mode should be TOGGLE_MODE
|
||||||
|
TEST_ASSERT_EQUAL(TOGGLE_MODE, getMode(dimmer));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test: toggleSettings with boundary values
|
||||||
|
void test_toggleSettings_boundary_values(void)
|
||||||
|
{
|
||||||
|
dimmertyp *dimmer = createDimmer(TEST_TRIAC_GPIO, TEST_ZC_GPIO);
|
||||||
|
TEST_ASSERT_NOT_NULL(dimmer);
|
||||||
|
|
||||||
|
begin(dimmer, NORMAL_MODE, ON, 50);
|
||||||
|
|
||||||
|
// Test toggle settings with max value above 99 (should be clamped)
|
||||||
|
toggleSettings(dimmer, 5, 100);
|
||||||
|
TEST_ASSERT_EQUAL(TOGGLE_MODE, getMode(dimmer));
|
||||||
|
|
||||||
|
// Test toggle settings with min value below 1 (should be clamped)
|
||||||
|
toggleSettings(dimmer, 0, 80);
|
||||||
|
TEST_ASSERT_EQUAL(TOGGLE_MODE, getMode(dimmer));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test: begin function with NORMAL_MODE
|
||||||
|
void test_begin_with_normal_mode(void)
|
||||||
|
{
|
||||||
|
dimmertyp *dimmer = createDimmer(TEST_TRIAC_GPIO, TEST_ZC_GPIO);
|
||||||
|
TEST_ASSERT_NOT_NULL(dimmer);
|
||||||
|
|
||||||
|
// Begin with NORMAL_MODE, ON state, 50Hz
|
||||||
|
begin(dimmer, NORMAL_MODE, ON, 50);
|
||||||
|
|
||||||
|
TEST_ASSERT_EQUAL(NORMAL_MODE, getMode(dimmer));
|
||||||
|
TEST_ASSERT_TRUE(getState(dimmer));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test: begin function with TOGGLE_MODE
|
||||||
|
void test_begin_with_toggle_mode(void)
|
||||||
|
{
|
||||||
|
dimmertyp *dimmer = createDimmer(TEST_TRIAC_GPIO, TEST_ZC_GPIO);
|
||||||
|
TEST_ASSERT_NOT_NULL(dimmer);
|
||||||
|
|
||||||
|
// Begin with TOGGLE_MODE, OFF state, 60Hz
|
||||||
|
begin(dimmer, TOGGLE_MODE, OFF, 60);
|
||||||
|
|
||||||
|
TEST_ASSERT_EQUAL(TOGGLE_MODE, getMode(dimmer));
|
||||||
|
TEST_ASSERT_FALSE(getState(dimmer));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test: Multiple dimmers can be created and managed independently
|
||||||
|
void test_multiple_dimmers_independent(void)
|
||||||
|
{
|
||||||
|
dimmertyp *dimmer1 = createDimmer(TEST_TRIAC_GPIO, TEST_ZC_GPIO);
|
||||||
|
dimmertyp *dimmer2 = createDimmer(TEST_TRIAC_GPIO_2, TEST_ZC_GPIO);
|
||||||
|
|
||||||
|
TEST_ASSERT_NOT_NULL(dimmer1);
|
||||||
|
TEST_ASSERT_NOT_NULL(dimmer2);
|
||||||
|
|
||||||
|
begin(dimmer1, NORMAL_MODE, ON, 50);
|
||||||
|
begin(dimmer2, TOGGLE_MODE, OFF, 50);
|
||||||
|
|
||||||
|
setPower(dimmer1, 30);
|
||||||
|
setPower(dimmer2, 70);
|
||||||
|
|
||||||
|
vTaskDelay(pdMS_TO_TICKS(10));
|
||||||
|
|
||||||
|
// Verify each dimmer maintains independent state
|
||||||
|
TEST_ASSERT_EQUAL(NORMAL_MODE, getMode(dimmer1));
|
||||||
|
TEST_ASSERT_EQUAL(TOGGLE_MODE, getMode(dimmer2));
|
||||||
|
|
||||||
|
TEST_ASSERT_EQUAL(30, getPower(dimmer1));
|
||||||
|
TEST_ASSERT_EQUAL(0, getPower(dimmer2)); // dimmer2 is OFF, so getPower returns 0
|
||||||
|
|
||||||
|
TEST_ASSERT_TRUE(getState(dimmer1));
|
||||||
|
TEST_ASSERT_FALSE(getState(dimmer2));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test: State changes affect getPower behavior
|
||||||
|
void test_state_affects_getPower(void)
|
||||||
|
{
|
||||||
|
dimmertyp *dimmer = createDimmer(TEST_TRIAC_GPIO, TEST_ZC_GPIO);
|
||||||
|
TEST_ASSERT_NOT_NULL(dimmer);
|
||||||
|
|
||||||
|
begin(dimmer, NORMAL_MODE, ON, 50);
|
||||||
|
|
||||||
|
// Set power and verify when ON
|
||||||
|
setPower(dimmer, 75);
|
||||||
|
vTaskDelay(pdMS_TO_TICKS(10));
|
||||||
|
TEST_ASSERT_EQUAL(75, getPower(dimmer));
|
||||||
|
|
||||||
|
// Turn OFF and verify getPower returns 0
|
||||||
|
setState(dimmer, OFF);
|
||||||
|
TEST_ASSERT_EQUAL(0, getPower(dimmer));
|
||||||
|
|
||||||
|
// Turn back ON and verify power is still 75
|
||||||
|
setState(dimmer, ON);
|
||||||
|
TEST_ASSERT_EQUAL(75, getPower(dimmer));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Main test runner
|
||||||
|
void app_main(void)
|
||||||
|
{
|
||||||
|
printf("\n\n");
|
||||||
|
printf("========================================\n");
|
||||||
|
printf("ESP32 Dimmer Driver Unit Tests\n");
|
||||||
|
printf("========================================\n\n");
|
||||||
|
|
||||||
|
UNITY_BEGIN();
|
||||||
|
|
||||||
|
// Dimmer creation tests
|
||||||
|
RUN_TEST(test_createDimmer_returns_valid_pointer);
|
||||||
|
RUN_TEST(test_createDimmer_with_different_pins);
|
||||||
|
|
||||||
|
// Power control tests
|
||||||
|
RUN_TEST(test_setPower_getPower_normal_values);
|
||||||
|
RUN_TEST(test_setPower_boundary_values);
|
||||||
|
RUN_TEST(test_getPower_when_dimmer_off);
|
||||||
|
|
||||||
|
// State management tests
|
||||||
|
RUN_TEST(test_setState_getState);
|
||||||
|
RUN_TEST(test_changeState_toggles_state);
|
||||||
|
RUN_TEST(test_state_affects_getPower);
|
||||||
|
|
||||||
|
// Mode management tests
|
||||||
|
RUN_TEST(test_setMode_getMode);
|
||||||
|
RUN_TEST(test_toggleSettings_with_valid_values);
|
||||||
|
RUN_TEST(test_toggleSettings_boundary_values);
|
||||||
|
|
||||||
|
// Initialization tests
|
||||||
|
RUN_TEST(test_begin_with_normal_mode);
|
||||||
|
RUN_TEST(test_begin_with_toggle_mode);
|
||||||
|
|
||||||
|
// Multiple dimmer tests
|
||||||
|
RUN_TEST(test_multiple_dimmers_independent);
|
||||||
|
|
||||||
|
UNITY_END();
|
||||||
|
|
||||||
|
printf("\n========================================\n");
|
||||||
|
printf("All tests completed!\n");
|
||||||
|
printf("========================================\n\n");
|
||||||
|
|
||||||
|
// Keep the app running
|
||||||
|
while(1) {
|
||||||
|
vTaskDelay(pdMS_TO_TICKS(1000));
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user