Products > Programming

Unit testing C embedded code - systems and frameworks

(1/6) > >>

ricko_uk:
Hi,
when I needed to do unit testing in C for embedded systems I did either one of the following:
- did it in simulator
- used the hardware and either have a breakpoint at the end of the unit testing code and see the results or output the results to the PC

A couple of questions:

1) How do you do it, especially when the hardware does play a role so it or something emulating its actions is involved? I am just wondering if there are either other preferred systems and/or frameworks that make it easier and/or faster?

2) same question as above but in the case of running an RTOS?

Thank you :)

SiliconWizard:

--- Quote from: ricko_uk on November 13, 2021, 11:20:59 pm ---Hi,
when I needed to do unit testing in C for embedded systems I did either one of the following:
- did it in simulator
- used the hardware and either have a breakpoint at the end of the unit testing code and see the results or output the results to the PC

A couple of questions:

1) How do you do it, especially when the hardware does play a role so it or something emulating its actions is involved? I am just wondering if there are either other preferred systems and/or frameworks that make it easier and/or faster?

--- End quote ---

If you absolutely need accurate hardware behavior, doing it on target can be your better option. You don't necessarily use a debugger - which may make automating tests difficult - there are other ways, usually by "instrumenting" code. Downside is you need to be careful about your instrumentation (additional code) having minimal effect on the result.

You may have simulators for specific devices, but that's not necessarily available. IIRC, there was a simulator for some PIC MCUs provided by Microchip that we used for this.

But I've most often done unit testing for embedded devices purely on a software level, "mocking" device-dependant parts, such as peripherals, when required. It will test the code, but (usually) not timings. I personally think this is appropriate as far as unit testing is concerned. You use other forms of testing for anything timing-related, and more generally hardware-related.


--- Quote from: ricko_uk on November 13, 2021, 11:20:59 pm ---2) same question as above but in the case of running an RTOS?

--- End quote ---

Same usually.
But keep in mind, as I said, that I use unit testing mostly for testing *software* behavior, not hardware behavior, and think that's where it's most appropriate.
As soon as there is some hardware interaction, then it looks more like forms of "integration testing" than unit testing anyway. At least that's my take on this.

Actually, for some higher-level functions in code - for instance things that implement a bit complex algorithms - testing them separately on a different target, typically a computer, can be useful and much easier too, especially when you need to test a lot of possible inputs/configurations/etc. Sure in this case you're not testing the code on the end target, and you need to be careful about any limitation and most of all any non-portable part of your code that may behave differently on a different target, but if your code is portable - which can often be the case for the higher-level parts of the code - this is a workable approach that works quite well.

ricko_uk:
Thank you all! :)

SiliconWizard:
No probs. That can be an interesting discussion in the "embedded development" context, because, as I pointed out, I don't think you can strictly consider doing "unit testing" as soon as you have several parts interacting. The whole point of unit testing is the opposite of that: testing blocks of code (the granularity remaining up to you...) independently. Which is why "mocking" anything the particular block you're testing may be accessing outside of it, is a common practice.

You're not really doing unit testing if the piece of code involved in a particular test needs to interact with hardware, IMHO. But that's a typically controversial topic, and YMMV. Can be a tricky one too, to determine what parts of hardware you consider not part of the "unit" you're testing, and what parts would be.

But what I've commonly witnessed is that management will just tell you to do unit testing, because that's good practice, after which you're on your own.

Jeroen3:
The most difficult part about unit testing your C code is that your C code need to be unit-testable.

It's quite easy to get loads of dependencies you need in your code that make testing very hard. Especially if you have to mock all those dependencies by dummy functions and defines.
An abstraction layer you can help you. For example it's quite trivial to write a module using ST's I2C HAL functions and then emulator being an EEPROM by some very simple array indexing in your mock functions. So you can test and develop your wear leveling and checksum algorithms for various data corruption and memory failure situations. Without actually using an chip, eeprom and logic analyzer.

The second most difficult thing is actually compiling and running your unit tests with frameworks on windows. I found the easiest way to go about it to install Visual Studio Community and to create a Google Test Project. It will present you with an empty (C++) project you can include your code in. Click compile, and you can debug your unit test programs.
Two drawbacks on this: 1. you have to repeatedly disable "precompiled headers" for some reason. 2: your c code need some #ifdef cpluspus extern "c"....

I think this is the most portable and beginner friendly way. Since you can use visual studio which fixes all the dependencies and compilation for you.
And actually compiling your code in a different compiler (not gcc) is beneficial to test your code portability as well. May even throw you some new warnings.

Navigation

[0] Message Index

[#] Next page

There was an error while thanking
Thanking...
Go to full version
Powered by SMFPacks Advanced Attachments Uploader Mod