-
Notifications
You must be signed in to change notification settings - Fork 19
create unit test for swc
- Prerequisites
- Introduction
- Folder structure
- Setup test runner folder
- Analyze the test Function
- write CMake files
- Excute
unit_test
rule and solve errors - Write Unit tests
- Output
This wiki page outlines how to create a unit test for dio_swc
.
This is a proposal for the unit test folder structure. Try to follow this structure to unify the general concept across the entire project.
software/bsw/mcal/dio_swc
│
├── CMakeLists.txt
├── core
│ ├── Dio.c
│ ├── Dio.h
│ └── Dio_MemMap.h
├── tests
│ └── unit
│ ├── stubs
│ ├── test_dio_swc.c
│ └── test_runners
│ ├── test_main.c
│ └── test_runner.c
└── tools
└── cmake
├── dio_swc_compile.cmake
└── dio_swc_tests.cmake
You will find template for different files in files test_main.c
#include "unity_fixture.h"
static void RunAllTests(void)
{
RUN_TEST_GROUP(dio_swc);
}
int main(int argc, const char * argv[])
{
return UnityMain(argc, argv, RunAllTests);
}
test_runner.c
#include "unity.h"
#include "unity_fixture.h"
TEST_GROUP_RUNNER(dio_swc)
{
RUN_TEST_CASE(dio_swc, TC1);
RUN_TEST_CASE(dio_swc, TC2);
}
test_dio_swc.c
#include "unity.h"
#include "unity_fixture.h"
TEST_GROUP(dio_swc);
TEST_SETUP(dio_swc)
{
}
TEST_TEAR_DOWN(dio_swc)
{
}
TEST(dio_swc, TC1)
{
}
TEST(dio_swc, TC2)
{
}
We need to analyze the function to perform unit tests on it and determine its dependencies.
void Dio_GetVersionInfo(Std_VersionInfoType *VersionInfo)
{
// Check if DET is enabled and if VersionInfo pointer is NULL
#ifdef DIO_DEV_ERROR_DETECT
if (VersionInfo == NULL)
{
// Report error and return without any action
Det_ReportError(DIO_MODULE_ID, DIO_INSTANCE_ID, DIO_GET_VERSION_INFO_SID, DIO_E_PARAM_POINTER);
return;
}
#endif
// Fill the VersionInfo structure with module version information
VersionInfo->vendorID = 0;
VersionInfo->moduleID = DIO_MODULE_ID;
VersionInfo->instanceID = DIO_INSTANCE_ID;
VersionInfo->sw_major_version = DIO_CFG_SW_MAJOR_VERSION;
VersionInfo->sw_minor_version = DIO_CFG_SW_MINOR_VERSION;
VersionInfo->sw_patch_version = DIO_CFG_SW_PATCH_VERSION;
VersionInfo->ar_major_version = DIO_CFG_AR_RELEASE_MAJOR_VERSION;
VersionInfo->ar_minor_version = DIO_CFG_AR_RELEASE_MINOR_VERSION;
VersionInfo->ar_patch_version = DIO_CFG_AR_RELEASE_PATCH_VERSION;
}
In this function, the Det_ReportError
only needs to be mocked.
- For
software/bsw/mcal/dio_swc/tools/cmake/dio_swc_tests.cmake
set(
dio_swc_tests_sources_list
${dio_swc}/tests/unit/test_dio_swc.c # Main test file that contain the test cases
# Any mocked file will be under ${MOCK_FILE_PATH}/mocks/mock_headerFileName.c
${MOCK_FILE_PATH}/mocks/mock_Det.c # Include the mock_Det
# Include Test Runners
${dio_swc}/tests/unit/test_runners/test_runner.c
${dio_swc}/tests/unit/test_runners/test_main.c
)
set(
dio_swc_ut_sources_list
${dio_swc}/core/Dio.c # Main test file
${gendata}/Dio_Lcfg.c
)
set (
dio_swc_mock_header_files
${stubs}/Det.h # Det.h will be mocked
)
set(
dio_swc_tests_includes
${dio_swc}/core
${port_swc}/core
${gendata}
${common_includes}
${platform}
${stubs}
${dio_swc}/tests/unit/stubs # include stub folder
${MOCK_FILE_PATH}/mocks/ # MOCK_FILE_PATH will be assigend at `software/bsw/mcal/dio_swc/CMakeLists.txt`
)
set(
dio_swc_tests_compile_options
)
set(
dio_swc_tests_defines
)
For complete details on the usage of this variable, take a look at section Integrate CMock/Unity with project files
in * Unit Test Frameworks Integration.
- for
software/bsw/mcal/dio_swc/CMakeLists.txt
# CMake Version Check
cmake_minimum_required(VERSION 3.14)
# Project
project(dio_swc
LANGUAGES C CXX
VERSION "1.0.0"
DESCRIPTION "dio_swc")
##############################################################################
# Extract Module Path in build/CMake/Test/ #
##############################################################################
extract_module_path(dio_swc MOCK_FILE_PATH) #Assign the path of mock files @ MOCK_FILE_PATH variable
##############################################################################
# Include Common Compilation Settings #
##############################################################################
include(tools/cmake/dio_swc_compile.cmake) #Include Variables
##############################################################################
# Build Configuration #
##############################################################################
# Compilation Mode: Only build the library
if(MODE STREQUAL "COMPILING")
add_library(dio_swc ${dio_swc_sources_list})
target_compile_options(dio_swc PRIVATE ${dio_swc_compile_options})
target_include_directories(dio_swc PRIVATE ${dio_swc_includes})
target_compile_definitions(dio_swc PRIVATE ${dio_swc_defines})
elseif (MODE STREQUAL "TESTING")
include(tools/cmake/dio_swc_tests.cmake)
add_library(dio_swc ${dio_swc_ut_sources_list})
target_compile_options(dio_swc PRIVATE ${dio_swc_tests_compile_options})
target_include_directories(dio_swc PRIVATE ${dio_swc_tests_includes})
target_compile_definitions(dio_swc PRIVATE ${dio_swc_tests_defines})
endif()
if(MODE STREQUAL "TESTING")
# Execute CMock script to generate mock_Det.h
execute_process(
COMMAND ruby ${CMOCK_SCRIPT} -o${CMOCK_CONFIG_FILE} ${dio_swc_mock_header_files}
OUTPUT_VARIABLE CMOCK_OUTPUT
WORKING_DIRECTORY ${MOCK_FILE_PATH} # /workspace/tools/build/CMake/Test/software/bsw/mcal/dio_swc
)
message("CMock output: ${CMOCK_OUTPUT}")
# Testing Mode: Build the library and test executable
add_executable(dio_swc_test ${dio_swc_tests_sources_list} ${unity_common_sources})
target_compile_definitions(dio_swc_test PRIVATE ${dio_swc_tests_defines})
target_compile_options(dio_swc_test PRIVATE ${dio_swc_tests_compile_options})
target_include_directories(dio_swc_test PRIVATE ${dio_swc_tests_includes} ${unity_common_includes})
endif()
make unit_test rebuild=1
output
We encountered a linking error, as shown in the screenshot below The compiler was unable to locate the object files for
dio.c
andport.c
. We will address this issue by adding dio.c as an external library and mocking the port library.
- For
software/bsw/mcal/dio_swc/tools/cmake/dio_swc_tests.cmake
set (
dio_swc_mock_header_files
${stubs}/Det.h
${port_swc}/core/Port.h
)
set(
dio_swc_tests_libs
"dio_swc"
)
make unit_test rebuild=1
output
linking error, as shown in the screenshot below
and here a wise man once said "طيب ما تجرب يا أخي انت خسران حاجه" or
I search for this variable using the search feature in VSCode
I found that the variable is externally declared in port.h
and dio.h
, with its definition in port.c
.
we can define it in our test file or i will add them in file called stub_structure.h
software/bsw/mcal/dio_swc/tests/unit/stubs/stub_structure.h
#include "stdint.h"
#include "Port.h"
typedef struct
{ /*port Structure*/
int32_t RESERVED0[255];
uint32_t DATA; /*port Data*/
uint32_t DIR; /*port Direction*/
uint32_t IS; /*port Interrupt Sense*/
uint32_t IBE; /*port Interrupt Both Edges*/
uint32_t IEV; /*port Interrupt Event*/
uint32_t IM; /*port Interrupt Mask*/
uint32_t RIS; /*port Raw Interrupt Status*/
uint32_t MIS; /*port Masked Interrupt Status*/
int32_t ICR; /*port Interrupt Clear*/
uint32_t AFSEL; /*port Alternate Function Select*/
int32_t RESERVED1[55];
uint32_t DR2R; /*port 2-mA Drive Select*/
uint32_t DR4R; /*port 4-mA Drive Select*/
uint32_t DR8R; /*port 8-mA Drive Select*/
uint32_t ODR; /*port Open Drain Select*/
uint32_t PUR; /*port Pull-Up Select*/
uint32_t PDR; /*port Pull-Down Select*/
uint32_t SLR; /*port Slew Rate Control Select*/
uint32_t DEN; /*port Digital Enable*/
uint32_t LOCK; /*port Lock*/
int32_t CR; /*port Commit*/
uint32_t AMSEL; /*port Analog Mode Select*/
uint32_t PCTL; /*port Port Control*/
uint32_t ADCCTL; /*port ADC Control*/
uint32_t DMACTL; /*port DMA Control*/
} Port_Type;
uint32_t PORTA_VAR = 0 ;
uint32_t PORTB_VAR = 0 ;
uint32_t PORTC_VAR = 0 ;
uint32_t PORTD_VAR = 0 ;
uint32_t PORTE_VAR = 0 ;
uint32_t PORTF_VAR = 0 ;
#define PORTA &PORTA_VAR // Change HW address by variable address to avoid segmentation fault
#define PORTB &PORTB_VAR
#define PORTC &PORTC_VAR
#define PORTD &PORTD_VAR
#define PORTE &PORTE_VAR
#define PORTF &PORTF_VAR
/* Define the base addresses of the ports */
Port_Type *portBaseAddresses[] = {
PORTA,
PORTB,
PORTC,
PORTD,
PORTE,
PORTF};
Finalllly it works <3
TEST(dio_swc, test_Dio_GetVersionInfo_ValidVersionInfo)
{
// Define a Std_VersionInfoType structure to hold version information
Std_VersionInfoType versionInfo;
// Call the function with a valid pointer to versionInfo
Dio_GetVersionInfo(&versionInfo);
// Check if the versionInfo structure is correctly filled
TEST_ASSERT_EQUAL(0, versionInfo.vendorID);
TEST_ASSERT_EQUAL(DIO_MODULE_ID, versionInfo.moduleID);
TEST_ASSERT_EQUAL(DIO_INSTANCE_ID, versionInfo.instanceID);
TEST_ASSERT_EQUAL(DIO_CFG_SW_MAJOR_VERSION, versionInfo.sw_major_version);
TEST_ASSERT_EQUAL(DIO_CFG_SW_MINOR_VERSION, versionInfo.sw_minor_version);
TEST_ASSERT_EQUAL(DIO_CFG_SW_PATCH_VERSION, versionInfo.sw_patch_version);
TEST_ASSERT_EQUAL(DIO_CFG_AR_RELEASE_MAJOR_VERSION, versionInfo.ar_major_version);
TEST_ASSERT_EQUAL(DIO_CFG_AR_RELEASE_MINOR_VERSION, versionInfo.ar_minor_version);
TEST_ASSERT_EQUAL(DIO_CFG_AR_RELEASE_PATCH_VERSION, versionInfo.ar_patch_version);
}
TEST(dio_swc, test_Dio_GetVersionInfo_VersionInfo_Null)
{
// Expect a call to Det_ReportError with specific parameters and return E_OK
Det_ReportError_ExpectAndReturn(DIO_MODULE_ID, DIO_INSTANCE_ID, DIO_GET_VERSION_INFO_SID, DIO_E_PARAM_POINTER,E_OK);
// Call the function with a null pointer
Dio_GetVersionInfo(NULL);
}
brooo make sure you add your test function test_Dio_GetVersionInfo_ValidVersionInfo_Null
, test_Dio_GetVersionInfo_VersionInfo_Null
and to the test runner file.
TEST_GROUP_RUNNER(dio_swc)
{
RUN_TEST_CASE(dio_swc, test_Dio_GetVersionInfo_ValidVersionInfo)
RUN_TEST_CASE(dio_swc, test_Dio_GetVersionInfo_VersionInfo_Null)
}
make unit_test rebuild=1
the html report will be @ tools/build/CMake/output/tests/unit/html