PlatformIO Community

Pio test can't find libraries that pio run can

Hello,
I started playing with the unit testing features of Platformio and ran into the basic problem, that I cant solve easily. So there is my project:

|--lib
|  |--ZgZrak_JSON
|  |  |- ZgZrak_JSON.cpp
|  |  |- ZgZrak_JSON.h
|
|- platformio.ini
|
|--src
|  |- main.cpp
|  |- main.h
|
|--test
|  |--test_desktop
|  |  |- test_json.cpp

I have two einvironments in my platformio.ini, one for the normal build and upload

[env:esp12e_RELEASE]
platform = espressif8266
board = esp12e
framework = arduino

and the other one for the unit test on the PC

[env:native]
platform = native

Now, default project on the esp8266 environment builds smoothly, using pio run command.
But the pio test ran on the native environment reports errors on finding all my libraries, including Arduino.h.
The content of the test_json.cpp is very simple and basic unit test:

#include <Arduino.h>
#include "../../lib/ZGZrak_JSON/ZgZrak_JSON.h"
#include <unity.h>

const char* tokenRequest_string = "hidden";

void test_jsonTokenRequest(void){
    TEST_ASSERT_EQUAL_STRING(tokenRequest_string, jsonTokenRequest(String("test")).c_str());
}

int main(int argc, char **argv){
    UNITY_BEGIN();
    RUN_TEST(test_jsonTokenRequest);
    UNITY_END();
    return 0;
}

The error is the following one:

g++ -o .pio\build\native\test\test_desktop\test_json.o -c -DPLATFORMIO=50101 -DUNIT_TEST -DUNITY_INCLUDE_CONFIG_H -Iinclude -Isrc -I.pio\build\native\UnityTestLib -IC:\users\krivi\.platformio\packages\tool-unity test\test_desktop\test_json.cpp
In file included from test\test_desktop\test_json.cpp:2:0:
test\test_desktop\../../lib/ZGZrak_JSON/ZgZrak_JSON.h:8:21: fatal error: Arduino.h: No such file or directory

Any advice is appreciated.

Cheers,

Pero

You don’t, by default have, Arduino.h in the native desktop environment. What is digitalWrite(LED_BUILTIN, HIGH); supposed to do on a PC? :smiley:

There is however the ArduinoFake library with which one can do unit-testing, in a similated Arduino environment. That example is linked to in the documentation.

Hey, thanks for the explanation, that does seem obvious. However, I didnt mention that neither my own library in lib folder gets recognised. The build returns the same error for ZgZrak_JSON.h

Refer to it as #include <ZgZrak_JSON.h>, not with this path hack.

If it’s still not working, upload the whole project please.

Hey…I tried it, and I also tried including missing libraries into the platformio.ini file under the lib_deps flag. It helped in a way that the build system now compiles some libraries like Arduino.h and original ZgZrak_JSON.h, but now it fails in compiling other dependency libraries like ArduinoJson.h.

Please be my guest and check the project, uploaded in zip form here: wetransfer link

Interestingly, this happens with pio test command. With pio run command, it fails compiling a completely different set of libraries, like ESP8266WiFi.h.

