Как я могу тестировать код Arduino?


Я хотел бы иметь возможность модульного тестирования моего кода Arduino. В идеале, я мог бы запустить любые тесты без необходимости загружать код в Arduino. Какие инструменты или библиотеки могут помочь мне в этом?

есть Arduino эмулятор в разработке который может быть полезен, но он еще не готов к использованию.

AVR Studio от Atmel содержит симулятор чипа, который может быть полезен, но я не вижу, как бы я его использовал в сочетании с Arduino IDE.

18 149

18 ответов:

Не запускайте модульные тесты на устройстве Arduino или эмуляторе

случай с микроконтроллерным устройством/эмулятором / Sim-тестами

цель модульного тестирования-проверить качество вашего собственного кода. Модульные тесты должны никогда проверьте функциональность факторов вне вашего контроля.

подумайте об этом так: даже если вы должны были проверить функциональность библиотеки Arduino, аппаратного обеспечения микроконтроллера или эмулятора, это совершенно невозможно для таких тестов, чтобы сказать вам что-нибудь о качестве собственной работы. Следовательно, есть абсолютно никакой ценности при написании модульных тестов, которые выполняются на устройстве (или эмуляторе) вообще.

независимо от того, рассматриваете ли вы запуск тестов на устройстве или эмуляторе, вы все равно заставляете себя повторять жестоко медленный процесс:

  1. настроить ваш код
  2. компиляция и загрузка в Arduino устройство
  3. наблюдать за поведением и гадать о том, работает ли он или нет.
  4. повторить

Шаг 3 особенно неприятен, если вы ожидаете получить диагностические сообщения через последовательный порт, но сам ваш проект должен использовать только аппаратный последовательный порт вашего Arduino. Если вы думали, что библиотека SoftwareSerial может помочь, вы должны знать, что это может нарушить любую функциональность, которая требует точного времени, например генерация других сигналов одновременно. Эта самая проблема случилась со мной.

опять же, если вы должны были проверить свой эскиз с помощью эмулятора и ваши критические по времени процедуры выполнялись отлично, пока вы не загрузили на фактический Arduino, то единственный урок, который вы собираетесь узнать, заключается в том, что эмулятор имеет недостатки-и зная это все еще показывает ничего о качестве собственной работы!

если это глупо, чтобы проверить на устройстве или эмуляторе, что должны я делаю?

вы, вероятно, используете компьютер для работы над вашим проектом Arduino. Этот компьютер буквально тысячи раз быстрее, чем микроконтроллер. Напишите тесты для сборки и запуск на вашем компьютере.

помните, что поведение библиотеки Arduino и микроконтроллера должно быть предполагается, что либо правильно, либо по крайней мере последовательно неправильно.

когда ваши тесты производят вывод вопреки вашим ожиданиям, то у вас, вероятно, есть недостаток в вашем коде, который был протестирован. Если ваш тестовый вывод соответствует вашим ожиданиям, но программа не ведет себя правильно, когда вы загружаете ее в Arduino, то вы знаете, что ваши тесты были основаны на неверных предположениях, и у вас, вероятно, есть ошибочный тест. В любом случае, вы получите реальное представление о том, что ваши следующие изменения кода должны быть.

как построить и Запуск тестов на вашем ПК

первое, что вам нужно сделать, это определите свои цели тестирования. Подумайте о том, какие части код вы хотите проверить, а затем убедитесь, что построить свою программу таким образом, что вы можете изолировать отдельные части для тестирования.

Если части, которые вы хотите протестировать, вызывают любые функции Arduino, вам нужно будет предоставить макетные замены в вашей тестовой программе. Это гораздо меньше работы, чем кажется. Ваши макеты не должны на самом деле делать ничего, кроме обеспечения предсказуемого ввода и вывода для ваших тестов.

любой ваш собственный код, который вы собираетесь тестировать, должен существовать в других исходных файлах .ФДЭ эскиз. Не волнуйтесь, ваш эскиз все равно будет компилироваться даже с некоторым исходным кодом за пределами эскиза. Когда вы действительно приступите к этому, в файле sketch должно быть определено немного больше, чем обычная точка входа вашей программы.

