ฉันจะทดสอบรหัส Arduino ได้อย่างไร?


186

ฉันต้องการที่จะสามารถทดสอบโค้ด Arduino ของฉันได้ เป็นการดีที่ฉันจะสามารถเรียกใช้การทดสอบใด ๆ โดยไม่ต้องอัปโหลดรหัสไปยัง Arduino เครื่องมือหรือไลบรารีใดที่สามารถช่วยฉันได้

มีตัวจำลอง Arduino ในการพัฒนาซึ่งอาจมีประโยชน์ แต่ก็ยังไม่พร้อมที่จะใช้งาน

AVR Studioจาก Atmel มีตัวจำลองชิปซึ่งอาจมีประโยชน์ แต่ฉันไม่เห็นว่าฉันจะใช้ร่วมกับ Arduino IDE ได้อย่างไร


มีเธรดอื่นสำหรับคำถามนี้จาก 2011 ที่arduino.cc/forum/index.php?action=printpage;topic=54356.0
— จา

ขอบคุณ @ Jakob เครื่องจำลอง Arduino อ้างอิงในหัวข้อนั้น (พร้อมลิงค์ที่มีประโยชน์อื่น ๆ ที่ด้านล่างของหน้า): arduino.com.au/Simulator-for-Arduino.html
— Matthew Murdoch

5
น่าเสียดายสำหรับ Windows เท่านั้นฉันต้องการเห็นวิธีการรวบรวมและเรียกใช้รหัส Arduino จากบรรทัดคำสั่งโดยไม่ต้องพึ่งพาแหล่งปิดหรือการพึ่งพาฮาร์ดแวร์
— Jakob

3
การปรับปรุงเล็ก ๆ น้อย ๆ ในอีก 5 ปีต่อมา: Simavrยังคงใช้งานได้ดีมากและได้รับการปรับปรุงมากมายตั้งแต่มีการถามคำถามดังนั้นฉันจึงคิดว่าสมควรที่จะได้รับแรงกระแทกจากด้านบน และอาจเป็นเครื่องมือที่เหมาะสมสำหรับการทดสอบการถดถอยการทดสอบตามสถานการณ์และทำไมไม่ทดสอบด้วยหน่วย วิธีนี้โค้ดที่คุณทดสอบจะเหมือนกับโค้ดบนฮาร์ดแวร์เป้าหมาย
— zmo

สำหรับโครงการสำคัญพิจารณาตัวทดสอบฮาร์ดแวร์ MCU อีกตัวที่มากกว่าเวลาและปุ่มทดสอบ / สวิตช์ปฏิกิริยาเวลาบูตอุณหภูมิการใช้ v / ma การเปลี่ยนรูปแบบตัวเลือกแปลก ฯลฯ ใช่มันเป็นฮาร์ดแวร์ที่จะสร้างมากขึ้น แต่สามารถเพิ่มชั้นความปลอดภัยในการแก้ไขได้ อุปกรณ์ pro จำนวนมากใช้ jtag และคณะ
— dandavis

คำตอบ:


136

อย่าเรียกใช้การทดสอบหน่วยบนอุปกรณ์ Arduino หรือตัวจำลอง

กรณีกับการทดสอบอุปกรณ์ไมโครคอนโทรลเลอร์ / จำลอง / ซิมที่ใช้

มีการถกเถียงกันมากมายเกี่ยวกับความหมายของการทดสอบหน่วยและฉันไม่ได้พยายามโต้เถียงเกี่ยวกับเรื่องนี้ โพสต์นี้ไม่ได้ บอกให้คุณหลีกเลี่ยงการทดสอบเชิงปฏิบัติทั้งหมดเกี่ยวกับฮาร์ดแวร์เป้าหมายสูงสุด ฉันกำลังพยายามหาจุดที่ทำให้วงจรการตอบรับการพัฒนาของคุณดีที่สุดโดยกำจัดฮาร์ดแวร์เป้าหมายของคุณออกจากการทดสอบทางโลกและบ่อยครั้งที่สุด หน่วยภายใต้การทดสอบจะถือว่ามีขนาดเล็กกว่าโครงการทั้งหมด

วัตถุประสงค์ของการทดสอบหน่วยคือการทดสอบคุณภาพของรหัสของคุณเอง การทดสอบหน่วยโดยทั่วไปไม่ควรทดสอบการทำงานของปัจจัยที่อยู่นอกเหนือการควบคุมของคุณ

คิดแบบนี้: แม้ว่าคุณจะต้องทดสอบการทำงานของห้องสมุด Arduino ฮาร์ดแวร์ไมโครคอนโทรลเลอร์หรืออีมูเลเตอร์มันเป็นไปไม่ได้อย่างแน่นอนสำหรับผลการทดสอบดังกล่าวที่จะบอกคุณเกี่ยวกับคุณภาพของงานของคุณเอง ดังนั้นจึงมีคุณค่าและมีประสิทธิภาพมากขึ้นในการเขียนการทดสอบหน่วยที่ไม่ได้ทำงานบนอุปกรณ์เป้าหมาย (หรืออุปกรณ์จำลอง)

