it-swarm.asia

Gömülü C geliştiricileri için iyi birim testi örnekleri

Önümüzdeki hafta bölümümle birim testi ve test odaklı geliştirme hakkında bir konuşma yapacağım. Bunun bir parçası olarak, son zamanlarda yazdığım bazı kodlardan bazı gerçek dünya örneklerini göstereceğim, ancak konuşmada yazacağım bazı çok basit örnekleri de göstermek istiyorum.

Web'de iyi örnekler için arama yaptım, ancak özellikle geliştirme alanımız için geçerli olanları bulmakta zorlanıyorum. Yazdığımız yazılımların neredeyse tamamı, küçük mikrodenetleyiciler üzerinde çalışan, gömülü kontrol sistemleridir. 'Alt' katmandan uzak kaldığınız sürece birim testine kolayca uygulanabilen bir çok C kodu var (hedefin kendisinden ziyade PC'de birim testinden bahsedeceğim): doğrudan konuşan şeyler mikrodenetleyici çevre birimlerine. Bununla birlikte, bulduğum örneklerin çoğu, dize işlemeye (örneğin, mükemmel Dive Into Python Romen rakamları örneği) dayalı olma eğilimindedir ve neredeyse hiç dizeleri kullanamadığımız için bu gerçekten uygun değildir ( kodumuzun genellikle kullandığı tek kütüphane işlevleri hakkında memcpy, memcmp ve memset olduğundan, strcat veya normal ifadelere dayanan bir şey tam olarak doğru değildir) .

Öyleyse, soru üzerine: lütfen canlı bir oturumda birim testini göstermek için kullanabileceğim bazı işlev örnekleri sunabilir miyiz? (Değişime tabi) düşünceme göre iyi bir cevap muhtemelen şöyle olacaktır:

  • Herkesin (sadece arada sırada kod yazanlar bile) anlayabileceği kadar basit bir işlev;
  • Anlamsız görünmeyen bir işlev (yani, parite veya CRC'yi çalışmak muhtemelen iki sayıyı bir araya getiren ve rastgele bir sabit ekleyen bir işlevden daha iyidir);
  • Bir odanın önüne yazmak için yeterince kısa bir işlev (hataları azaltmak için Vim'in birçok panosundan yararlanabilirim ...);
  • Sayıları, dizileri, işaretçileri veya yapıları parametre olarak alan ve dizeleri işlemek yerine benzer bir şey döndüren bir işlev;
  • Basit bir hata içeren bir işlev (ör. > ziyade >=) çoğu durumda yine de işe yarayacak ancak belirli bir Edge vakasıyla kırılacak: bu, bir birim testi ile tanımlanması ve düzeltilmesi kolaydır.

Düşüncesi olan var mı?

Muhtemelen alakalı olmasa da, testlerin kendileri muhtemelen Google Test Çerçevesi kullanılarak C++ ile yazılır: tüm başlıklarımızda zaten #ifdef __cplusplus extern "C" { onların etrafına sarıcı; bu şimdiye kadar yaptığım testlerle iyi sonuç verdi.

21
DrAl

İşte len bayt üzerinde bir sağlama toplamı oluşturması gereken basit bir işlev.

int checksum(void *p, int len)
{
    int accum = 0;
    unsigned char* pp = (unsigned char*)p;
    int i;
    for (i = 0; i <= len; i++)
    {
        accum += *pp++;
    }
    return accum;
}

Bir çit direği hatası var: for ifadesinde, test i < len.

Eğlenceli olan, eğer böyle bir metin dizesine uygularsanız ...

char *myString = "foo";
int testval = checksum(myString, strlen(myString));

"doğru cevabı" alacaksın! Bunun nedeni, sağlama toplamı alınan ekstra baytın sıfır dize sonlandırıcısı olmasıdır. Böylece bu sağlama toplamı işlevini koda koyabilir ve hatta onunla birlikte gönderebilir ve hiçbir zaman bir sorun fark edemezsiniz - yani, metin dizelerinden başka bir şeye uygulamaya başlayıncaya kadar.

İşte bu hatayı işaretleyecek basit bir birim testi (çoğu zaman ... :-)

void main()
{
    // Seed the random number generator
    srand(time(NULL));

    // Fill an array with junk bytes
    char buf[1024];
    int i;
    for (i = 0; i < 1024; i++)
    {
        buf[i] = (char)Rand();
    }

    // Put the numbers 0-9 in the first ten bytes
    for (i = 0; i <= 9; i++)
    {
        buf[i] = i;
    }

    // Now, the unit test. The sum of 0 to 9 should
    // be 45. But if buf[10] isn't 0 - which it won't be,
    // 255/256 of the time - this will fail.
    int testval = checksum(buf, 10);
    if (testval == 45)
    {
        printf("Passed!\n");
    }
    else
    {
        printf("Failed! Expected 45, got %d\n", testval);
    }
}
15
Bob Murphy

bubble sort gibi bir sıralama işlevi uygulamaya ne dersiniz? Sıralama işlevi çalıştıktan sonra, ikili arama ile devam edebilirsiniz, bu da birim testi ve TDD'yi tanıtmak için iyidir.

Sıralama ve arama, yanlış anlaşılması kolay karşılaştırmalara bağlıdır. Ayrıca dikkatle yapılması gereken işaretçileri değiştirmeyi de içerir. Her ikisi de hatalara eğilimlidir, bu yüzden karışıklıktan çekinmeyin :)

Birkaç fikir daha:

  • Birim testleri, yeniden düzenleme yaparken çok yardımcı olur. Kabarcık sıralamanız çalıştıktan sonra, qsort gibi daha güçlü bir sıraya dönüştürebilirsiniz ve testler yine de geçmelidir ve yeni sıralama işlevinizin de çalıştığını kanıtlar.
  • Sıralama test etmek kolaydır, sonuç ya sıralanır ya da değildir, bu da onu iyi bir aday yapar.
  • Aynı şey arama için; ya var ya da yok.
  • Sıralama için test yazma, test için ne tür girdilerin kullanılacağı gibi tartışmaları açar (sıfır eleman, rastgele girdi, yinelenen girişler, devasa diziler vb.).
2
Martin Wickman