I\'d like to be able to unit test my Arduino code. Ideally, I would be able to run any tests without having to upload the code to the Arduino. What tools or libraries can he
I have considerable success unit testing my PIC code by abstracting out the hardware access and mocking it in my tests.
For example, I abstract PORTA with
#define SetPortA(v) {PORTA = v;}
Then SetPortA can easily be mocked, without adding overhead code in the PIC version.
Once the hardware abstraction has been tested a while I soon find that generally code goes from the test rig to the PIC and works first time.
Update:
I use a #include seam for the unit code, #including the unit code in a C++ file for the test rig, and a C file for the target code.
As an example I want to multiplex four 7 segment displays, one port driving the segments and a second selecting the display. The display code interfaces with the displays via SetSegmentData(char)
and SetDisplay(char)
. I can mock these in my C++ test rig and check that I get the data I expect. For the target I use #define
so that I get a direct assignment without the overhead of a function call
#define SetSegmentData(x) {PORTA = x;}
There is a project called ncore, which provides native core for Arduino. And allows you to write tests for Arduino code.
From the project description
The native core allows you to compile and run Arduino sketches on the PC, generally with no modification. It provides native versions of standard Arduino functions, and a command-line interepreter to give inputs to your sketch that would normally come from the hardware itself.
Also on the "what do I need to use it" section
If you want to build the tests, you'll need cxxtest from http://cxxtest.tigris.org. NCORE has been tested with cxxtest 3.10.1.
Use Proteus VSM with an Arduino library to debug your code or to test it.
It is a best practice before getting your code onboard, but be sure with timings because the simulation does not run realtime as they run on the board.
Try Autodesk circuit simulator. It allows to test Arduino code and circuits with many other hardware components.
I built arduino_ci for this purpose. Although it's limited to testing Arduino libraries (and not standalone sketches), it enables unit tests to be run either locally or on a CI system (like Travis CI or Appveyor).
Consider a very simple library in your Arduino Library directory, called DoSomething
, with do-something.cpp
:
#include <Arduino.h>
#include "do-something.h"
int doSomething(void) {
return 4;
};
You'd unit test it as follows (with a test file called test/is_four.cpp
or some such):
#include <ArduinoUnitTests.h>
#include "../do-something.h"
unittest(library_does_something)
{
assertEqual(4, doSomething());
}
unittest_main() // this is a macro for main(). just go with it.
That's all. If that assertEqual
syntax and test structure looks familiar, it's because I adopted some of Matthew Murdoch's ArduinoUnit library
that he referred to in his answer.
See Reference.md for more information about unit testing I/O pins, the clock, Serial ports, etc.
These unit tests are compiled and run using a script contained in a ruby gem. For examples of how to set that up, see the README.md or just copy from one of these examples:
In case you are interested in running an INO sketch and checkout the serial output, I have a working implementation of that in my Arduino NMEA checksum project.
The following script takes the file and uses Arduino CLI to compile it to a HEX file which is then loaded to SimAVR which evaluates it and prints the serial output. Since all Arduino programs run forever without really having an option of killing themselves (exit(0)
doesn't work), I let the sketch run for a few seconds and then diff the captured output with expected output.
Download and extract Arduino CLI (in this case version 0.5.0 - latest at the time of writing):
curl -L https://github.com/arduino/arduino-cli/releases/download/0.5.0/arduino-cli_0.5.0_Linux_64bit.tar.gz -o arduino-cli.tar.gz
tar -xvzf arduino-cli.tar.gz
Now you can update the index and install the appropriate core:
./arduino-cli core update-index
./arduino-cli core install arduino:avr
Assuming your sketch is named nmea-checksum.ino
, to get ELF and HEX, run:
./arduino-cli compile -b arduino:avr:uno nmea-checksum.ino
Next up, SimAVR to run the HEX (or ELF) - I build from source because the latest release didn't work for me:
sudo apt-get update
sudo apt-get install -y build-essential libelf-dev avr-libc gcc-avr freeglut3-dev libncurses5-dev pkg-config
git clone https://github.com/buserror/simavr.git
cd simavr
make
Successful compilation will give you simavr/run_avr
which you can use to run the sketch. Like I said, timeout
it otherwise it will never terminate:
cd simavr
timeout 10 ./run_avr -m atmega168 -f 16000000 ../../nmea-checksum.ino.arduino.avr.uno.elf &> nmea-checksum.ino.clog || true
The generated file will have ANSI color code control characters wrapping the serial output, to get rid of those:
cat nmea-checksum.ino.clog | sed -r "s/\x1B\[([0-9]{1,2}(;[0-9]{1,2})?)?[mGK]//g" > nmea-checksum.ino.log
cat nmea-checksum.ino.log
Now all you need to do is compared this file to a known good file:
diff nmea-checksum.ino.log ../../nmea-checksum.ino.test
If there are no differences, diff
will exit with code 0, otherwise the script will fail.