การทดสอบฮาร์ดแวร์เป้าหมายเป็นประจำมีรอบการทำงานที่ช้าอย่างเจ็บปวด:

  1. ปรับแต่งรหัสของคุณ
  2. รวบรวมและอัพโหลดไปยังอุปกรณ์ Arduino
  3. สังเกตพฤติกรรมและเดาว่ารหัสของคุณทำในสิ่งที่คุณคาดหวังหรือไม่
  4. ทำซ้ำ

ขั้นตอนที่ 3 เป็นสิ่งที่น่ารังเกียจอย่างยิ่งหากคุณคาดว่าจะได้รับข้อความวินิจฉัยผ่านพอร์ตอนุกรม แต่โครงการของคุณจำเป็นต้องใช้พอร์ตอนุกรมฮาร์ดแวร์ของ Arduino เท่านั้น หากคุณคิดว่า SoftwareSerial library อาจช่วยได้คุณควรรู้ว่าการทำเช่นนั้นมีแนวโน้มที่จะรบกวนการทำงานใด ๆ ที่ต้องใช้เวลาที่แม่นยำเช่นสร้างสัญญาณอื่น ๆ ในเวลาเดียวกัน ปัญหานี้เกิดขึ้นกับฉัน

อีกครั้งถ้าคุณต้องทดสอบภาพร่างของคุณโดยใช้อีมูเลเตอร์และรูทีนเวลาที่สำคัญของคุณจะวิ่งอย่างสมบูรณ์แบบจนกว่าคุณจะอัปโหลดไปยัง Arduino ที่แท้จริงแล้วบทเรียนเดียวที่คุณจะได้เรียนรู้คืออีมูเลเตอร์มีข้อบกพร่อง เผยให้เห็นอะไรเกี่ยวกับคุณภาพของคุณเองทำงาน

ถ้ามันโง่ที่จะทดสอบอุปกรณ์หรือโปรแกรมจำลองฉันควรทำอย่างไร

คุณอาจกำลังใช้คอมพิวเตอร์เพื่อทำงานในโครงการ Arduino ของคุณ คอมพิวเตอร์เครื่องนั้นมีขนาดของคำสั่งเร็วกว่าไมโครคอนโทรลเลอร์ เขียนการทดสอบการสร้างและการทำงานบนคอมพิวเตอร์ของคุณ

โปรดจำไว้ว่าพฤติกรรมของห้องสมุด Arduino และไมโครคอนโทรลเลอร์ควรได้รับการสันนิษฐานว่าจะเป็นอย่างใดอย่างหนึ่งที่ถูกต้องหรืออย่างน้อยอย่างต่อเนื่องที่ไม่ถูกต้อง

เมื่อการทดสอบของคุณสร้างผลลัพธ์ที่ตรงกันข้ามกับความคาดหวังของคุณคุณอาจมีข้อบกพร่องในรหัสของคุณที่ได้รับการทดสอบ หากผลการทดสอบของคุณตรงกับความคาดหวังของคุณ แต่โปรแกรมทำงานไม่ถูกต้องเมื่อคุณอัปโหลดไปยัง Arduino คุณจะรู้ว่าการทดสอบของคุณอยู่บนสมมติฐานที่ไม่ถูกต้องและคุณอาจมีข้อบกพร่องในการทดสอบ ไม่ว่าในกรณีใดคุณจะได้รับข้อมูลเชิงลึกที่แท้จริงเกี่ยวกับการเปลี่ยนแปลงรหัสถัดไปของคุณ คุณภาพของความคิดเห็นของคุณจะดีขึ้นจาก " บางสิ่งบางอย่างเสีย" เพื่อ"นี้รหัสเฉพาะเสีย"

วิธีการสร้างและรันการทดสอบบนพีซีของคุณ

สิ่งแรกที่คุณต้องทำคือการระบุเป้าหมายการทดสอบของคุณ คิดว่าส่วนใดของรหัสของคุณที่คุณต้องการทดสอบแล้วตรวจสอบให้แน่ใจว่าได้สร้างโปรแกรมของคุณในลักษณะที่คุณสามารถแยกส่วนที่แยกออกจากกันสำหรับการทดสอบ

หากชิ้นส่วนที่คุณต้องการทดสอบเรียกใช้ฟังก์ชั่น Arduino ใด ๆ คุณจะต้องจัดหาการเปลี่ยนจำลองในโปรแกรมทดสอบของคุณ นี่มันทำงานน้อยกว่าที่คิด การจำลองของคุณไม่จำเป็นต้องทำอะไรนอกจากให้การป้อนข้อมูลและผลลัพธ์ที่คาดการณ์ได้สำหรับการทดสอบของคุณ