все, что остается написать фактические тесты, а затем скомпилировать его с помощью вашего любимого компилятора C++! Это, вероятно, лучше всего иллюстрируется на примере реального мира.

фактический рабочий пример

один из моих любимых проектов нашли здесь имеет несколько простых тестов, которые работают на ПК. Для этого ответа я просто расскажу, как я издевался над некоторыми функциями библиотеки Arduino и тестами, которые я написал, чтобы проверить эти макеты. Это не противоречит тому, что я говорил раньше о не тестировании код других людей, потому что я был тем, кто написал макеты. Я хотел быть уверен, что мои макеты были правильными.

источник mock_arduino.cpp, который содержит код, который дублирует некоторые функции поддержки, предоставляемые библиотекой Arduino:

#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();
}

этот пост достаточно длинный, поэтому, пожалуйста, обратитесь к мой проект на GitHub чтобы увидеть еще несколько тестовых случаев в действии. Я продолжаю свою работу в ветвях, отличных от master, поэтому проверьте эти ветви для дополнительных тестов.

я решил написать свои собственные легкие тестовые процедуры, но более надежные также доступны платформы модульного тестирования, такие как CppUnit.

в отсутствие каких-либо ранее существующих модульных тестовых платформ для Arduino, я создал ArduinoUnit. Вот простой эскиз Arduino, демонстрирующий его использование:

#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();
}

у меня есть значительный успех модуль тестирования моего кода PIC, абстрагируясь от аппаратного доступа и издеваясь над ним в моих тестах.

например, я абстрактный PORTA с

#define SetPortA(v) {PORTA = v;}

тогда SetPortA можно легко высмеять, не добавляя служебный код в версию PIC.

после того, как аппаратная абстракция была протестирована некоторое время, я скоро обнаружу, что обычно код идет от тестовой установки к PIC и работает первым время.

обновление:

я использую шов #include для кода модуля, #включая код модуля в файле C++ для тестовой установки и файл C для целевого кода.

в качестве примера я хочу мультиплексировать четыре 7-сегментных дисплея, один порт управляет сегментами, а второй выбирает дисплей. Код дисплея взаимодействует с дисплеями через SetSegmentData(char) и SetDisplay(char). Я могу издеваться над ними в своей тестовой установке C++ и проверять, что я получаю данные, которые ожидаю. Для цель я использую #define так что я получаю прямое назначение без накладных расходов на вызов функции

#define SetSegmentData(x) {PORTA = x;}

кажется, emulino сделал бы работу отлично.

Emulino-это эмулятор для платформы Arduino от Greg Hewgill. (источник)

репозитории GitHub

simavr это AVR симулятор С помощью avr-gcc.

Он уже поддерживает несколько микроконтроллеров ATTiny и ATMega, и - по словам автора - легко добавить еще несколько.

в примерах лежит simduino, эмулятор Arduino. Он поддерживает запуск загрузчика Arduino и может быть запрограммирован с помощью avrdude через Socat (модифицированный Netcat).

вы можете модульный тест в Python с моим проектом,PySimAVR. Arscons используется для строительства и simavr для моделирования.

пример:

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'

Начать тест:

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

Я не знаю ни одной платформы, которая может тестировать код Arduino.

, есть Fritzing платформа, которую вы можете использовать для моделирования оборудования, а затем экспортировать диаграммы печатных плат и прочее.

стоит проверить.

мы используем платы Arduino для сбора данных в большом научном эксперименте. Впоследствии, мы должны поддерживать несколько плат Arduino с различными реализациями. Я написал утилиты Python для динамической загрузки шестнадцатеричных изображений Arduino во время модульного тестирования. Код, найденный по ссылке ниже, поддерживает Windows и Mac OS X через файл конфигурации. Чтобы узнать, где ваши шестнадцатеричные изображения размещаются с помощью Arduino IDE, нажмите клавишу shift, прежде чем нажать кнопку build (play). Нажмите клавишу shift при нажатии загрузить, чтобы узнать, где ваш avrdude (утилита загрузки командной строки) находится в вашей системе / версии Arduino. Кроме того, вы можете посмотреть включенные файлы конфигурации и использовать свое место установки (в настоящее время на Arduino 0020).

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

