programing tip

Arduino 코드를 단위 테스트하려면 어떻게해야합니까?

itbloger 2020. 5. 30. 22:13
반응형

Arduino 코드를 단위 테스트하려면 어떻게해야합니까?


Arduino 코드를 단위 테스트 할 수 있기를 원합니다. 이상적으로는 코드를 Arduino에 업로드하지 않고도 테스트를 실행할 수 있습니다. 어떤 도구 나 라이브러리가 도움이 될 수 있습니까?

거기입니다 개발에 아두 이노 에뮬레이터 유용 할 수 있지만, 아직 사용할 준비가 될 것 같지 않습니다.

Atmel의 AVR Studio 에는 유용한 칩 시뮬레이터가 포함되어 있지만 Arduino IDE와 함께 사용하는 방법을 알 수 없습니다.


Arduino 장치 또는 에뮬레이터에서 장치 테스트를 실행하지 마십시오

마이크로 컨트롤러 Device / Emulator / Sim 기반 테스트 사례

단위 테스트 가 무엇을 의미 하는지에 대한 많은 토론이 있으며 실제로 그것에 대해 논쟁하려고하지는 않습니다. 이 게시물에서는 궁극적 인 대상 하드웨어에 대한 모든 실제 테스트 를 피하도록 지시하지 않습니다 . 가장 평범하고 빈번한 테스트에서 대상 하드웨어를 제거하여 개발 피드백주기를 최적화하는 데 중점을두고 있습니다. 테스트중인 단위는 전체 프로젝트보다 훨씬 작은 것으로 가정합니다.

단위 테스트의 목적은 사용자 코드의 품질을 테스트하는 것입니다. 단위 테스트는 일반적으로 통제 범위 밖의 요인의 기능을 테스트해서는 안됩니다.

Arduino 라이브러리, 마이크로 컨트롤러 하드웨어 또는 에뮬레이터의 기능을 테스트하더라도 이러한 테스트 결과가 자신의 작업 품질에 대한 정보를 제공하는 것은 불가능 합니다. 따라서 대상 장치 (또는 에뮬레이터)에서 실행되지 않는 단위 테스트를 작성하는 것이 훨씬 더 가치 있고 효율적입니다.

대상 하드웨어에 대한 빈번한 테스트로 인해주기가 매우 느립니다.

  1. 코드 조정
  2. 컴파일 및 Arduino 장치에 업로드
  3. 행동을 관찰하고 있는지 추측 당신의 코드는 당신이 무엇을 기대하고있다
  4. 반복

직렬 포트를 통해 진단 메시지를받을 것으로 예상되지만 프로젝트 자체가 Arduino의 유일한 하드웨어 직렬 포트를 사용해야하는 경우 3 단계는 특히 불쾌합니다. SoftwareSerial 라이브러리가 도움이 될 것이라고 생각한 경우, 그렇게하면 다른 신호를 동시에 생성하는 것과 같이 정확한 타이밍이 필요한 기능이 중단 될 수 있음을 알아야합니다. 이 문제는 나에게 일어났다.

다시, 에뮬레이터를 사용하여 스케치를 테스트하고 실제 Arduino에 업로드 할 때까지 시간이 중요한 루틴이 완벽하게 실행 된 경우, 배울 유일한 교훈은 에뮬레이터에 결함이 있다는 것입니다. 자신의 작업 품질에 대해서는 아무 것도 나타내지 않습니다 .

장치 또는 에뮬레이터에서 테스트하기가 어리 석다면 어떻게 해야 합니까?

컴퓨터를 사용하여 Arduino 프로젝트에서 작업하고있을 것입니다. 그 컴퓨터는 마이크로 컨트롤러보다 훨씬 빠릅니다. 컴퓨터 에서 빌드하고 실행 하기위한 테스트를 작성하십시오 .

Arduino 라이브러리와 마이크로 컨트롤러의 동작은 정확하거나 적어도 일관되게 부정확 한 것으로 가정 해야합니다 .

테스트 결과가 예상과 달리 출력을 생성하면 테스트 된 코드에 결함이있을 수 있습니다. 테스트 결과가 예상과 일치하지만 Arduino에 업로드 할 때 프로그램이 올바르게 작동하지 않으면 테스트가 잘못된 가정에 기초한 것이며 결함이있는 테스트 일 수 있습니다. 두 경우 모두 다음 코드 변경 내용에 대한 실질적인 통찰력을 얻게됩니다. 피드백의 품질이 " 무슨 문제 "에서 "이 특정 코드 가 깨졌습니다"로 향상되었습니다 .

PC에서 테스트를 빌드하고 실행하는 방법

가장 먼저해야 할 일은 테스트 목표를 파악하는 것 입니다. 테스트하려는 자체 코드 부분을 ​​생각한 다음 테스트를 위해 별도의 부분분리 할 수있는 방식으로 프로그램을 구성하십시오 .