รหัสใด ๆ ของคุณที่คุณตั้งใจจะทดสอบจำเป็นต้องมีอยู่ในไฟล์ต้นฉบับนอกเหนือจากร่าง. pde ไม่ต้องกังวลร่างของคุณจะยังคงคอมไพล์แม้จะมีซอร์สโค้ดอยู่ด้านนอกของร่าง เมื่อคุณลงไปจริง ๆ ควรกำหนดจุดเข้าน้อยกว่าปกติของโปรแกรมไว้ในไฟล์ร่าง

สิ่งที่เหลืออยู่คือการเขียนการทดสอบจริงแล้วรวบรวมโดยใช้คอมไพเลอร์ 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);
}

ฉันใช้ mock-up ต่อไปนี้เพื่อสร้างเอาต์พุตที่สามารถอ่านได้เมื่อโค้ดของฉันเขียนข้อมูลไบนารีไปยังอุปกรณ์ซีเรียลฮาร์ดแวร์

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เพื่อดูกรณีทดสอบเพิ่มเติมในทางปฏิบัติ ฉันเก็บผลงานของฉันในสาขาอื่นที่ไม่ใช่เจ้านายดังนั้นให้ตรวจสอบสาขาเหล่านั้นเพื่อทำการทดสอบเพิ่มเติมด้วย

ฉันเลือกที่จะเขียนกิจวัตรการทดสอบที่มีน้ำหนักเบาของตัวเอง แต่ยังมีเฟรมเวิร์กการทดสอบหน่วยที่แข็งแกร่งกว่าเช่น CppUnit อีกด้วย


1
นี่เป็นคำตอบที่ยอดเยี่ยม! ขอบคุณ!
— Jonathan Arkell

5
@WarrenMacEvoy อีกครั้งฉันคิดว่าคุณได้รับคำแนะนำของฉันและทำให้มันเป็นสิ่งที่ไม่ใช่ แน่นอนคุณควรทดสอบรหัสของคุณในสภาพแวดล้อมจริงที่บางจุด ข้อโต้แย้งของฉันคือคุณไม่ควรทำอย่างนั้นทุกวันและคุณไม่ควรเรียกมันว่าเป็นการทดสอบหน่วย
— ผู้ช่วยให้รอดเหล็ก

1
@toasted_flakes ฉันไม่แน่ใจว่าคุณได้รับใบเสนอราคานั้นจากที่ไหน แต่มันไม่ใช่สิ่งที่ฉันพูด การทดสอบหน่วยที่ทำงานบนอุปกรณ์มีปัญหามากมาย - ลูปติชมช้ามากคุณอาจไม่มีพอร์ตอนุกรมหรือวิธีการอื่นใดของ IO ที่สำรองไว้ในอุปกรณ์เป้าหมายของคุณและมีความจุ จำกัด มากซึ่งอาจส่งผลกระทบต่อขอบเขตของ ชุดทดสอบของคุณ
— ผู้ช่วยให้รอดเหล็ก

1
@ChristianHujer คุณควรทดสอบฮาร์ดแวร์จริง ๆ - ไม่มีใครบอกว่าคุณไม่ควรทดสอบฮาร์ดแวร์เป้าหมาย โพสต์ของฉันเกี่ยวกับการทำให้ข้อเสนอแนะการพัฒนารายวันของคุณแน่นขึ้นโดยการทดสอบหน่วยบนเครื่องพัฒนาของคุณ ค่าใช้จ่ายในการทดสอบของคุณจะลดลงด้วยวิธีนี้เนื่องจากคุณจะทดสอบเฉพาะฮาร์ดแวร์เป้าหมายเมื่อจำเป็น
— ผู้ช่วยให้รอดเหล็ก

1
@Benjohn Arduino ไฟล์ต้นฉบับร่างที่มีนามสกุล "pde" แม้ว่าพวกเขาจะเป็น C ++ arduino.cc/en/Guide/Environment#toc1
— ผู้ช่วยให้รอดเหล็ก

63

ในกรณีที่ไม่มีของที่มีอยู่ก่อนกรอบการทดสอบหน่วยใด ๆ สำหรับ 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();
}

18
การทดสอบดูเหมือนจะทำงานเฉพาะใน arduino ดังนั้นคุณจึงไม่สามารถดำเนินการทดสอบได้โดยอัตโนมัติบนเครื่องพัฒนาของคุณ แนวคิดพื้นฐานของการทดสอบหน่วยคือการรันโดยอัตโนมัติดังนั้นการออกแบบปัจจุบันดูเหมือนจะเป็นเครื่องมือในการดีบั๊ก แต่ไม่มีกรอบการทดสอบหน่วยจริง
— Jakob

