sobota, 19 grudnia 2020

Google test - Opis projektu w VSC CMake dla STM32

W tym poście chciałbym opisać sposób przygotowania projektu obsługującego Google Test w Visual Studio Code z wykorzystaniem CMake. Projekt może być wykorzystywany do testowania kodu wykonanego np w STM32Cube Ide.


[Źródło: https://en.wikipedia.org/wiki/Visual_Studio_Code]

Projekt wykonujący testy należy umieścić w tej samej lokalizacji co projekt główny w celu łatwiejszego podłączania testowanych bibliotek.

Projekt został wykonany z wykorzystaniem CMake. 

Plik CMakeLists.txt zlokalizowany w głównym folderze powinien wyglądać następująco:

  1. cmake_minimum_required(VERSION 3.10)
  2.  
  3. set(This Example)
  4.  
  5. project(&{This} C CXX)
  6.  
  7. set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -g")
  8.  
  9. set(CMAKE_POSITION_INDEPENDENT_CODE ON)
  10.  
  11. enable_testing()
  12.  
  13. add_subdirectory(googletest)
  14.  
  15. set(Headers
  16.     Core/Inc/subfolder_1/fileToTest_1.h
  17.     Core/Inc/subfolder_2/fileToTest_2.h
  18.     Core/Inc/fileToTest_3.h
  19. )
  20. set(Sources
  21.     Core/Src/subfolder_1/fileToTest_1.c
  22.     Core/Src/subfolder_2/fileToTest_2.c
  23.     Core/Src/fileToTest_3.c
  24. )
  25.  
  26. option(gtest_disable_pthreads "Disable uses of pthreads in gtest." ON)
  27.  
  28. add_library(Example STATIC ${Sources} ${Headers})
  29.  
  30. target_include_directories(Example PUBLIC "C:/Users/wojte/OneDrive/Pulpit/Programy_serwisowe/Tania_plyta/stm32h7/h7/Core/Inc")
  31.  
  32. target_include_directories(Example PUBLIC "C:/Users/wojte/OneDrive/Pulpit/Programy_serwisowe/Tania_plyta/stm32h7/h7/Core/Src")
  33.  
  34. add_subdirectory(test)

Pod tym linkiem znajduje się tutorial objaśniający dokładnie wprowadzone komendy w celu zbudowania projektu.

Na samym początku określona zostaje minimalna wersja CMake, następnie ustawione zostaje nazwa projektu, języki, flagi do kompilacji, uruchomienie procedury testowania, dodanie lokalizacji bibliotek Google test. Kolejnym elementem jest dodanie plików które zawierają testowane funkcje. Niżej dodane są lokalizacje do projektu oraz dołączenie folderu z funkcjami testowymi.

Dodanie folderów Inc oraz Src pozwala na dołączenie do projektu wykonującego testy zarówno pliki *.h jak i *.c. Taka operacja pozwoli na przeprowadzanie testów funkcji lokalnych, jeśli z jakichś powodu chcemy je testować. 

Projekt kompiluje za pomocą GNU 6.3.0. 

Struktura projektu dołączonego do projektu wygenerowanego przez CubeMx z obsługą w STM32Cube IDE wygląda następująco:


Kolejnym plikiem CMakeLists.txt jest plik zawarty w folderze przechowującym funkcje testowe (folder test).

  1. cmake_minimum_required(VERSION 3.10)
  2.  
  3. set(This ExampleTests)
  4.  
  5. set(Sources
  6.     test1.cpp
  7.     test2.cpp
  8.     test3.cpp
  9.     test4.cpp
  10. )
  11.  
  12. add_executable(${This} ${Sources})
  13. target_link_libraries(${This} PUBLIC
  14.     gtest_main
  15.     Example //Nazwa projektu
  16. )
  17.  
  18. add_test(
  19.     NAME ${This}
  20.     COMMAND ${This}
  21. )

Powyżej dodawane są pliki z testami do podanego projektu.

Przykładowa funkcja testowa:

  1. extern "C" {
  2.     #include "../Inc/test_function/math_function.h"
  3.     #include "../Inc/test_function/math_function.c"
  4. }
  5.  
  6. #include <gtest/gtest.h>
  7.  
  8. TEST(mathFunctionTest, CheckAddFunction_CorrectValue)
  9. {
  10.      uint16_t mathFunction = AddFunct(10, 80);
  11.      ASSERT_EQ(90, mathFunction );
  12. }

W pliku dodajemy pliki zawierające funkcje które chcemy przetestować, biblioteki do testów oraz wszystkie funkcje testowe jakie będą potrzebne. 

Warto pamiętać aby testy przechodziły sprawnie to w plikach dla projektu stm32 należy maksymalnie oddzielić funkcję obsługujące hardware (wysyłanie komunikatów, sterowanie pinami itp itd) od funkcji wykonujących pozostałe operacje (obliczenia, przygotowanie ramki danych itp. itd). Dzięki temu nie będzie konieczności kombinowania w celu dodania funkcji zastępujących deklarację sprzętowe.

Aby odłączyć nie które funkcje możemy dodać ich deklarację z podstawową funkcjonalnością pomijającą sprzęt lub wyłączyć je za pomocą np. dyrektywy define.

  1. #ifndef GOOGLE_TEST_ENABLE
  2. #include "rtc/rtc_config.h"
  3. #else
  4. #include "rtc/rtc_data.h"
  5. static RTC_Resoult_t RTC_GetDateTime(RTC_time_t* data, RTC_Format_t format) { return RTC_Result_Ok; }
  6. static RTC_Resoult_t RTC_SetDateTime(RTC_time_t* data, RTC_Format_t format) { return RTC_Result_Ok; }
  7. #endif

Powyżej następuje zastąpienie funkcji ustawiających i odczytujących czas z bibliteki RTC gdy została ustawiona instrukcja GOOGLE_TEST_ENABLE.

Po wykonaniu testów informacje zostaną wyświetlone w oknie OUTPUT lub w konsoli uruchamiając plik *.exe zlokalizowany w folderze build->test.