Arduino Cihazında veya Emülatöründe Birim Testleri Yapmayın
Mikrodenetleyici Cihaz / Emülatör / Sim tabanlı testlere karşı dava
Birim testin ne anlama geldiği hakkında çok fazla tartışma var ve burada bununla ilgili bir tartışma yapmaya çalışmıyorum. Bu mesaj olduğunu değil
önlemek için söylüyorum tüm nihai hedef donanım üzerinde pratik test. Hedef donanımınızı en sıradan ve sık testlerden kaldırarak geliştirme geri bildirim döngünüzü optimize etme konusunda bir noktaya değinmeye çalışıyorum. Test edilen birimlerin tüm projeden çok daha küçük olduğu varsayılmaktadır.
Birim testinin amacı, kendi kodunuzun kalitesini test etmektir. Birim testleri genellikle kontrolünüz dışındaki faktörlerin işlevselliğini asla test etmemelidir.
Bunu şu şekilde düşünün: Arduino kütüphanesinin, mikrodenetleyici donanımının veya bir emülatörün işlevselliğini test etseniz bile, bu tür test sonuçlarının size kendi çalışmanızın kalitesi hakkında bir şey söylemesi kesinlikle imkansızdır . Bu nedenle, hedef cihazda (veya emülatörde) çalışmayan birim testleri yazmak çok daha değerli ve etkilidir.
Hedef donanımınız üzerinde sık yapılan testlerin acı verici yavaş bir döngüsü vardır:
- Kodunuzu değiştirin
- Derleyin ve Arduino cihazına yükleyin
- Davranışını gözlemleyin ve olmadığını tahmin senin kod beklediğiniz yapıyor
- Tekrar et
Adım 3, özellikle seri bağlantı noktası üzerinden tanılama mesajları almayı bekliyorsanız, ancak projenizin Arduino'nun tek donanım seri bağlantı noktasını kullanması gerekiyorsa özellikle kötüdür. SoftwareSerial kütüphanesinin yardımcı olabileceğini düşünüyorsanız, bunu yapmanın aynı anda diğer sinyalleri üretmek gibi doğru zamanlama gerektiren herhangi bir işlevselliği bozacağını bilmelisiniz. Bu sorun benim başıma geldi.
Yine, çiziminizi bir emülatör kullanarak test edecekseniz ve zaman açısından kritik rutinleriniz gerçek Arduino'ya yüklenene kadar mükemmel bir şekilde çalıştıysa, öğreneceğiniz tek ders emülatörün kusurlu olması ve bunu hala bilmesidir. kendi işinizin kalitesi hakkında hiçbir şey ortaya çıkarmaz .
O aygıt veya emülatörünüzde testine saçma olursa, ne olmalı yapmam?
Muhtemelen Arduino projenizde çalışmak için bir bilgisayar kullanıyorsunuz. Bu bilgisayar mikrodenetleyiciden daha hızlı büyüklük sırasıdır. Bilgisayarınızda oluşturmak ve çalıştırmak için testleri yazın .
Unutmayın, Arduino kütüphanesinin ve mikrodenetleyicinin davranışının ya doğru ya da en azından tutarlı bir şekilde yanlış olduğu varsayılmalıdır .
Testleriniz beklentilerinizin aksine çıktı ürettiğinde, muhtemelen kodunuzda test edilmiş bir kusur vardır. Test çıktınız beklentilerinize uyuyorsa, ancak Arduino'ya yüklediğinizde program doğru davranmıyorsa, testlerinizin yanlış varsayımlara dayandığını ve muhtemelen hatalı bir testiniz olduğunu biliyorsunuzdur. Her iki durumda da, bir sonraki kod değişikliğinizin ne olması gerektiği konusunda size gerçek bilgiler verilecektir. Geribildiriminiz kalitesi "dan artırıldı şey için bozuldu" "Bu özel kod bozuldu" .
Bilgisayarınızda Test Oluşturma ve Çalıştırma
Yapmanız gereken ilk şey test hedeflerinizi belirlemektir . Kendi kodunuzun hangi bölümlerini test etmek istediğinizi düşünün ve ardından programınızı ayrı parçaları test için izole edebileceğiniz şekilde oluşturduğunuzdan emin olun .
Test etmek istediğiniz parçalar herhangi bir Arduino işlevini çağırırsa, test programınızda maket yedekleri sağlamanız gerekir. Bu göründüğünden çok daha az iş. Maketlerinizin testleriniz için öngörülebilir girdi ve çıktı sağlamaktan başka bir şey yapmasına gerek yoktur.
Test etmek istediğiniz kendi kodunuzun .pde çizimi dışındaki kaynak dosyalarda bulunması gerekir. Endişelenmeyin, çiziminiz, çizimin dışındaki bazı kaynak kodlarıyla bile derlenecektir. Gerçekten aşağı indiğinizde, çizim dosyasında programınızın normal giriş noktasından biraz daha fazlası tanımlanmalıdır.
Geriye kalan tek şey, gerçek testleri yazmak ve en sevdiğiniz C ++ derleyicisini kullanarak derlemek! Bu muhtemelen en iyi gerçek dünya örneği ile gösterilebilir.
Gerçek bir çalışma örneği
Benim evcil projelerden biri bulundu burada PC'de çalıştırmak bazı basit testler vardır. Bu cevap gönderimi için, sadece bazı Arduino kütüphane fonksiyonlarını nasıl taktığımı ve bu maketleri test etmek için yazdığım testleri inceleyeceğim. Bu, daha önce başkalarının kodlarını test etmeme hakkında söylediğim şeylerin aksine değil, çünkü maketleri yazan ben oldum. Modellerimin doğru olduğundan çok emin olmak istedim.
Arduino kütüphanesi tarafından sağlanan bazı destek işlevlerini kopyalayan kodu içeren mock_arduino.cpp kaynağı:
#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);
}
Kodum donanım seri aygıtına ikili veri yazdığında okunabilir çıktı üretmek için aşağıdaki mock-up kullanın.
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;
ve son olarak, gerçek test programı:
#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();
}
Bu yazı yeterince uzun, bu yüzden bazı test senaryolarını görmek için lütfen GitHub'daki projeme bakın. Devam etmekte olan çalışmalarımı master dışındaki dallarda tutuyorum, bu yüzden bu dalları da ekstra testler için kontrol edin.
Kendi hafif test rutinlerimi yazmayı seçtim, ancak CppUnit gibi daha sağlam birim testi çerçeveleri de mevcut.