1
คุณถูก. ในการที่จะสามารถเรียกใช้สิ่งเหล่านี้บนพีซีจะต้องมี Arduino หรือ AVR emulator ไม่มีเลเยอร์ abstraction ฮาร์ดแวร์ที่แท้จริงในไลบรารี Arduino (ในขณะนี้) และอีมูเลเตอร์ AVR เมื่อฉันดูยังคงพัฒนาอยู่ หากสิ่งต่าง ๆ ได้ดำเนินต่อไปในหลักการก็สามารถทำได้
— Matthew Murdoch

12
@MatthewMurdoch ฉันกลัวว่าคุณไม่ถูกต้อง ตามคำนิยามการทดสอบหน่วยจะไม่ทำงานในสภาพแวดล้อมเป้าหมาย ในความเป็นจริงแนวคิดที่อยู่เบื้องหลังการทดสอบหน่วยคือการกำจัดสภาพแวดล้อมเป้าหมายออกจากการทดสอบอย่างสมบูรณ์ พวกเขามักจะทำงานในสภาพแวดล้อมที่เหมือนห้องปฏิบัติการที่ลอกเลียนกิจกรรมทั้งหมดภายนอกหน่วยที่กำลังทดสอบเพื่อให้แน่ใจว่าความสำเร็จหรือความล้มเหลวของการทดสอบสะท้อนให้เห็นเฉพาะในหน่วยที่ทดสอบ นั่นเป็นหนึ่งในเหตุผลที่ใหญ่ที่สุดที่ผู้คนใช้แนวคิดของการกลับใจควบคุมในโครงการที่ซับซ้อน
— ผู้ช่วยให้รอดเหล็ก

2
@ marcv81 พื้นที่ที่มีปัญหาการพกพามีอยู่น่าจะเป็นวิชาที่ไม่ดีสำหรับการทดสอบหน่วย โปรดจำไว้ว่าการทดสอบหน่วยควรทดสอบโค้ดของคุณเท่านั้นดังนั้น จำกัด ขอบเขตให้เหมาะสม ด้วยความไม่เท่าเทียมกันอย่างมากมายในฮาร์ดแวร์ที่เรากำลังพูดถึงที่นี่ฉันสามารถยอมรับได้ว่าสถานการณ์ดังกล่าวบางอย่างอาจหลีกเลี่ยงไม่ได้ ในกรณีเหล่านั้นวิศวกรควรคงไว้ซึ่งความรู้ความเข้าใจและทำตามขั้นตอนเพื่อบรรเทา ซึ่งอาจหมายถึงการปรับเปลี่ยนการออกแบบของคุณเพื่อปรับปรุงความสามารถในการทดสอบหรือแม้แต่สิ่งที่ง่ายเพียงแค่บันทึกข้อเท็จจริงที่เกี่ยวข้อง
— ผู้ช่วยให้รอดเหล็ก

2
@Iron Savior การทดสอบหน่วยทดสอบโค้ดของคุณ แต่โค้ดของคุณทำงานที่ใดที่หนึ่ง หากบริบทนั้นเป็นหรือจำลองบริบท Arduino; จากนั้น ArdunoUnit จะช่วยให้คุณเขียนการทดสอบหน่วย หากคุณดูที่โครงการ ArduinoUnit การทดสอบเมตาของเฟรมเวิร์กจะโหลดรันและตรวจสอบผลลัพธ์ของการทดสอบบนเป้าหมายข้ามแพลตฟอร์มโดยอัตโนมัติ เช่นเดียวกับที่คุณทำในเป้าหมายข้ามแพลตฟอร์มอื่น ๆ มุมมองของคุณเป็นข้ออ้างสำหรับการไม่ทดสอบโค้ดในสภาพแวดล้อมแบบฝังตัวที่ความถูกต้องมีความสำคัญมากหากไม่มากไปกว่าบริบทอื่น ๆ
— Warren MacEvoy

21

ฉันประสบความสำเร็จอย่างมากในการทดสอบโค้ด PIC ของฉันโดยการสรุปการเข้าถึงฮาร์ดแวร์และเยาะเย้ยในการทดสอบของฉัน

ตัวอย่างเช่นฉัน abstract PORTA ด้วย

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

จากนั้น SetPortA สามารถเยาะเย้ยได้อย่างง่ายดายโดยไม่ต้องเพิ่มรหัสค่าใช้จ่ายในเวอร์ชัน PIC

เมื่อฮาร์ดแวร์ที่ได้รับการทดสอบในขณะที่ฉันเร็ว ๆ นี้พบว่ารหัสโดยทั่วไปไปจากอุปกรณ์ทดสอบเพื่อ PIC และทำงานเป็นครั้งแรก

ปรับปรุง:

