Question Test d'unité C Code [fermé]


J'ai travaillé sur un système embarqué cet été écrit en C. C'était un projet existant pour lequel l'entreprise pour laquelle je travaille avait pris le relais. Je suis devenu assez habitué à écrire des tests unitaires en Java en utilisant JUnit mais je ne savais pas comment écrire des tests unitaires pour du code existant (qui nécessitait un refactoring) ainsi que du nouveau code ajouté au système.

Existe-t-il un moyen de rendre le test C unitaire aussi simple que le test unitaire du code Java avec, par exemple, JUnit? Toute idée qui s'appliquerait spécifiquement au développement intégré (compilation croisée avec la plate-forme arm-linux) serait grandement appréciée.


714


origine


Réponses:


Un cadre de test unitaire en C est Vérifier; une liste de cadres de tests unitaires en C peut être trouvée ici et est reproduit ci-dessous. Selon le nombre de fonctions de bibliothèque standard de votre environnement d'exécution, vous pouvez ou non utiliser l'une de ces fonctions.

AceUnit

AceUnit (Advanced C et Embedded Unit) se présente comme un cadre de test d'unité de code C confortable. Il essaie d'imiter JUnit 4.x et inclut des capacités de type réflexion. AceUnit peut être utilisé dans des environnements de contrainte de ressources, par ex. Le développement de logiciels embarqués, et surtout, il fonctionne bien dans les environnements où vous ne pouvez pas inclure un seul fichier d'en-tête standard et ne peut pas invoquer une seule fonction C standard à partir des bibliothèques ANSI / ISO C. Il a également un port Windows. Il n'utilise pas de fourche pour piéger les signaux, bien que les auteurs aient exprimé leur intérêt à ajouter une telle caractéristique. Voir le AceUnit page d'accueil.

GNU Autounit

Tout à fait dans le même sens que Check, y compris en forçant à exécuter des tests unitaires dans un espace d'adressage séparé (en fait, l'auteur original de Check a emprunté l'idée à GNU Autounit). GNU Autounit utilise largement GLib, ce qui signifie que les liens et certaines options spéciales sont nécessaires, mais cela peut ne pas poser de gros problèmes, surtout si vous utilisez déjà GTK ou GLib. Voir le Page d'accueil de GNU Autounit.

cUnit

Utilise également GLib, mais ne fourche pas pour protéger l'espace d'adressage des tests unitaires.

CUnit

Standard C, avec des plans pour une implémentation de l'interface graphique Win32. Actuellement, n'embrasse pas ou ne protège pas l'espace d'adressage des tests unitaires. Au début du développement. Voir le CUnit page d'accueil.

CuTest

Un framework simple avec juste un fichier .c et un fichier .h que vous déposez dans votre arborescence source. Voir le CuTest page d'accueil.

CppUnit

Le premier framework de test unitaire pour C ++; vous pouvez également l'utiliser pour tester le code C. Il est stable, développé activement et possède une interface graphique. Les principales raisons de ne pas utiliser CppUnit pour C sont d'abord que c'est assez grand, et deuxièmement vous devez écrire vos tests en C ++, ce qui signifie que vous avez besoin d'un compilateur C ++. Si cela ne vous semble pas préoccupant, il vaut vraiment la peine de l'envisager, avec d'autres frameworks de tests unitaires C ++. Voir le Page d'accueil CppUnit.

embUnit

embUnit (Embedded Unit) est un autre cadre de test unitaire pour les systèmes embarqués. Celui-ci semble être remplacé par AceUnit. Page d'accueil de l'unité intégrée.

MinUnit

Un ensemble minimal de macros et c'est tout! Le but est de montrer combien il est facile de tester votre code unitaire. Voir le Page d'accueil de MinUnit.

CUnit pour M. Ando

Une implémentation CUnit qui est relativement nouvelle, et apparemment encore en début de développement. Voir le CUnit pour la page d'accueil de M. Ando.

Cette liste a été mise à jour en mars 2008.

Autres:

CMocka

CMocka est un framework de test pour C avec prise en charge des objets fantaisie. C'est facile à utiliser et à configurer. CMocka page d'accueil officielle.

Critère

Criterion est un framework de tests unitaires C multiplateforme prenant en charge l'enregistrement automatique des tests, les tests paramétrés, les théories, et pouvant être édité en plusieurs formats, notamment TAP et JUnit XML. Chaque test est exécuté dans son propre processus, de sorte que les signaux et les plantages peuvent être signalés ou testés si nécessaire. Voir le Page d'accueil du critère pour plus d'informations.

HWUT

