Unit Testing - multiple definition of `loop()'; error

I have my code fully working and have decided, mid project (I know bad decision), to start implementing unit testing. I have gone through the tutorials and have had no issues getting it all working. But with my current code I am having issues getting it working. When trying to run my unit tests I keep getting the errors of "multiple definitions of loop(); and setup(). That being said my code works perfectly and I have no compile or build errors with it.

When I am doing the tutorials or starting a new project, where I have a setup/loop function in both the main src dir and the test dir, I have no issues. But in this project, I keep getting this error.

Here is the test_main.cpp file:

#ifdef UNIT_TEST

#include "Arduino.h"
#include "network.h"
#include "unity.h"

void test_getCredentialLength() {

  TEST_ASSERT_GREATER_OR_EQUAL(1, 5);

}

void setup() {}

void loop() {

  UNITY_BEGIN();  // IMPORTANT LINE!
  RUN_TEST(test_getCredentialLength);
  UNITY_END();
}
#endif

Here is the main.cpp file. I have removed basically everything from the main.cpp file to try to fix this issue but it still kept occuring:

#ifndef UNIT_TEST

#include <Arduino.h>

void setup() {}

void loop() {}

#endif

My platform.ini file:

[env:esp32dev]
platform = espressif32
board = esp32dev
framework = arduino, espidf
monitor_speed = 115200
platform_packages =
    framework-arduinoespressif32 @ https://github.com/espressif/arduino-esp32.git#idf-release/v4.0
board_build.partitions = partitions.csv
lib_deps =
    bblanchon/ArduinoJson @ ^6.16.1
    256dpi/MQTT @ ^2.4.7
    lvgl/lvgl@^7.1.0
    adafruit/Adafruit NeoPixel@^1.6.1
build_flags =
    -DARDUINO=100
    -DESP32=1
    -D LV_CONF_INCLUDE_SIMPLE
    ; -I include Required to find lv_conf.h
    -I include
test_build_project_src = true

You are telling PlatformIO to compile the src/ folder when testing. As the GCC error message tells you, your src/main.cpp and test/test_main.cpp both want to define the functions setup() and loop(), so that won’t work – only one can implement this.

Review if you really need the source folder to be built, and remove it if not necessary. If you do need src to be built, surround the implementations of setup() and loop() with #ifndef UNIT_TEST in src/main.cpp, just like the documentation says.

1 Like

All the code I have written is in src, so I would like that tested. I have put the #ifndef UNIT_TEST statement in and it is working a bit better now. The same issue is still coming up now I have put the #ifndef and #endif around the src main and setup functions. So not sure what the issue is now.

I can’t be sure what the issue is either when I don’t see the full code and error message :smiley:.

I have a similar issue, using test_build_project_src = yes with ESP-IDF. I wrapped the app_main() in my src/main.c with #ifndef UNIT_TEST. However, the build still failed due to multiple definitions of app_main.

It seems like the UNIT_TEST build flag isn’t actually being supplied at build-time for some reason. I was able to work around it with a custom pre-script that looks something like this:


from SCons.Script import COMMAND_LINE_TARGETS

Import("env")

def add_build_flags():
    if "__test" in COMMAND_LINE_TARGETS:
        env.Append(CCFLAGS=["-DUNIT_TEST=1"])

add_build_flags()

With this in place, the #ifndef UNIT_TEST actually works.

UNIT_TEST will be automatically defined by the PlatformIO core logic.

Do you have a minimal example that reproduces the problem?

Yup, I see that, but it doesn’t seem to be happening in this case. My project is pretty large, I’m guessing @luke.m.coffey is closer to having a minimally-reproducible example.