테스트하려는 부품이 Arduino 기능을 호출하는 경우 테스트 프로그램에서 모형 대체품을 제공해야합니다. 이것은 생각보다 훨씬 적은 작업입니다. 실물 모형은 실제로 테스트를 위해 예측 가능한 입력 및 출력을 제공하는 것 외에는 아무것도 할 필요가 없습니다.

테스트하려는 자체 코드는 .pde 스케치 이외의 소스 파일에 존재해야합니다. 걱정하지 마십시오. 스케치 외부에서 소스 코드를 사용해도 스케치가 컴파일됩니다. 실제로 내려 가면 스케치 파일에서 프로그램의 일반적인 진입 점보다 조금만 정의해야합니다.

남아있는 것은 실제 테스트를 작성하고 좋아하는 C ++ 컴파일러를 사용하여 컴파일하는 것입니다! 이것은 실제 사례를 통해 가장 잘 설명 될 수 있습니다.

실제 작업 예

여기에있는 애완 동물 프로젝트 중 하나 는 PC에서 실행되는 간단한 테스트가 있습니다. 이 답변 제출을 위해 Arduino 라이브러리 함수 중 일부를 모의 한 방법과 해당 모의를 테스트하기 위해 작성한 테스트를 살펴 보겠습니다. 이것은 내가 목업을 쓴 사람이기 때문에 다른 사람들의 코드를 테스트하지 않는다는 것에 대해 이전에 말한 것과 반대되는 것은 아닙니다. 나는 목업의 정확성을 확신하고 싶었다.

Arduino 라이브러리에서 제공하는 일부 지원 기능을 복제하는 코드가 포함 된 mock_arduino.cpp의 소스 :

#include <sys/timeb.h>
#include "mock_arduino.h"

timeb t_start;
unsigned long millis() {
  timeb t_now;
  ftime(&t_now);
  return (t_now.time  - t_start.time) * 1000 + (t_now.millitm - t_start.millitm);
}

void delay( unsigned long ms ) {
  unsigned long start = millis();
  while(millis() - start < ms){}
}

void initialize_mock_arduino() {
  ftime(&t_start);
}

내 코드가 이진 데이터를 하드웨어 직렬 장치에 쓸 때 다음 모형을 사용하여 읽을 수있는 출력을 생성합니다.

fake_serial.h

#include <iostream>

class FakeSerial {
public:
  void begin(unsigned long);
  void end();
  size_t write(const unsigned char*, size_t);
};

extern FakeSerial Serial;

fake_serial.cpp

#include <cstring>
#include <iostream>
#include <iomanip>

#include "fake_serial.h"

void FakeSerial::begin(unsigned long speed) {
  return;
}

void FakeSerial::end() {
  return;
}

size_t FakeSerial::write( const unsigned char buf[], size_t size ) {
  using namespace std;
  ios_base::fmtflags oldFlags = cout.flags();
  streamsize oldPrec = cout.precision();
  char oldFill = cout.fill();

  cout << "Serial::write: ";
  cout << internal << setfill('0');

  for( unsigned int i = 0; i < size; i++ ){
    cout << setw(2) << hex << (unsigned int)buf[i] << " ";
  }
  cout << endl;

  cout.flags(oldFlags);
  cout.precision(oldPrec);
  cout.fill(oldFill);

  return size;
}

FakeSerial Serial;

마지막으로 실제 테스트 프로그램 :

#include "mock_arduino.h"

using namespace std;

void millis_test() {
  unsigned long start = millis();
  cout << "millis() test start: " << start << endl;
  while( millis() - start < 10000 ) {
    cout << millis() << endl;
    sleep(1);
  }
  unsigned long end = millis();
  cout << "End of test - duration: " << end - start << "ms" << endl;
}

void delay_test() {
  unsigned long start = millis();
  cout << "delay() test start: " << start << endl;
  while( millis() - start < 10000 ) {
    cout << millis() << endl;
    delay(250);
  }
  unsigned long end = millis();
  cout << "End of test - duration: " << end - start << "ms" << endl;
}

void run_tests() {
  millis_test();
  delay_test();
}

int main(int argc, char **argv){
  initialize_mock_arduino();
  run_tests();
}

This post is long enough, so please refer to my project on GitHub to see some more test cases in action. I keep my works-in-progress in branches other than master, so check those branches for extra tests, too.

I chose to write my own lightweight test routines, but more robust unit-test frameworks like CppUnit are also available.


In the absence of any pre-existing unit test frameworks for Arduino, I have created ArduinoUnit. Here's a simple Arduino sketch demonstrating its use:

#include <ArduinoUnit.h>

// Create test suite
TestSuite suite;

void setup() {
    Serial.begin(9600);    
}

// Create a test called 'addition' in the test suite
test(addition) {
    assertEquals(3, 1 + 2);
}

void loop() {
    // Run test suite, printing results to the serial port
    suite.run();
}

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;}