HWUT est un outil général de test d'unité avec un grand support pour C. Il peut aider à créer des Makefiles, générer des cas de test massifs codés dans des tables d'itération minimales, marcher sur des machines à états, générer des C-stubs et plus. L'approche générale est assez unique: les verdicts sont basés sur «bonne stdout / mauvaise stdout». La fonction de comparaison, cependant, est flexible. Ainsi, n'importe quel type de script peut être utilisé pour vérifier. Il peut être appliqué à n'importe quel langage pouvant produire une sortie standard. Voir HWUT page d'accueil

Wikipedia donne une liste détaillée des cadres de tests unitaires C sous Liste des cadres de tests unitaires: C


418



Personnellement, j'aime le Cadre de test Google.

La vraie difficulté dans le test du code C est de casser les dépendances sur les modules externes afin que vous puissiez isoler le code en unités. Cela peut être particulièrement problématique lorsque vous essayez d'obtenir des tests autour du code existant. Dans ce cas, je me trouve souvent en utilisant l'éditeur de liens pour utiliser les fonctions stubs dans les tests.

C'est ce à quoi les gens font référence lorsqu'ils parlent de "couturesEn C, votre seule option est vraiment d'utiliser le pré-processeur ou l'éditeur de liens pour simuler vos dépendances.

Une suite de tests typique dans l'un de mes projets C peut ressembler à ceci:

#include "myimplementationfile.c"
#include <gtest/gtest.h>

// Mock out external dependency on mylogger.o
void Logger_log(...){}

TEST(FactorialTest, Zero) {
    EXPECT_EQ(1, Factorial(0));
}

Notez que vous incluez réellement le fichier C et non le fichier d'en-tête. Cela donne l'avantage d'accéder à tous les membres de données statiques. Ici, je simule mon enregistreur (qui peut être dans logger.o et donne une implémentation vide.) Cela signifie que le fichier de test compile et lie indépendamment du reste de la base de code et s'exécute de manière isolée.

En ce qui concerne la compilation croisée du code, pour que cela fonctionne, vous avez besoin de bonnes installations sur la cible. J'ai fait ceci avec la croix de googletest compilée à Linux sur une architecture de PowerPC. Cela est logique parce que vous avez une coquille complète et OS pour recueillir vos résultats. Pour les environnements moins riches (que je classe comme quelque chose sans un système d'exploitation complet), vous devriez juste construire et exécuter sur l'hôte. Vous devriez le faire de toute façon afin que vous puissiez exécuter les tests automatiquement dans le cadre de la construction.

Je trouve que le test du code C ++ est généralement beaucoup plus facile en raison du fait que le code OO est en général beaucoup moins couplé que procédural (bien sûr cela dépend beaucoup du style de codage). Toujours en C ++, vous pouvez utiliser des astuces telles que l'injection de dépendances et le remplacement de méthodes pour obtenir des liens dans du code qui est autrement encapsulé.

Michael Feathers a un excellent livre sur le test du code existant. Dans un chapitre, il couvre les techniques pour traiter le code non-OO que je recommande fortement.

modifier: J'ai écrit un article de blog sur le code de procédure de test unitaire, avec source disponible sur GitHub.

modifier: Il y a un nouveau livre sorti des programmeurs pragmatiques qui traite spécifiquement des tests unitaires code C qui Je recommande fortement.


139



Minunit est un framework de tests unitaires incroyablement simple. Je l'utilise pour tester le code du microcontrôleur c pour avr.


121



J'utilise actuellement le framework de test unitaire CuTest:

http://cutest.sourceforge.net/

Il est idéal pour les systèmes embarqués car il est très léger et simple. Je n'ai eu aucun problème à le faire fonctionner sur la plate-forme cible aussi bien que sur le bureau. En plus d'écrire les tests unitaires, tout ce qui est requis est:

  • un fichier d'en-tête inclus partout vous appelez les routines CuTest
  • un seul fichier 'C' supplémentaire à compilé / lié dans l'image
  • un code simple ajouté à la main pour mettre en place et appeler les tests unitaires - I il suffit de l'avoir dans une main spéciale () fonction qui est compilée si UNITTEST est défini pendant la construire.