эта программа позволяет автоматизировать запуск нескольких модульных тестов Arduino. Процесс тестирования запускается на ПК, но тесты выполняются на реальном оборудовании Arduino. Один набор модульных тестов обычно используется для тестирования одной библиотеки Arduino. (это

форум Arduino:http://arduino.cc/forum/index.php?topic=140027.0

страница проекта GitHub:http://jeroendoggen.github.com/Arduino-TestSuite

страница в индексе пакета Python: http://pypi.python.org/pypi/arduino_testsuite

модульные тесты написаны с помощью "библиотеки модульного тестирования Arduino":http://code.google.com/p/arduinounit

для каждого набора модульных тестов выполняются следующие шаги:

  • прочитайте файл конфигурации, чтобы узнать, какие тесты для запуска
  • скрипт компилирует и загружает эскиз Arduino, который содержит код модульного тестирования.
  • unit-тесты бежать на плате Arduino.
  • результаты теста печатаются через последовательный порт и анализируются скриптом Python.
  • сценарий запускает следующий тест, повторяя описанные выше шаги для всех тестов, запрошенных в файле конфигурации.
  • сценарий печатает сводку, показывающую обзор всех неудачных / пройденных тестов в полном testsuite.

Я использую Searduino при написании кода Arduino. Searduino-это симулятор Arduino и среда разработки (Makefiles, C-код ...), что делает его легко взломать в C/C++ с использованием вашего любимого редактора. Вы можете импортировать эскизы Arduino и запускать их в симуляторе.

скриншот Searduino 0.8:http://searduino.files.wordpress.com/2014/01/jearduino-0-8.png

Searduino 0.9 будет выпущен и видео будет записано в ближайшее время по мере того как последние испытания сделаны .... через день или два.

тестирование на симуляторе не следует рассматривать как реальные тесты, но это, безусловно, очень помогло мне найти глупые / логические ошибки (забыв сделать pinMode(xx, OUTPUT) и т. д.).

кстати: я один из людей, развивающих Searduino.

держите аппаратный код отдельным или абстрагированным от остальных, чтобы вы могли тестировать и отлаживать этот больший "отдых" на любой платформе, для которой у вас есть хорошие инструменты и с которой вы знакомы больше всего.

в принципе, попробуйте построить как можно больше окончательного кода из как можно большего количества известных для работы строительных блоков. Оставшаяся аппаратная работа будет намного проще и быстрее. Вы можете завершить его с помощью существующих эмуляторов и / или эмулирующих устройств самостоятельно. И, конечно, вам нужно будет как-то проверить настоящую вещь. В зависимости от обстоятельств, это может быть или не быть очень хорошо автоматизируемым (т. е. кто или что будет нажимать кнопки и предоставлять другие входы? кто или что будет наблюдать и интерпретировать различные показатели и результаты?).

Джеймс У. Греннинг пишет отличные книги, и это касается модульного тестирования встроенного кода C тестовая разработка для встроенного C.

есть проект под названием ncore, который обеспечивает родное ядро для Arduino. И позволяет писать тесты для кода Arduino.

описание проекта

родное ядро позволяет компилировать и запускать Arduino эскизы на ПК, как правило, без изменений. Он предоставляет собственные версии стандартные функции Arduino, и interepreter командной строки, котор нужно дать входные данные для вашего эскиза, которые обычно поступают из аппаратного обеспечения себя.

также на "что мне нужно, чтобы использовать его в раздел"

Если вы хотите построить тесты, вам понадобится cxxtest от http://cxxtest.tigris.org. NCORE был протестирован с помощью cxxtest 3.10.1.

Если вы хотите модульный тестовый код вне MCU (на рабочем столе), проверьте libcheck: https://libcheck.github.io/check/

Я использовал его, чтобы проверить свой собственный встроенный код несколько раз. Это довольно прочная структура.

я рад объявить (что, кажется) первый стабильный релиз рубиновый камень называется arduino_ci что я построил для этой цели. Хотя он ограничен тестированием библиотек Arduino (а не автономных эскизов), он позволяет запускать модульные тесты на Travis CI.

предполагая, что у вас установлены Ruby и rubygems, добавление этого CI в библиотеку является простым. Давайте представим себе очень простую библиотеку в вашем каталоге библиотеки Arduino, называемую DoSomething. Оно содержит файл заголовка, и эта реализация:

#include <Arduino.h>
#include "do-something.h"

int doSomething(void) {
  return 4;
};

давайте проверим его с arduino_ci. Во-первых, вам нужно добавить Gemfile в корневом каталоге вашей библиотеки со следующим содержимым:

source 'https://rubygems.org'
gem 'arduino_ci', '~> 0.1.7'

далее запустить bundle install.

затем создайте каталог под названием test/. (Каждый .cpp файл, который вы размещаете здесь, будет считаться отдельным набором тестов). Мы создадим один тест на данный момент, в test/is_four.cpp:

#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.

вот и все. Если это assertEqual синтаксис и структура теста выглядит знакомо, это потому, что я принял некоторые ArduinoUnit библиотека Мэтью Мердока что он упомянул в ответ.

теперь вы готовы запустить bundle exec arduino_ci_remote.rb, который будет выполнять эти тесты. Это может дать выход что-то вроде этого:

$ bundle exec arduino_ci_remote.rb
Installing library under test...                                               ✓
Library installed at /Users/XXXXX/Documents/Arduino/libraries/DoSomething...   ✓
Checking GCC version...
    Using built-in specs.
    COLLECT_GCC=g++-4.9
    COLLECT_LTO_WRAPPER=/usr/local/Cellar/gcc@4.9/4.9.4_1/libexec/gcc/x86_64-apple-darwin16.    7.0/4.9.4/lto-wrapper
    Target: x86_64-apple-darwin16.7.0
    Configured with: ../configure --build=x86_64-apple-darwin16.7.0     --prefix=/usr/local/Cellar/gcc@4.9/4.9.4_1     --libdir=/usr/local/Cellar/gcc@4.9/4.9.4_1/lib/gcc/4.9 --enable-languages=c,c++,objc,    obj-c++,fortran --program-suffix=-4.9 --with-system-zlib --enable-libstdcxx-time=yes     --enable-stage1-checking --enable-checking=release --enable-lto --enable-plugin     --with-build-config=bootstrap-debug --disable-werror --with-pkgversion='Homebrew GCC     4.9.4_1' --with-bugurl=https://github.com/Homebrew/homebrew-core/issues     MAKEINFO=missing --disable-nls --enable-multilib
    Thread model: posix
    gcc version 4.9.4 (Homebrew GCC 4.9.4_1)
...Checking GCC version                                                        ✓
Installing board package arduino:sam...                                        ✓
Unit testing is_four.cpp...

TAP version 13
1..1
# Subtest: library_does_something
    ok 1 - assertEqual 4 == doSomething()
    1..1
ok 1 - library_does_something
...Unit testing is_four.cpp                                                    ✓
Failures: 0

запуск того же кода как часть задания CI на Трэвис CI (например, так что вы можете вызвать его из запросов GitHub pull) является и очень просто. Просто добавьте это в свой .travis.yml file:

language: ruby
script:
   - bundle install
   - bundle exec arduino_ci_remote.rb

конечно, есть гораздо больше мощности и гибкости для этой библиотеки CI чем я сюда попаду. Вот еще несколько примеров:

можно использовать emulare - вы можете перетащить микроконтроллер на диаграмму и запустить свой код в Eclipse. Документация на веб-сайте рассказывает вам, как его настроить.

используйте Proteus VSM с библиотекой Arduino для отладки кода или его тестирования.

Это лучшая практика, прежде чем получить ваш код на борту, но будьте уверены, с таймингами, потому что моделирование не работает в реальном времени, как они работают на борту.

попробовать Autodesk circuit simulator. Это позволяет тестировать код Arduino и схемы со многими другими аппаратными компонентами.