It seems that emulino would do the job perfectly.

Emulino is an emulator for the Arduino platform by Greg Hewgill. (Source)

GitHub repository


simavr is an AVR simulator using avr-gcc.

It already supports a few ATTiny and ATMega microcontrollers, and - according to the author - it's easy to add some more.

In the examples lies simduino, an Arduino emulator. It supports running the Arduino bootloader and can be programmed with avrdude through Socat (a modified Netcat).


You can unit test in Python with my project, PySimAVR. Arscons is used for building and simavr for simulation.

Example:

from pysimavr.sim import ArduinoSim    
def test_atmega88():
    mcu = 'atmega88'
    snippet = 'Serial.print("hello");'

    output = ArduinoSim(snippet=snippet, mcu=mcu, timespan=0.01).get_serial()
    assert output == 'hello'

Start test:

$ nosetests pysimavr/examples/test_example.py
pysimavr.examples.test_example.test_atmega88 ... ok

I am not aware of any platform which can test Arduino code.

However, there is the Fritzing platform, which you can use to model the hardware and later on export PCB diagrams and stuff.

Worth checking.


We are using Arduino boards for data acquisition in a large scientific experiment. Subsequently, we have to support several Arduino boards with different implementations. I wrote Python utilities to dynamically load Arduino hex images during unit testing. The code found on the link below supports Windows and Mac OS X via a configuration file. To find out where your hex images are placed by the Arduino IDE, hit the shift key before you hit the build (play) button. Hit the shift key while hitting upload to find out where your avrdude (command line upload utility) is located on your system / version of Arduino. Alternatively, you can look at the included configuration files and use your install location (currently on Arduino 0020).

http://github.com/toddstavish/Python-Arduino-Unit-Testing


This program allows automated running of several Arduino unit tests. The testing process is started on the PC but the tests run on the actual Arduino hardware. One set of unit tests is typically used to test one Arduino library. (this

Arduino Forum: http://arduino.cc/forum/index.php?topic=140027.0

GitHub project page: http://jeroendoggen.github.com/Arduino-TestSuite

Page in the Python Package Index: http://pypi.python.org/pypi/arduino_testsuite

The unit tests are written with the "Arduino Unit Testing Library": http://code.google.com/p/arduinounit

The following steps are performed for each set of unit tests:

  • Read the config file to find out which tests to run
  • The script compiles and uploads an Arduino sketch that contains the unit testing code.
  • The unit tests are run on the Arduino board.
  • The results of the test are printed over the serial port and analyzed by the Python script.
  • The script starts the next test, repeating the above steps for all test that are requested in the configuration file.
  • The script prints a summary showing an overview of all the failed/passed tests in the complete testsuite.

Keep hardware-specific code separate or abstracted away from the rest so you can test and debug that bigger "rest" on any platform for which you have good tools and with which you're familiar most.

Basically, try to build as much of the final code from as many known-to-work building blocks as possible. The remaining hardware-specific work will then be much easier and faster. You may finish it by using existing emulators and/or emulating devices on your own. And then, of course, you'll need to test the real thing somehow. Depending on circumstances, that may or may not be very well automatable (i.e. who or what will press buttons and provide other inputs? who or what will observe and interpret various indicators and outputs?).


James W. Grenning writes great books and this one is about unit testing embedded C code Test Driven Development for Embedded C.


I am using Searduino when writing Arduino code. Searduino is an Arduino simulator and a development environment (Makefiles, C code ...) that makes it easy to hack in C/C++ using your favorite editor. You can import Arduino sketches and run them in the simulator.

Screenshot of Searduino 0.8: http://searduino.files.wordpress.com/2014/01/jearduino-0-8.png

Searduino 0.9 will be released and a video will be recorded as soon as the lasts tests are done .... in a day or two.

Testing on the simulator is not to be considered as real tests, but it certainly have helped me a lot in finding stupid/logical mistakes (forgetting to do pinMode(xx, OUTPUT), etc.).

BTW: I am one of the people developing Searduino.


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:


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.


If you want to unit-test code outside MCU (on desktop), check out libcheck: https://libcheck.github.io/check/

I used it to test my own embedded code few times. It's pretty robust framework.


You can use emulare — you can drag and drop a microcontroller on a diagram and run your code in Eclipse. The documentation on the website tells you how to set it up.


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.


In basic Arduino is written with C and C++, even libraries of arduino are written in C and C++. So,in simple terms just handle the code as C and C++ and try doing the unit testing. Here, by the word "handle" I mean you to change all the basic syntax like serial.println to sysout, pinmode to varaibles, void loop to while() loop which breaks either in keystock or after some iteration.

I know this is little a long process and not so straight forward.On my personal experience, once you get to do with it, this turns to be more reliable.

-Nandha_Frost


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.

참고URL : https://stackoverflow.com/questions/780819/how-can-i-unit-test-arduino-code

반응형