Le système doit prendre en charge un tas et certaines fonctionnalités stdio (ce qui n'est pas le cas de tous les systèmes embarqués). Mais le code est assez simple que vous pourriez probablement travailler dans des alternatives à ces exigences si votre plate-forme ne les a pas.

Avec une utilisation judicieuse des blocs externes "C" {}, il supporte aussi le test C ++.


39



Je dis presque la même chose que ratkok mais si vous avez une torsion intégrée aux tests unitaires alors ...

Unité - Cadre hautement recommandé pour le test unitaire du code C.

Les exemples dans le livre qui est mentionné dans ce fil TDD pour C intégré sont écrits en utilisant Unity (et CppUTest).


33



Vous pourriez aussi vouloir jeter un coup d'oeil à libtap, un framework de test en C qui produit le protocole TAP (Test Anything Protocol) et s'intègre ainsi parfaitement à une variété d'outils issus de cette technologie. Il est principalement utilisé dans le monde de la langue dynamique, mais il est facile à utiliser et devient très populaire.

Un exemple:

#include <tap.h>

int main () {
    plan(5);

    ok(3 == 3);
    is("fnord", "eek", "two different strings not that way?");
    ok(3 <= 8732, "%d <= %d", 3, 8732);
    like("fnord", "f(yes|no)r*[a-f]$");
    cmp_ok(3, ">=", 10);

    done_testing();
}

29



Il y a un cadre de test unitaire élégant pour C avec un support pour les objets simulés appelé cmocka. Il ne nécessite que la bibliothèque C standard, fonctionne sur une gamme de plates-formes informatiques (y compris embarqué) et avec différents compilateurs.

Il prend également en charge différents formats de sortie de message, tels que les sous-unités, le protocole Test Anything et les rapports XML jUnit.

cmocka a été créé pour fonctionner également sur les plates-formes embarquées et a également un support Windows.

Un test simple ressemble à ceci:

#include <stdarg.h>
#include <stddef.h>
#include <setjmp.h>
#include <cmocka.h>

/* A test case that does nothing and succeeds. */
static void null_test_success(void **state) {
    (void) state; /* unused */
}

int main(void) {
    const struct CMUnitTest tests[] = {
        cmocka_unit_test(null_test_success),
    };
    return cmocka_run_group_tests(tests, NULL, NULL);
}

le API est entièrement documenté et plusieurs exemples font partie du code source.

Pour commencer avec cmocka, vous devriez lire l'article sur LWN.net: Tests unitaires avec des objets simulés en C

cmocka 1.0 est sorti en février 2015.


24



Je n'ai pas testé loin une application C héritée avant que je commence à chercher un moyen de simuler des fonctions. J'avais besoin de faux bâtons pour isoler le fichier C que je veux tester des autres. J'ai essayé cmock et je pense que je vais l'adopter.

Cmock analyse les fichiers d'en-tête et génère des fonctions fantaisie en fonction des prototypes trouvés. Mocks vous permettra de tester un fichier C en parfaite isolation. Tout ce que vous avez à faire est de lier votre fichier de test avec des faux à la place de vos vrais fichiers objets.

Un autre avantage de cmock est qu'il va valider les paramètres passés aux fonctions mockées, et il vous permettra de spécifier quelle valeur de retour les mock devraient fournir. Ceci est très utile pour tester différents flux d'exécution dans vos fonctions.

Les tests consistent en des fonctions typiques testA (), testB () dans lesquelles vous construisez des attentes, appelez des fonctions pour tester et vérifier des affirmations.

La dernière étape consiste à générer un coureur pour vos tests avec unité. Cmock est lié au cadre de test de l'unité. L'unité est aussi facile à apprendre que n'importe quel autre cadre de test unitaire.

Ça vaut le coup d'essayer et assez facile à comprendre:

http://sourceforge.net/apps/trac/cmock/wiki

Mise à jour 1

Un autre cadre que j'étudie est Cmockery.

http://code.google.com/p/cmockery/

C'est un cadre C pur qui supporte les tests unitaires et les moqueurs. Il n'a aucune dépendance sur ruby ​​(contrairement à Cmock) et il a très peu de dépendance sur les libs externes.

Il faut un peu plus de travail manuel pour paramétrer les mocks car il ne génère pas de code. Cela ne représente pas beaucoup de travail pour un projet existant puisque les prototypes ne changeront pas beaucoup: une fois que vous aurez vos mock, vous n'aurez pas besoin de les changer pendant un moment (c'est mon cas). La frappe supplémentaire fournit un contrôle complet des faux-semblants. S'il y a quelque chose que vous n'aimez pas, vous changez simplement votre maquette.

Pas besoin d'un coureur d'essai spécial. Vous n'avez besoin que de créer un tableau de tests et de le passer à une fonction run_tests. Un peu plus de travail manuel ici aussi mais j'aime bien l'idée d'un cadre autonome autonome.

De plus, il contient quelques trucs astucieux que je ne connaissais pas.

Dans l'ensemble, Cmockery a besoin d'un peu plus de compréhension des simulacres pour commencer. Des exemples devraient vous aider à surmonter cela. On dirait qu'il peut faire le travail avec une mécanique plus simple.


19