ฉันจะทดสอบรหัส 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.