ฉันใช้ตะเข็บ #include สำหรับรหัสหน่วย # รวมถึงรหัสหน่วยในไฟล์ C ++ สำหรับอุปกรณ์ทดสอบและไฟล์ C สำหรับรหัสเป้าหมาย

เป็นตัวอย่างที่ฉันต้องการมัลติเพล็กซ์สี่เซกชั่นจอแสดงผลหนึ่งพอร์ตขับเซกเมนต์และวินาทีเลือกจอแสดงผล อินเตอร์เฟซรหัสการแสดงผลด้วยการแสดงผ่านทางและSetSegmentData(char) SetDisplay(char)ฉันสามารถจำลองสิ่งเหล่านี้ในอุปกรณ์ทดสอบ C ++ ของฉันและตรวจสอบว่าฉันได้รับข้อมูลที่ฉันคาดหวัง สำหรับเป้าหมายที่ฉันใช้#defineเพื่อให้ฉันได้รับการมอบหมายโดยตรงโดยไม่มีค่าใช้จ่ายในการเรียกใช้ฟังก์ชัน

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

ฉันเห็นในหลักการว่าฉันสามารถใช้ 'ตะเข็บ' ของโปรเซสเซอร์สำหรับการทดสอบหน่วยได้อย่างไร อย่างไรก็ตามฉันไม่แน่ใจว่าฉันสามารถทำเช่นนี้ได้อย่างไรโดยไม่ต้องมีอีมูเลเตอร์ซึ่งใช้ในการทดสอบหรือคอมไพเลอร์ที่รองรับ avr-gcc ซึ่งแสดงผล (ในกรณีของฉัน) ไบนารี Windows ...
— Matthew Murdoch

ขอบคุณสำหรับการอัพเดท. คุณใช้การทดสอบหน่วยใน PIC หรือบนพีซีของคุณหรือไม่?
— Matthew Murdoch

การทดสอบหน่วยทำงานบน Mac โดยใช้ Xcode ในการรันบน Pic อาจต้องใช้โปรแกรมจำลองบางอย่าง สรุปมันจึงทำงานบน Mac ทำให้โปรเซสเซอร์สลับการจัดการที่ดี easieer
— เดวิด Sykes

สภาพแวดล้อม Arduino ใช้คอมไพเลอร์ avr-gcc ซึ่งมี idiosyncrasies บางตัวซึ่งหมายความว่าการคอมไพล์ด้วย gcc (หรือคอมไพเลอร์ C ++ อื่น ๆ ) และทำงานบนพีซีอาจไม่ได้หมายความว่ารหัสจะคอมไพล์บน avr-gcc
— Matthew Murdoch

คุณกำลังพูดถึงความแตกต่างอะไร เป็นสิ่งที่ไม่สามารถจัดการได้ด้วยคำสั่งพรีโปรเซสเซอร์หรือไม่?
— Joseph Lisee


12

simavrเป็นตัวจำลอง AVR โดยใช้ avr-gcc

มันรองรับคอนโทรลเลอร์ไมโครคอนโทรลเลอร์ ATTiny และ ATMega สองสามตัวและ - ตามที่ผู้เขียนบอกไว้ - มันง่ายที่จะเพิ่มอีก

ในตัวอย่างอยู่ที่ simduino ตัวเลียนแบบ Arduino รองรับการรัน Arduino bootloader และสามารถตั้งโปรแกรมด้วย avrdude ผ่านSocat ( Netcat ที่แก้ไข)


9

คุณสามารถทดสอบหน่วยในหลามกับโครงการของฉัน, 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

6

ฉันไม่ทราบถึงแพลตฟอร์มใด ๆ ที่สามารถทดสอบรหัส Arduino ได้

อย่างไรก็ตามมีแพลตฟอร์มFritzingซึ่งคุณสามารถใช้เพื่อจำลองแบบฮาร์ดแวร์และรุ่นที่ใหม่กว่าในการส่งออกไดอะแกรม PCB และเนื้อหา

การตรวจสอบที่คุ้มค่า


6

เราใช้บอร์ด Arduino สำหรับเก็บข้อมูลในการทดลองทางวิทยาศาสตร์ครั้งใหญ่ ต่อจากนั้นเราต้องสนับสนุนบอร์ด Arduino หลายตัวที่มีการใช้งานที่แตกต่างกัน ฉันเขียนโปรแกรมอรรถประโยชน์ Python เพื่อโหลดภาพ hex Arduino แบบไดนามิกระหว่างการทดสอบหน่วย รหัสที่พบในลิงค์ด้านล่างรองรับ Windows และ Mac OS X ผ่านไฟล์กำหนดค่า เพื่อหาตำแหน่งที่วางภาพเลขฐานสิบหกของคุณโดย Arduino IDE กดปุ่ม Shift ก่อนที่คุณจะกดปุ่มสร้าง (เล่น) กดปุ่ม Shift ขณะกดปุ่มอัพโหลดเพื่อดูว่า avrdude ของคุณ (ยูทิลิตี้อัพโหลดบรรทัดคำสั่ง) ตั้งอยู่บน Arduino / ระบบของคุณ หรือคุณสามารถดูไฟล์กำหนดค่าที่รวมอยู่และใช้ตำแหน่งการติดตั้งของคุณ (ปัจจุบันคือ Arduino 0020)

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


