From 37fecd2df12c9b7810bb70e76c1557c4480c8d82 Mon Sep 17 00:00:00 2001 From: Minaya Serrano Date: Mon, 21 Oct 2024 09:39:34 +0200 Subject: [PATCH 1/2] Googletest enviroment testing --- platformio.ini | 10 ++++- src/main.cpp | 5 +++ test/RoboCaddie/RoboCaddieTests.h | 11 +++++ test/test_custom_runner.py | 41 +++++++++++++++++++ test/test_runner_embedded/Test_Embedded.cpp | 9 +++- .../test_custom_runner.py | 10 ----- test/test_runner_native/Test_Native.cpp | 12 +++++- test/wait_for_restart.py | 7 ++++ 8 files changed, 89 insertions(+), 16 deletions(-) create mode 100644 src/main.cpp create mode 100644 test/test_custom_runner.py delete mode 100644 test/test_runner_embedded/test_custom_runner.py create mode 100644 test/wait_for_restart.py diff --git a/platformio.ini b/platformio.ini index 19c36e4..159548b 100644 --- a/platformio.ini +++ b/platformio.ini @@ -10,6 +10,7 @@ [env:native] platform = native +test_framework = googletest test_ignore = test_runner_embedded [env:nano33ble] @@ -18,12 +19,17 @@ board = nano33ble framework = arduino ; Use arduino framework Unity version instead of Platformio default version ; https://docs.platformio.org/en/stable/advanced/unit-testing/frameworks/custom/examples/custom_unity_library.html -test_framework = custom +build_flags = -DGTEST_OS_NRF52 +test_framework = googletest test_ignore = test_runner_native +extra_scripts = test/wait_for_restart.py [env:nano33ble-renode] extends = env:nano33ble -build_flags = -DRENODE_ENVIRONMENT +build_flags = -DGTEST_OS_NRF52 -DRENODE_ENVIRONMENT +; Modify GoogletestTestCaseParser to allow Renode log format +; https://github.com/platformio/platformio-core/blob/master/platformio/test/runners/googletest.py +test_framework = custom platform_packages = platformio/tool-renode test_testing_command = diff --git a/src/main.cpp b/src/main.cpp new file mode 100644 index 0000000..66b2461 --- /dev/null +++ b/src/main.cpp @@ -0,0 +1,5 @@ +#include + +void setup() { delay(1000); } + +void loop() { delay(1000); } diff --git a/test/RoboCaddie/RoboCaddieTests.h b/test/RoboCaddie/RoboCaddieTests.h index 9028fe9..e95e2fa 100644 --- a/test/RoboCaddie/RoboCaddieTests.h +++ b/test/RoboCaddie/RoboCaddieTests.h @@ -1,5 +1,15 @@ #ifdef UNIT_TEST +TEST(DummyTest, ShouldPass) { EXPECT_EQ(1, 1); } + +TEST(DummyFailedTest, ShouldNotPass) { EXPECT_EQ(1, 0); } + +TEST(SkipTest, DoesSkip) { + GTEST_SKIP() << "Skipping single test"; + EXPECT_EQ(0, 1); // Won't fail; it won't be executed +} + +/* void test_robocaddie_is_stopped_on_startup(); void test_a_STOP_message_is_sent_to_the_motor_when_robocaddie_status_is_STOP(); void test_robocaddie_sends_a_transmission_every_30_ms(); @@ -114,5 +124,6 @@ void test_uart_baud_rate_should_be_115200() { TEST_ASSERT_EQUAL_UINT64(115200, uart.getBaudRate()); } +*/ #endif diff --git a/test/test_custom_runner.py b/test/test_custom_runner.py new file mode 100644 index 0000000..7cadc16 --- /dev/null +++ b/test/test_custom_runner.py @@ -0,0 +1,41 @@ +# Modify GoogletestTestCaseParser to allow Renode log format +# https://github.com/platformio/platformio-core/blob/master/platformio/test/runners/googletest.py + +import os +import re + +from platformio.public import GoogletestTestRunner +from platformio.test.runners.googletest import GoogletestTestCaseParser + + +class CustomGoogletestTestCaseParser(GoogletestTestCaseParser): + # Examples: + # 12:02:09.8136 [INFO] uart0: [host: 2.12s (+11.59ms)|virt: 1.03s (+0.21ms)] [ RUN ] FooTest.Bar + # ... + # 12:02:09.8136 [INFO] uart0: [host: 2.12s (+11.59ms)|virt: 1.03s (+0.21ms)] [ FAILED ] FooTest.Bar (0 ms) + STATUS__NAME_RE = r".*\[\s+(?P[A-Z]+)\s+\]\s+(?P[^\(\s]+)" + + # Examples: + # 12:02:09.8136 [INFO] uart0: [host: 2.12s (+11.59ms)|virt: 1.03s (+0.21ms)] [ RUN ] FooTest.Bar + # 12:02:09.8136 [INFO] uart0: [host: 2.12s (+11.59ms)|virt: 1.03s (+0.21ms)] test/test_gtest/test_main.cpp:26: Failure + # 12:02:09.8136 [INFO] uart0: [host: 2.12s (+11.59ms)|virt: 1.03s (+0.21ms)] Y:\core\examples\unit-testing\googletest\test\test_gtest\test_main.cpp:26: Failure + SOURCE_MESSAGE_RE = r".*(?P.+):(?P\d+):(?P.*)$" + + def _parse_status_and_name(self, line): + result = (None, None) + line = line.strip() + # if not line.startswith("["): + # return result + match = re.search(self.STATUS__NAME_RE, line) + if not match: + return result + return match.group("status"), match.group("name") + + +class CustomTestRunner(GoogletestTestRunner): + EXTRA_LIB_DEPS = ["google/googletest@^1.15.2"] + + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + self._tc_parser = CustomGoogletestTestCaseParser() + os.environ["GTEST_COLOR"] = "no" # disable ANSI symbols diff --git a/test/test_runner_embedded/Test_Embedded.cpp b/test/test_runner_embedded/Test_Embedded.cpp index 856e351..71dea15 100644 --- a/test/test_runner_embedded/Test_Embedded.cpp +++ b/test/test_runner_embedded/Test_Embedded.cpp @@ -2,7 +2,7 @@ #include #include -#include +#include #include "RoboCaddie/RoboCaddieTests.h" @@ -15,7 +15,12 @@ REDIRECT_STDOUT_TO(Serial); void setup() { delay(2000); - run_tests(); + Serial.begin(115200); + + ::testing::InitGoogleTest(); + + if (RUN_ALL_TESTS()) { + }; } void loop() { delay(1000); } diff --git a/test/test_runner_embedded/test_custom_runner.py b/test/test_runner_embedded/test_custom_runner.py deleted file mode 100644 index f684014..0000000 --- a/test/test_runner_embedded/test_custom_runner.py +++ /dev/null @@ -1,10 +0,0 @@ -from platformio.public import UnityTestRunner - -class CustomTestRunner(UnityTestRunner): - - # Ignore "throwtheswitch/Unity" package - EXTRA_LIB_DEPS = None - - # Do not add default Unity to the build process - def configure_build_env(self, env): - pass \ No newline at end of file diff --git a/test/test_runner_native/Test_Native.cpp b/test/test_runner_native/Test_Native.cpp index 17ac6ef..1c0ea0c 100644 --- a/test/test_runner_native/Test_Native.cpp +++ b/test/test_runner_native/Test_Native.cpp @@ -1,10 +1,18 @@ #ifdef UNIT_TEST #include -#include +#include #include "RoboCaddie/RoboCaddieTests.h" -int main() { return run_tests(); } +int main(int argc, char **argv) { + ::testing::InitGoogleTest(&argc, argv); + + if (RUN_ALL_TESTS()) { + }; + + // Always return zero-code and allow PlatformIO to parse results + return 0; +} #endif diff --git a/test/wait_for_restart.py b/test/wait_for_restart.py new file mode 100644 index 0000000..de66f08 --- /dev/null +++ b/test/wait_for_restart.py @@ -0,0 +1,7 @@ +import time + +def waiting_for_restart_before_embedding_tests(source, target, env): + time.sleep(2) + +Import("env") +env.AddPostAction("upload", waiting_for_restart_before_embedding_tests) \ No newline at end of file From ab81fd9a339d3c31b367e1f0861ff845447fc9f2 Mon Sep 17 00:00:00 2001 From: Minaya Serrano Date: Mon, 21 Oct 2024 14:41:39 +0200 Subject: [PATCH 2/2] Googletest migration --- lib/RoboCaddie/src/RoboCaddie.cpp | 2 + test/RoboCaddie/RoboCaddieTests.h | 58 ++++++--------------- test/test_runner_embedded/Test_Embedded.cpp | 1 + test/test_runner_native/Test_Native.cpp | 1 + 4 files changed, 20 insertions(+), 42 deletions(-) diff --git a/lib/RoboCaddie/src/RoboCaddie.cpp b/lib/RoboCaddie/src/RoboCaddie.cpp index c2e4616..e5993a8 100644 --- a/lib/RoboCaddie/src/RoboCaddie.cpp +++ b/lib/RoboCaddie/src/RoboCaddie.cpp @@ -2,6 +2,8 @@ using namespace RoboCaddieUART; +const int RoboCaddie::STOP; + RoboCaddie::RoboCaddie(UART &uart, TimeService &time) : uart(uart), time(time) {} diff --git a/test/RoboCaddie/RoboCaddieTests.h b/test/RoboCaddie/RoboCaddieTests.h index e95e2fa..b8c389b 100644 --- a/test/RoboCaddie/RoboCaddieTests.h +++ b/test/RoboCaddie/RoboCaddieTests.h @@ -1,41 +1,14 @@ #ifdef UNIT_TEST -TEST(DummyTest, ShouldPass) { EXPECT_EQ(1, 1); } - -TEST(DummyFailedTest, ShouldNotPass) { EXPECT_EQ(1, 0); } - -TEST(SkipTest, DoesSkip) { - GTEST_SKIP() << "Skipping single test"; - EXPECT_EQ(0, 1); // Won't fail; it won't be executed -} - -/* -void test_robocaddie_is_stopped_on_startup(); -void test_a_STOP_message_is_sent_to_the_motor_when_robocaddie_status_is_STOP(); -void test_robocaddie_sends_a_transmission_every_30_ms(); -void test_uart_baud_rate_should_be_115200(); - -int run_tests() { - UNITY_BEGIN(); - - RUN_TEST(test_robocaddie_is_stopped_on_startup); - RUN_TEST( - test_a_STOP_message_is_sent_to_the_motor_when_robocaddie_status_is_STOP); - RUN_TEST(test_robocaddie_sends_a_transmission_every_30_ms); - RUN_TEST(test_uart_baud_rate_should_be_115200); - - return UNITY_END(); -} - -void test_robocaddie_is_stopped_on_startup() { +TEST(RoboCaddieTest, RoboCaddieIsStoppedOnStartup) { SpyUART uart; FakeTimeService time; RoboCaddie robocaddie(uart, time); - TEST_ASSERT_EQUAL(RoboCaddie::STOP, robocaddie.getStatus()); + EXPECT_EQ(RoboCaddie::STOP, robocaddie.getStatus()); } -void test_a_STOP_message_is_sent_to_the_motor_when_robocaddie_status_is_STOP() { +TEST(RoboCaddieTest, AStopMessageIsSentToTheMotorWhenRoboCaddieStatusIsSTOP) { const uint8_t PROTOCOL_MSG2_SOM = 0x04; // PROTOCOL_SOM_NOACK const uint8_t PROTOCOL_MSG2_CI = 0x01; // Continuity Counter const uint8_t PROTOCOL_MSG2_LEN = 0x0A; // Len of bytes to follow, @@ -71,15 +44,17 @@ void test_a_STOP_message_is_sent_to_the_motor_when_robocaddie_status_is_STOP() { RoboCaddie robocaddie(uart, time); // Precondition: no message sent yet on initialization - TEST_ASSERT_NULL(uart.getLastSentMessage().data()); + EXPECT_EQ(uart.getLastSentMessage().data(), nullptr); robocaddie.transmission(); - TEST_ASSERT_EQUAL_UINT8_ARRAY( - stop_msg.data(), uart.getLastSentMessage().data(), stop_msg.size()); + const auto &lastMessage = uart.getLastSentMessage(); + EXPECT_THAT(std::vector(lastMessage.data(), + lastMessage.data() + lastMessage.size()), + testing::ElementsAreArray(stop_msg)); } -void test_robocaddie_sends_a_transmission_every_30_ms() { +TEST(RoboCaddieTest, RoboCaddieSendsATransmissionEvery30Ms) { SpyUART uart; FakeTimeService time; RoboCaddie robocaddie(uart, time); @@ -89,41 +64,40 @@ void test_robocaddie_sends_a_transmission_every_30_ms() { robocaddie.run(); - TEST_ASSERT_EQUAL_UINT64(0, uart.getNumbersOfExecutions()); + EXPECT_EQ(0, uart.getNumbersOfExecutions()); time.setCurrentTime(30); time.setStartTime(0); robocaddie.run(); - TEST_ASSERT_EQUAL_UINT64(1, uart.getNumbersOfExecutions()); + EXPECT_EQ(1, uart.getNumbersOfExecutions()); time.setCurrentTime(45); time.setStartTime(31); robocaddie.run(); - TEST_ASSERT_EQUAL_UINT64(1, uart.getNumbersOfExecutions()); + EXPECT_EQ(1, uart.getNumbersOfExecutions()); time.setCurrentTime(62); time.setStartTime(31); robocaddie.run(); - TEST_ASSERT_EQUAL_UINT64(2, uart.getNumbersOfExecutions()); + EXPECT_EQ(2, uart.getNumbersOfExecutions()); } -void test_uart_baud_rate_should_be_115200() { +TEST(RoboCaddieTest, UARTBaudRateShouldBe115200) { SpyUART uart; FakeTimeService time; RoboCaddie robocaddie(uart, time); - TEST_ASSERT_EQUAL_UINT64(0, uart.getBaudRate()); + EXPECT_EQ(0, uart.getBaudRate()); robocaddie.init(); - TEST_ASSERT_EQUAL_UINT64(115200, uart.getBaudRate()); + EXPECT_EQ(115200, uart.getBaudRate()); } -*/ #endif diff --git a/test/test_runner_embedded/Test_Embedded.cpp b/test/test_runner_embedded/Test_Embedded.cpp index 71dea15..8230daf 100644 --- a/test/test_runner_embedded/Test_Embedded.cpp +++ b/test/test_runner_embedded/Test_Embedded.cpp @@ -2,6 +2,7 @@ #include #include +#include #include #include "RoboCaddie/RoboCaddieTests.h" diff --git a/test/test_runner_native/Test_Native.cpp b/test/test_runner_native/Test_Native.cpp index 1c0ea0c..26a19dc 100644 --- a/test/test_runner_native/Test_Native.cpp +++ b/test/test_runner_native/Test_Native.cpp @@ -1,6 +1,7 @@ #ifdef UNIT_TEST #include +#include #include #include "RoboCaddie/RoboCaddieTests.h"