pio test compiles the source files in the test/ folder (by default, changable with test_build_project_src, pio run tries to compile the src/ folder. If the code in there does include like ESP8266WiFi.h, that of course can’t work when compiling for a desktop PC.

As you can see with a CLI and a verbose test run (pio test -e native -v)

PS C:\Users\Max\Desktop\Otvoreni_Zrak> pio test -e native -v
Collected 1 items

Processing test_desktop in native environment
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------Building...
LDF: Library Dependency Finder -> http://bit.ly/configure-pio-ldf
LDF Modes: Finder ~ chain, Compatibility ~ soft
Framework incompatible library C:\Users\Max\Desktop\Otvoreni_Zrak\lib\ZgZrak_EEPROM
Framework incompatible library C:\Users\Max\Desktop\Otvoreni_Zrak\lib\ZgZrak_JSON  
Framework incompatible library C:\Users\Max\Desktop\Otvoreni_Zrak\.pio\libdeps\native\ArduinoJson
More details about "Library Compatibility Mode": https://docs.platformio.org/page/librarymanager/ldf.html#ldf-compat-mode
Found 1 compatible libraries
Scanning dependencies...
Dependency Graph
|-- <ArduinoFake> 0.2.2 (C:\Users\Max\Desktop\Otvoreni_Zrak\.pio\libdeps\native\ArduinoFake)
Building in release mode

your libraries are being rejected because they don’t advertise being compatibe with the native platform via a library.json file.

If you don’t want to write these files, you can bypass this as the link tells you with

lib_compat_mode = off 

In the platformio.ini.

Then the dependency graph looks like

Dependency Graph
|-- <ArduinoFake> 0.2.2 (C:\Users\Max\Desktop\Otvoreni_Zrak\.pio\libdeps\native\ArduinoFake)
|-- <ArduinoJson> 6.17.2 (C:\Users\Max\Desktop\Otvoreni_Zrak\.pio\libdeps\native\ArduinoJson)
|   |-- <ArduinoFake> 0.2.2 (C:\Users\Max\Desktop\Otvoreni_Zrak\.pio\libdeps\native\ArduinoFake)
|-- <ZgZrak_EEPROM> (C:\Users\Max\Desktop\Otvoreni_Zrak\lib\ZgZrak_EEPROM)
|   |-- <ArduinoFake> 0.2.2 (C:\Users\Max\Desktop\Otvoreni_Zrak\.pio\libdeps\native\ArduinoFake)
|-- <ZgZrak_JSON> (C:\Users\Max\Desktop\Otvoreni_Zrak\lib\ZgZrak_JSON)
|   |-- <ArduinoFake> 0.2.2 (C:\Users\Max\Desktop\Otvoreni_Zrak\.pio\libdeps\native\ArduinoFake)
|   |-- <ArduinoJson> 6.17.2 (C:\Users\Max\Desktop\Otvoreni_Zrak\.pio\libdeps\native\ArduinoJson)
|   |   |-- <ArduinoFake> 0.2.2 (C:\Users\Max\Desktop\Otvoreni_Zrak\.pio\libdeps\native\ArduinoFake)

But fails because it can’t find the subsequent headers.

In file included from test\test_desktop\test_json.cpp:2:
lib\ZgZrak_JSON/ZgZrak_JSON.h:11:10: fatal error: PMserial.h: No such file or directory

******************************************************************
* Looking for PMserial.h dependency? Check our library registry!
*
* CLI  > platformio lib search "header:PMserial.h"
* Web  > https://platformio.org/lib/search?query=header:PMserial.h
*
******************************************************************

   11 | #include <PMserial.h>
      |          ^~~~~~~~~~~~
compilation terminated.
gcc -o .pio\build\native\UnityTestLib\unity.o -c -DPLATFORMIO=50200 -DUNIT_TEST -DUNITY_INCLUDE_CONFIG_H -Ilib\ZgZrak_JSON -I.pio\build\native\UnityTestLib -IC:\Users\Max\.platformio\packages\tool-unity C:\Users\Max\.platformio\packages\tool-unity\unity.c
*** [.pio\build\native\test\test_desktop\test_json.o] Error 1
In file included from lib\ZgZrak_EEPROM\ZgZrak_EEPROM.cpp:1:
lib\ZgZrak_EEPROM/ZgZrak_EEPROM.h:9:10: fatal error: EEPROM.h: No such file or directory

The libraries must be written in such a way that the missing Arduino functionality is either emulated by ArduinoFake or not accessed / switched out with something else entirely. You are compiling for the native platform, after all.

Not that you can also run the tests on the embedded target itself, where you have the entire framework available.

Hey thank you for the effort of checking it out. I see the point now.

Sadly, it seems I cant do what I wanted - to unit test my own libraries that don’t depend on specific hardware on the local machine. Apparently the build system always digs down to the basic, non-compatible header files, that are not covered in ArduinoFake, and fails with the build. Example is ESP8266WiFi.h, which I cant write the emulation for.

And most of the 3rd party libraries do not include the unit test capability. For instance, PMserial calls for HardwareSerial, which is apparently not emulated in ArduinoFake. I tried to bypass those calls via #ifndef UNIT_TEST macro, but the rabbit-hole is just too deep, and it basicaly requires me to rewrite the whole library.

It is bad, since I wanted to make these tests on a remote CI server, like CircleCI or Gitlab.

Just for the recors, I tried building a test on a embedded device, and it also fails with a funny error:
pio test -e esp12e_RELEASE:

...
c:/users/krivi/.platformio/packages/toolchain-xtensa/bin/../lib/gcc/xtensa-lx106-elf/4.8.2/../../../../xtensa-lx106-elf/bin/ld.exe: .pio\build\esp12e_RELEASE\libFrameworkArduino.a(core_esp8266_main.cpp.o):(.text._ZL12loop_wrapperv+0x4): undefined reference to `setup'
c:/users/krivi/.platformio/packages/toolchain-xtensa/bin/../lib/gcc/xtensa-lx106-elf/4.8.2/../../../../xtensa-lx106-elf/bin/ld.exe: .pio\build\esp12e_RELEASE\libFrameworkArduino.a(core_esp8266_main.cpp.o):(.text._ZL12loop_wrapperv+0x8): undefined reference to `loop'
c:/users/krivi/.platformio/packages/toolchain-xtensa/bin/../lib/gcc/xtensa-lx106-elf/4.8.2/../../../../xtensa-lx106-elf/bin/ld.exe: .pio\build\esp12e_RELEASE\libFrameworkArduino.a(core_esp8266_main.cpp.o): 
in function `loop_wrapper()':
core_esp8266_main.cpp:(.text._ZL12loop_wrapperv+0x21): undefined reference to `setup'
c:/users/krivi/.platformio/packages/toolchain-xtensa/bin/../lib/gcc/xtensa-lx106-elf/4.8.2/../../../../xtensa-lx106-elf/bin/ld.exe: core_esp8266_main.cpp:(.text._ZL12loop_wrapperv+0x2d): undefined reference to `loop'
collect2.exe: error: ld returned 1 exit status
*** [.pio\build\esp12e_RELEASE\firmware.elf] Error 1

Apparently, it gets confused with setup and loop functions, that make no such issues on pio run command.

Your test file has a main() function, which is correct for the native platform, but for the embedded Arduino platform it still needs setup() and loop(). Try restructure it like

Yeah, I’ve just seen the docs and fixed it…sorry for posting it before checking.

Thanks for the prompt response.