Go Down

Topic: Unittest framework for Arduino projects (currently with Platform.io) (Read 920 times) previous topic - next topic

susundberg

Hey!

I made this small framework to unittest (=software only test on pc) my own projects, as i did not found proper one with google. It currently works with platform.io projects only - as thats my choice of how to program arduino - but it should be easy to use also with Arduino IDE.

Source code and examples here


susundberg

Hi again, i am writing this as i have pushed an update to the framework (mostly documentation) but also some additional features.

I must say i was bit suprised that no-one even commented about this, as i think this is quite cool compared to other testing possibilities that i found. Did i miss some obvious solution for unittesting the arduino code on PC or is it just me who thinks that it (unittesting arduino code on pc) makes life easier?

Or is the problem that it works only with platform.io and most of the people here are using the arduino ide?

I am asking these questions since i truly think that this framework of mines would be beneficial for most of the arduino-developers with projects more complicated than blinking a led.


Robin2

I did not notice this before now.

For me the fact that it is not based on the Arduino IDE is a deal-breaker.

How does it deal with real-world I/O - for example input from an optical or ultrasonic detector? Or communication using SPI with (say) an nRf24L01+ wireless transceiver?

...R
Two or three hours spent thinking and reading documentation solves most programming problems.

susundberg

Hi,

The arduino ide is - like said - currently not supported, but dropping the basic support for it would be easy. The more problem is (as far as i know) that ppl using arduino ide usually tend to stuff everything inside single source file, that is no go for the mocking approach i selected.

I actually have on my desk a project with ultrasonic range finder, and the story goes like this: I have 'distance.h' file that defines a class "Distance{ .... get_distance() }" and then on my main application i have

Code: [Select]


void setup()
{
  SENSOR_DIST  = Distance( PIN_TRIGGER, PIN_ECHO );
}
  ...
void logic()
{
  int distance_mm = SENSOR_DIST.get_distance();
  if ( distance_mm< THRESHOLD )
  { 
    digitalWrite( PIN_SHORT_DISTANCE, 1 );
    // and do some more complex stuff that you really want to test, like the pwm speed is
    // smooth and nice
  }
  else
  {
    digitalWrite( PIN_SHORT_DISTANCE, 0 );
  }
 
}


Now, i want to have testcases for both cases, when distance is smaller or larger (testcase that say checks that certain pin is raised or lowered). i have test_main.cpp faking the get_distance() return values (as i want them):

Code: [Select]

   // testcase for short distance,
   Distance__get_distance_fake.return_val = 1
   REQUIRE( ARDUINO_TEST.pin_value[ PIN_SHORT_DISTANCE ] == 1 )
   // and here the real tests for the complex stuff


The example is silly, but i hope one gets the idea;

do not emulate the device - use a 'fake' or 'mock' implementation on the device interface, so that you can test your own code with different behaviour of the sensor/other module.

Cheers,
Pauli

Robin2

Thank you for a clear exposition.

I can see how the FAKE values can be used to verify some aspects of the program.

But I reckon there are two weaknesses when the concept is applied to external hardware. First it assumes that the user is conscious of all the idiosyncrasies of the hardware he is faking and has the full range of fake values. And secondly it assumes that there is no unexpected interference between items of external hardware.

I am certainly not opposed to test-driven development. But I am concerned that the user needs to understand how much or how little his tests have proved.

...R
Two or three hours spent thinking and reading documentation solves most programming problems.

susundberg

You are absolutely correct on the issue - you cannot test the functionality of real device with this framework.

But, the idea is that you can test that the code works as you think it should. I tried to think good examples where i have found the unittesting to be good:

* I had project where stepper-motor was driving with certain polynomial ramp - with unittesting i could get the ramp figures out to a file and check that it works in different cases (de-acceleration, speed change, speed from zero)

* I had project where have a timer, that needs (or lets say good implementation is) projected from overflowing, with microsencond resolution. Testing the different cases (timer set - alarm will overflow, timer overflow, alarm not etc).

* Serial library that was to be nonblocking serial read, returning a string after user had return pressed, reading numbers (with min/max limits) -- how to validate all inputs.

* Interrupt (opto-sensor-active) / queue (main.cpp says drive) driven state machine - having ability to check when opto-interupts arrive at different stages makes much sense -- having to test that with real hardware is super pain in the ass, due precission timing needed.

* HTTP server project, where the arduino returned JSON for certain gets - to verify that the json looks correct

Sure, you can test all these with "flash it on board and try, add few prints" method, doing it on PC with GDB hooked up and fast compiling its just much more effective, imho.

And hey thanks for you feedback again, i will update the 'why' section at least on the documentation. Talking with somebody on your own ideas always makes them more clear :) Thanks.

Cheers,
Pauli

Go Up