Getting Started with Code Coverage in PlatformIO: A Beginner's Guide to Writing Effective Tests

In the world of software development, it’s essential to ensure that the code being written is not only functional but also maintainable and easily testable. One way to measure the effectiveness of testing is to analyze the code coverage to identify areas of the code that are not adequately tested. In this article, we’ll delve into the concept of source code coverage analysis, its importance, and some tools available for performing the analysis. Read more :point_right:

3 Likes

Hello guys,

I’m trying to get code coverage working on my unit test project. I’m working on a mac M1 using clang and I’m struggling to find out how to compile it.
I added these flags to my platformio.ini test file :

-fprofile-instr-generate
-fcoverage-mapping
-fprofile-arcs
-ftest-coverage

But it sounds like my linker doesn’t really like it because it gives me errors like :

Undefined symbols for architecture x86_64:
  "___llvm_profile_runtime", referenced from:
      ___llvm_profile_runtime_user in unity_config.o
      ___llvm_profile_runtime_user in main.o
      ___llvm_profile_runtime_user in libluos_engine.a(unit_test.o)
      ___llvm_profile_runtime_user in libUnity.a(unity.o)
     (maybe you meant: ___llvm_profile_runtime_user)
  "_llvm_gcda_emit_arcs", referenced from:
      ___llvm_gcov_writeout in unity_config.o
      ___llvm_gcov_writeout in main.o
      ___llvm_gcov_writeout in libluos_engine.a(unit_test.o)
      ___llvm_gcov_writeout in libUnity.a(unity.o)
  "_llvm_gcda_emit_function", referenced from:
      ___llvm_gcov_writeout in unity_config.o
      ___llvm_gcov_writeout in main.o
      ___llvm_gcov_writeout in libluos_engine.a(unit_test.o)
      ___llvm_gcov_writeout in libUnity.a(unity.o)
  "_llvm_gcda_end_file", referenced from:
      ___llvm_gcov_writeout in unity_config.o
      ___llvm_gcov_writeout in main.o
      ___llvm_gcov_writeout in libluos_engine.a(unit_test.o)
      ___llvm_gcov_writeout in libUnity.a(unity.o)
  "_llvm_gcda_start_file", referenced from:
      ___llvm_gcov_writeout in unity_config.o
      ___llvm_gcov_writeout in main.o
      ___llvm_gcov_writeout in libluos_engine.a(unit_test.o)
      ___llvm_gcov_writeout in libUnity.a(unity.o)
  "_llvm_gcda_summary_info", referenced from:
      ___llvm_gcov_writeout in unity_config.o
      ___llvm_gcov_writeout in main.o
      ___llvm_gcov_writeout in libluos_engine.a(unit_test.o)
      ___llvm_gcov_writeout in libUnity.a(unity.o)
  "_llvm_gcov_init", referenced from:
      ___llvm_gcov_init in unity_config.o
      ___llvm_gcov_init in main.o
      ___llvm_gcov_init in libluos_engine.a(unit_test.o)
      ___llvm_gcov_init in libUnity.a(unity.o)
ld: symbol(s) not found for architecture x86_64

Do you guys have any idea to solve this?

Related to Codecoverage running natively on OSX - #4 by softwaregravy ?

2 Likes

Yes it is, thank you.

Thanks for this introduction to code coverage in vs code / platformio!
Much easier than I thought - should have used this for much longer :slight_smile:

Two questions though:

  • Coverage needs some special build flags. At least some are not ideal for “production” code. Can I configure in platformio.ini to use them for tests but not for release?
  • Generating html includes many unneeded files (mostly /usr/include/*). Can I exclude them from the report somehow?

EDIT: in case it matters: for now I use it on linux / native target, not some microcontroller:

[env:native]
platform = native
build_flags = 
    -Og -g
    -lgcov
    --coverage

Check out Setting up PlatformIO for CI/CD with Testing, Code Coverage and Versioning | PlatformIO Labs

It explains how to set up different environments in platformio.ini to deal with different phases in development.

Recently I have found a simple solution to getting a coverage overview report using gcovr. Will try to append that to the blog post.