+1 สิ่งที่ยอดเยี่ยม! คุณมีข้อมูลใด ๆ เกี่ยวกับการทดสอบหน่วยของคุณเมื่ออัพโหลดรูปภาพแล้วหรือยัง?
— Matthew Murdoch

เราใช้ nosetests เพื่อทดสอบหน่วยของเราบนฝั่งหลาม การตั้งค่าสำหรับการทดสอบแต่ละครั้งจะโหลดอิมเมจ hex ที่ถูกต้องสำหรับการทดสอบนั้น เราเริ่มต้นเล็ก ๆ แล้วทำงานทดสอบที่ครอบคลุมมากขึ้น ตรวจสอบให้แน่ใจว่าการสื่อสารแบบอนุกรมใช้งานได้ตรวจสอบให้แน่ใจว่าการรวมอนุกรมกับ UI ใช้งานได้ตรวจสอบการรวมอนุกรมกับฐานข้อมูล ฯลฯ analog_read_speed pde และ py แสดงพื้นฐานของสิ่งนี้ (ดูลิงค์ github ด้านบน) ในที่สุดเราจะเปิดแหล่งที่มาของโครงการทั้งหมดดังนั้นโปรดติดตาม :)
— toddstavish

6

โปรแกรมนี้ช่วยให้การทำงานโดยอัตโนมัติของการทดสอบหน่วย Arduino หลาย กระบวนการทดสอบเริ่มต้นบนพีซี แต่การทดสอบทำงานบนฮาร์ดแวร์ Arduino ที่แท้จริง โดยทั่วไปแล้วชุดการทดสอบหนึ่งชุดจะใช้ในการทดสอบหนึ่งไลบรารี Arduino (นี้

Arduino Forum: 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 ที่มีรหัสการทดสอบหน่วย
  • การทดสอบหน่วยทำงานบนบอร์ด Arduino
  • ผลการทดสอบจะถูกพิมพ์ผ่านพอร์ตอนุกรมและวิเคราะห์โดยสคริปต์ Python
  • สคริปต์เริ่มการทดสอบถัดไปโดยทำซ้ำขั้นตอนข้างต้นสำหรับการทดสอบทั้งหมดที่ร้องขอในไฟล์กำหนดค่า
  • สคริปต์พิมพ์ข้อมูลสรุปที่แสดงภาพรวมของการทดสอบที่ล้มเหลว / ผ่านทั้งหมดในการทดสอบที่สมบูรณ์

5

แยกรหัสเฉพาะฮาร์ดแวร์ออกหรือแยกออกจากส่วนที่เหลือเพื่อให้คุณสามารถทดสอบและดีบัก "ส่วนที่เหลือ" ที่ใหญ่กว่าบนแพลตฟอร์มใด ๆ ที่คุณมีเครื่องมือที่ดีและสิ่งที่คุณคุ้นเคยที่สุด

โดยพื้นฐานแล้วพยายามสร้างรหัสสุดท้ายให้มากที่สุดจากบล็อคหน่วยความจำที่เป็นที่รู้จักมากที่สุด งานเฉพาะฮาร์ดแวร์ที่เหลือจะง่ายขึ้นและเร็วขึ้น คุณสามารถเสร็จสิ้นได้โดยใช้อีมูเลเตอร์และ / หรืออุปกรณ์จำลองที่มีอยู่ด้วยตัวคุณเอง และแน่นอนคุณจะต้องทดสอบของจริง ขึ้นอยู่กับสถานการณ์ที่อาจหรือไม่อาจจะเป็นไปโดยอัตโนมัติได้ดี (เช่นใครหรือสิ่งที่จะกดปุ่มและให้อินพุตอื่น ๆ ใครหรือสิ่งที่จะสังเกตและตีความตัวชี้วัดและการส่งออกต่าง ๆ ?)



5

ฉันใช้Searduinoเมื่อเขียนรหัส Arduino Searduino เป็นเครื่องมือจำลอง Arduino และสภาพแวดล้อมการพัฒนา (Makefiles, C code ... ) ที่ทำให้การแฮ็กใน C / C ++ ง่ายขึ้นโดยใช้โปรแกรมแก้ไขที่คุณชื่นชอบ คุณสามารถนำเข้าภาพร่าง Arduino และเรียกใช้งานได้ในโปรแกรมจำลอง

สกรีนช็อตของ Searduino 0.8: http://searduino.files.wordpress.com/2014/01/jearduino-0-8.png

Searduino 0.9 จะออกวางจำหน่ายและวิดีโอจะถูกบันทึกทันทีที่การทดสอบครั้งสุดท้ายเสร็จสิ้น .... ในหนึ่งหรือสองวัน

การทดสอบตัวจำลองไม่ได้เป็นการพิจารณาที่แท้จริง แต่มันช่วยฉันได้มากในการค้นหาความผิดพลาดที่โง่ / ตรรกะ (ลืมที่จะทำpinMode(xx, OUTPUT)ฯลฯ )

BTW: ฉันเป็นหนึ่งในผู้พัฒนา Searduino


5

ฉันสร้างขึ้นarduino_ciเพื่อจุดประสงค์นี้ แม้ว่าจะ จำกัด เฉพาะการทดสอบไลบรารี Arduino (และไม่ใช่สเก็ตช์แบบสแตนด์อโลน) แต่ก็ช่วยให้การทดสอบหน่วยสามารถใช้งานได้ทั้งในพื้นที่หรือบนระบบ CI (เช่น Travis CI หรือ Appveyor)

พิจารณาห้องสมุดที่ง่ายมากในไดเรกทอรี Arduino ห้องสมุดของคุณเรียกว่าDoSomethingด้วยdo-something.cpp:

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

int doSomething(void) {
  return 4;
};

คุณจะทดสอบหน่วยดังต่อไปนี้ (ด้วยไฟล์ทดสอบที่เรียกว่า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 แมทธิวเมอร์ด็ ว่าเขาอ้างถึงในคำตอบของเขา

ดูReference.mdสำหรับข้อมูลเพิ่มเติมเกี่ยวกับการทดสอบหน่วย I / O พินนาฬิกาพอร์ตอนุกรม ฯลฯ

การทดสอบหน่วยเหล่านี้รวบรวมและเรียกใช้โดยใช้สคริปต์ที่มีอยู่ในอัญมณีทับทิม สำหรับตัวอย่างวิธีตั้งค่าดูREADME.mdหรือเพียงคัดลอกจากหนึ่งในตัวอย่างเหล่านี้:


มันดูน่าสนใจ แต่ฉันไม่แน่ใจว่ามันเป็นการทดสอบรหัส Arduino อย่างถูกต้อง จากผลลัพธ์ที่คุณโพสต์มันรวบรวมสถาปัตยกรรม x86_64 ซึ่งแน่นอนว่าไม่ได้ใช้สำหรับ Arduino ที่สามารถแนะนำข้อบกพร่องที่เกิดจากความขัดแย้งระหว่างการใช้งานประเภท
— Cerin

ข้อผิดพลาดประเภทนั้นเป็นไปได้อย่างแน่นอน คุณมีตัวอย่างที่ฉันสามารถใช้สำหรับกรณีทดสอบหรือไม่
— เอียน

3

มีโครงการที่เรียกว่าncoreซึ่งให้บริการแกนกลางสำหรับ Arduino และช่วยให้คุณสามารถเขียนการทดสอบสำหรับรหัส Arduino

จากคำอธิบายโครงการ

แกนประมวลผลดั้งเดิมช่วยให้คุณสามารถรวบรวมและเรียกใช้ภาพร่าง Arduino บนพีซีโดยทั่วไปโดยไม่มีการดัดแปลง มันมีฟังก์ชั่น Arduino มาตรฐานรุ่นเนทีฟและตัวคั่นบรรทัดคำสั่งเพื่อให้อินพุตกับร่างของคุณซึ่งโดยปกติจะมาจากฮาร์ดแวร์เอง

นอกจากนี้ในส่วน"ฉันต้องใช้อะไรบ้าง" ส่วน

หากคุณต้องการที่จะสร้างการทดสอบคุณจะต้อง cxxtest จาก http://cxxtest.tigris.org NCORE ได้รับการทดสอบด้วย cxxtest 3.10.1


นี่เป็นโครงการที่น่าสนใจ น่าเสียดายที่ตอนนี้ดูเหมือนตายแล้วเนื่องจากไม่มีความคืบหน้าเป็นเวลา 6 ปี
— Cerin

2

หากคุณต้องการรหัสทดสอบหน่วยนอก MCU (บนเดสก์ท็อป) ให้ตรวจสอบ libcheck: https://libcheck.github.io/check/

ฉันใช้มันเพื่อทดสอบโค้ดฝังตัวของตัวเองสองสามครั้ง มันเป็นกรอบที่แข็งแกร่ง


ข้อเสียเพียงอย่างเดียวคือสิ่งนี้ไม่รองรับ g ++ ซึ่งทำให้ไร้ประโยชน์สำหรับการทดสอบไลบรารี Arduino ส่วนใหญ่ที่ใช้คุณสมบัติ C ++
— Cerin

1

คุณสามารถใช้emulare - คุณสามารถลากและวางไมโครคอนโทรลเลอร์บนไดอะแกรมและรันโค้ดของคุณใน Eclipse เอกสารในเว็บไซต์บอกวิธีการตั้งค่า


1

ใช้ Proteus VSM กับห้องสมุด Arduino เพื่อดีบักรหัสของคุณหรือเพื่อทดสอบ

มันเป็นวิธีปฏิบัติที่ดีที่สุดก่อนที่จะได้รับรหัสของคุณออนบอร์ด แต่ต้องแน่ใจว่ามีการกำหนดเวลาเพราะการจำลองไม่ได้ทำงานแบบเรียลไทม์ขณะที่พวกเขาทำงานบนกระดาน


1

ลองจำลองวงจร Autodesk ช่วยให้สามารถทดสอบรหัส Arduino และวงจรกับส่วนประกอบฮาร์ดแวร์อื่น ๆ อีกมากมาย


0

ใน Arduino พื้นฐานเขียนด้วย C และ C ++ แม้แต่ไลบรารีของ arduino ก็ถูกเขียนใน C และ C ++ ดังนั้นในแง่ง่าย ๆ เพียงจัดการรหัสเป็น C และ C ++ และลองทำการทดสอบหน่วย ที่นี่โดยคำว่า "จัดการ" ฉันหมายความว่าคุณจะเปลี่ยนไวยากรณ์พื้นฐานทั้งหมดเช่น serial.println เพื่อ sysout, pinmode เพื่อ varaibles, void loop เป็น while () วนที่แตกใน keystock หรือหลังการทำซ้ำบางอย่าง

ฉันรู้ว่านี่เป็นกระบวนการที่ใช้เวลานานและไม่ได้ส่งตรงไปถึงประสบการณ์ส่วนตัวของฉันเมื่อคุณได้ทำสิ่งนี้จะกลายเป็นความน่าเชื่อถือมากขึ้น

-Nandha_Frost


0

ในกรณีที่คุณมีความสนใจในการเรียกใช้ร่าง INO และเช็คเอาท์เอาท์พุทแบบอนุกรมฉันมีการใช้งานของมันในโครงการArduino NMEA checksumของฉัน

สคริปต์ต่อไปนี้ใช้ไฟล์และใช้ Arduino CLI เพื่อรวบรวมเป็นไฟล์ HEX ซึ่งโหลดไปยัง SimAVR ซึ่งจะทำการประเมินและพิมพ์เอาต์พุตอนุกรม เนื่องจากโปรแกรม Arduino ทั้งหมดทำงานตลอดไปโดยที่ไม่มีตัวเลือกในการฆ่าตัวตาย ( exit(0)ไม่ทำงาน) ฉันปล่อยให้ร่างทำงานสองสามวินาทีจากนั้นจึงเอาท์พุทที่บันทึกไว้ด้วยเอาต์พุตที่คาดไว้

ดาวน์โหลดและแยก Arduino CLI (ในกรณีนี้เวอร์ชั่น 0.5.0 - ล่าสุดในขณะที่เขียน):

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

ตอนนี้คุณสามารถอัพเดตดัชนีและติดตั้งคอร์ที่เหมาะสม:

./arduino-cli core update-index
./arduino-cli core install arduino:avr

สมมติว่าชื่อสเก็ตช์ของคุณnmea-checksum.inoได้รับ ELF และ HEX ให้เรียกใช้:

./arduino-cli compile -b arduino:avr:uno nmea-checksum.ino

ถัดไป SimAVR เพื่อเรียกใช้ HEX (หรือเอลฟ์) - ฉันสร้างจากแหล่งที่มาเพราะรุ่นล่าสุดไม่ทำงานสำหรับฉัน:

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

การรวบรวมที่ประสบความสำเร็จจะให้คุณsimavr/run_avrซึ่งคุณสามารถใช้ในการเรียกใช้ร่าง อย่างที่ฉันบอกไปtimeoutไม่อย่างนั้นมันจะไม่มีวันยุติ:

cd simavr
timeout 10 ./run_avr -m atmega168 -f 16000000 ../../nmea-checksum.ino.arduino.avr.uno.elf &> nmea-checksum.ino.clog || true

ไฟล์ที่สร้างขึ้นจะมีอักขระควบคุมรหัสสี ANSI ล้อมรอบเอาต์พุตอนุกรมเพื่อกำจัดสิ่งเหล่านี้:

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

ตอนนี้สิ่งที่คุณต้องทำคือการเปรียบเทียบไฟล์นี้กับไฟล์ที่รู้จักกันดี:

diff nmea-checksum.ino.log ../../nmea-checksum.ino.test

หากไม่มีความแตกต่างdiffจะออกด้วยรหัส 0 มิฉะนั้นสคริปต์จะล้มเหลว

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.