Ogólnie, zgadzam się z odpowiedzią Wesa - znacznie trudniej będzie dodać testy kodu, który nie jest napisany z myślą o testach. Nie ma nic nieodłącznego w C, co uniemożliwia sprawdzenie - ale ponieważ C nie zmusza cię do pisania w konkretnym stylu, bardzo łatwo jest napisać kod C, który jest trudny do przetestowania.
Moim zdaniem, pisanie kodu z myślą o testach zachęci krótsze funkcje, z kilkoma argumentami, które pomogą złagodzić ból w przykładach.
Najpierw należy wybrać ramy testowania jednostkowego. Istnieje wiele przykładów w this question (choć niestety wiele z nich to framework C++ - odradzam używanie C++ do testowania C).
Ja osobiście używam TestDept, ponieważ jest łatwy w użyciu, lekki i umożliwia krępowanie. Jednak nie sądzę, by był on jeszcze bardzo szeroko wykorzystywany. Jeśli szukasz bardziej popularnej architektury, wiele osób poleca Check - co jest wspaniałe, jeśli używasz automake.
Oto kilka konkretnych odpowiedzi dla swoich przypadków użycia:
Uboczny wokół dużego „kontekście” struct wskaźnik
W tym przypadku można zbudować instancję struct z warunki wstępne zostały ustawione ręcznie, a następnie sprawdź status struktury po uruchomieniu funkcji. Dzięki krótkim funkcjom każdy test będzie dość prosty.
Nie łatwy sposób testować na niepowodzenie funkcji zależnych
Myślę, że to jedna z największych przeszkód z testów jednostkowych C miałem sukces przy użyciu TestDept, który pozwala uruchomić czas odgałęzienie funkcji zależnych. To świetnie nadaje się do zerwania ściśle powiązanego kodu. Oto przykład z ich dokumentacji:
void test_stringify_cannot_malloc_returns_sane_result() {
replace_function(&malloc, &always_failing_malloc);
char *h = stringify('h');
assert_string_equals("cannot_stringify", h);
}
W zależności od docelowego środowiska może to dla ciebie działać lub nie. Aby uzyskać więcej informacji, patrz their documentation.
Funkcje z wieloma parametrami
to prawdopodobnie nie jest to odpowiedź szukasz, ale chciałbym po prostu rozbić je na mniejsze funkcji przy mniejszej liczbie parametrów. O wiele łatwiejsze do przetestowania.
statyczne lub ukryte funkcje
to nie jest super czysty, ale ja testowałem funkcje statyczne poprzez włączenie pliku źródłowego bezpośrednio, umożliwiając połączenia funkcji statycznych. W połączeniu z TestDeptem do usuwania wszystkiego, czego nie ma w teście, działa to całkiem dobrze.
#include "implementation.c"
/* Now I can call foo(), defined static in implementation.c */
dużo kodu C jest starszy kod z kilku testów - w tych przypadkach, to na ogół łatwiej dodać testy integracyjne sprawdzające dużych części kodu pierwsze, zamiast drobno ziarnistych testów jednostkowych . Pozwala to na rozpoczęcie refaktoryzacji kodu pod testem integracyjnym do stanu testowalnego przez jednostkę - choć może, ale nie musi być warta inwestycji, w zależności od twojej sytuacji.Oczywiście będziesz chciał dodać testy jednostek do każdego nowego kodu napisanego w tym okresie, więc dobrym rozwiązaniem jest posiadanie solidnego szkieletu i wczesnego uruchamiania.
Jeśli jesteś jest działający ze starszym kodem, this book (Efektywna praca ze starszym kodem autorstwa Michaela Feathersa) to świetna dalsza lektura.
[Możliwe duplikaty] (http://stackoverflow.com/questions/65820/unit-testing-c-code), jeśli nie tylko powiązane. – ajp15243
@ ajp15243: Mniej mnie interesuje struktura lub narzędzie używane podczas testów jednostkowych. Raczej interesują mnie sposoby pisania testu na kod C, który jest wysoce zależny lub używa wspólnych idiomów C, takich jak struktura 'global_context_t', która jest przekazywana. – MarkP
Cóż, mógłbym edytować "duplikat", gdybym mógł w tym momencie. Pomyślałem, że możesz przynajmniej znaleźć frameworki pomocne, ale no cóż: /. – ajp15243