Une solution d'en-tête simple pour les tests unitaires pour C / C ++.
Just #include "utest.h" dans votre code!
Les plates-formes prises en charge actuelles sont Linux, MacOS et Windows.
Les compilateurs pris en charge actuels sont GCC, Clang, Cl.exe de MSVC et Clang-Cl.exe.
Il fonctionne également avec TCC mais avec une mise en garde: la dernière version du compilateur TCC (version 0.9.27) n'a pas de fonctionnalité à travailler. Assurez-vous d'utiliser un TCC qui est corrigé avec l'extension d'attribut constructeur. Ubuntu et Debian Linux Distros récent expérimentent TCC avec ce correctif déjà inclus. Si vous compilez TCC vous-même, utilisez la version du tronc et cela fonctionnera comme prévu.
Utest.h prend en charge certaines options de ligne de commande:
--help pour publier le message d'aide--filter=<filter> filtrera les cas de test à exécuter (utile pour la réévaluation d'un cas de test incriminé particulier).--list-tests énuméreront les noms de test, un par ligne. Les noms de sortie peuvent être transmis à --filter .--output=<output> publiera un fichier XUnit XML avec les résultats du test (que Jenkins, Travis-Ci et Appveyor peuvent analyser les résultats des tests).--enable-mixed-units permettra à la sortie par test de contenir des unités mixtes (S / MS / US / NS).--random-order[=<seed>] va randomiser l'ordre dans lequel les tests sont effectués. Si l'argument facultatif n'est pas fourni, une graine de départ aléatoire est utilisée. UTEST est une bibliothèque d'en-tête unique pour activer tout le plaisir des tests unitaires en C et C ++. La bibliothèque a été conçue pour fournir une sortie similaire au framework Googlest de Google:
[==========] Running 1 test cases.
[ RUN ] foo.bar
[ OK ] foo.bar (631ns)
[==========] 1 test cases ran.
[ PASSED ] 1 tests.
Dans un fichier C ou C ++, vous devez appeler le macro utest_main:
UTEST_MAIN ()Cela fera appel à usest.h, instanciera tous les cas de test et exécutera le cadre de test unitaire.
Alternativement, si vous souhaitez rédiger votre propre principal et appeler dans ust.h, vous pouvez à la place, en un seul appel C ou C ++:
UTEST_STATE ();Et puis lorsque vous êtes prêt à appeler dans le framework USTEST.H: faites:
int main ( int argc , const char * const argv []) {
// do your own thing
return utest_main ( argc , argv );
}Pour définir un cas de test à exécuter, vous pouvez effectuer ce qui suit;
#include "utest.h"
UTEST ( foo , bar ) {
ASSERT_TRUE ( 1 );
}La macro Utest prend deux paramètres - le premier étant l'ensemble auquel appartient le cas de test, le second étant le nom du test. Cela permet aux tests d'être regroupés pour plus de commodité.
Un testcase fixé est celui dans lequel il y a une structure qui est instanciée qui peut être partagée sur plusieurs cas de test.
struct MyTestFixture {
char c ;
int i ;
float f ;
};
UTEST_F_SETUP ( MyTestFixture ) {
utest_fixture -> c = 'a' ;
utest_fixture -> i = 42 ;
utest_fixture -> f = 3.14f ;
// we can even assert and expect in setup!
ASSERT_EQ ( 42 , utest_fixture -> i );
EXPECT_TRUE (true);
}
UTEST_F_TEARDOWN ( MyTestFixture ) {
// and also assert and expect in teardown!
ASSERT_EQ ( 13 , utest_fixture -> i );
}
UTEST_F ( MyTestFixture , a ) {
utest_fixture -> i = 13 ;
// teardown will succeed because i is 13...
}
UTEST_F ( MyTestFixture , b ) {
utest_fixture -> i = 83 ;
// teardown will fail because i is not 13!
}Certaines choses à noter qui ont été démontrées ci-dessus:
UTEST_F_SETUP et UTEST_F_TEARDOWN - même s'ils ne font rien dans le corps.Parfois, vous voulez utiliser le même luminaire et tester à plusieurs reprises, mais peut-être changer subtilement une variable à l'intérieur. C'est là que les cas de test indexés entrent en jeu.
struct MyTestIndexedFixture {
bool x ;
bool y ;
};
UTEST_I_SETUP ( MyTestIndexedFixture ) {
if ( utest_index < 30 ) {
utest_fixture -> x = utest_index & 1 ;
utest_fixture -> y = ( utest_index + 1 ) & 1 ;
}
}
UTEST_I_TEARDOWN ( MyTestIndexedFixture ) {
EXPECT_LE ( 0 , utest_index );
}
UTEST_I ( MyTestIndexedFixture , a , 2 ) {
ASSERT_TRUE ( utest_fixture -> x | utest_fixture -> y );
}
UTEST_I ( MyTestIndexedFixture , b , 42 ) {
// this will fail when the index is >= 30
ASSERT_TRUE ( utest_fixture -> x | utest_fixture -> y );
}Note:
En correspondant de ce que Go Googlest a, nous fournissons deux variantes de chacune des conditions de vérification des erreurs - affirme et attend. Si une affirmation échoue, le cas de test cessera l'exécution et ust.h continuera le prochain cas de test à exécuter. Si une attente échoue, le reste du cas de test sera toujours exécuté, permettant de réaliser de nouvelles chèques.
Nous fournissons actuellement les macros suivantes à utiliser au sein des uts d'aliments:
Affirme que X évalue à True (par exemple non nul).
UTEST ( foo , bar ) {
int i = 1 ;
ASSERT_TRUE ( i ); // pass!
ASSERT_TRUE ( 42 ); // pass!
ASSERT_TRUE ( 0 ); // fail!
}Affirme que X évalue False (par exemple, zéro).
UTEST ( foo , bar ) {
int i = 0 ;
ASSERT_FALSE ( i ); // pass!
ASSERT_FALSE ( 1 ); // fail!
}Affirme que x et y sont égaux.
UTEST ( foo , bar ) {
int a = 42 ;
int b = 42 ;
ASSERT_EQ ( a , b ); // pass!
ASSERT_EQ ( a , 42 ); // pass!
ASSERT_EQ ( 42 , b ); // pass!
ASSERT_EQ ( 42 , 42 ); // pass!
ASSERT_EQ ( a , b + 1 ); // fail!
}Affirme que X et Y ne sont pas égaux.
UTEST ( foo , bar ) {
int a = 42 ;
int b = 13 ;
ASSERT_NE ( a , b ); // pass!
ASSERT_NE ( a , 27 ); // pass!
ASSERT_NE ( 69 , b ); // pass!
ASSERT_NE ( 42 , 13 ); // pass!
ASSERT_NE ( a , 42 ); // fail!
}Affirme que x est inférieur à y.
UTEST ( foo , bar ) {
int a = 13 ;
int b = 42 ;
ASSERT_LT ( a , b ); // pass!
ASSERT_LT ( a , 27 ); // pass!
ASSERT_LT ( 27 , b ); // pass!
ASSERT_LT ( 13 , 42 ); // pass!
ASSERT_LT ( b , a ); // fail!
}Affirme que x est inférieur ou égal à y.
UTEST ( foo , bar ) {
int a = 13 ;
int b = 42 ;
ASSERT_LE ( a , b ); // pass!
ASSERT_LE ( a , 27 ); // pass!
ASSERT_LE ( a , 13 ); // pass!
ASSERT_LE ( 27 , b ); // pass!
ASSERT_LE ( 42 , b ); // pass!
ASSERT_LE ( 13 , 13 ); // pass!
ASSERT_LE ( 13 , 42 ); // pass!
ASSERT_LE ( b , a ); // fail!
}Affirme que x est supérieur à y.
UTEST ( foo , bar ) {
int a = 42 ;
int b = 13 ;
ASSERT_GT ( a , b ); // pass!
ASSERT_GT ( a , 27 ); // pass!
ASSERT_GT ( 27 , b ); // pass!
ASSERT_GT ( 42 , 13 ); // pass!
ASSERT_GT ( b , a ); // fail!
}Affirme que x est supérieur ou égal à y.
UTEST ( foo , bar ) {
int a = 42 ;
int b = 13 ;
ASSERT_GE ( a , b ); // pass!
ASSERT_GE ( a , 27 ); // pass!
ASSERT_GE ( a , 13 ); // pass!
ASSERT_GE ( 27 , b ); // pass!
ASSERT_GE ( 42 , b ); // pass!
ASSERT_GE ( 13 , 13 ); // pass!
ASSERT_GE ( 42 , 13 ); // pass!
ASSERT_GE ( b , a ); // fail!
}Affirme que les chaînes X et Y sont égales.
UTEST ( foo , bar ) {
char * a = "foo" ;
char * b = "bar" ;
ASSERT_STREQ ( a , a ); // pass!
ASSERT_STREQ ( b , b ); // pass!
ASSERT_STREQ ( a , b ); // fail!
}Affirme que les chaînes X et Y ne sont pas égales.
UTEST ( foo , bar ) {
char * a = "foo" ;
char * b = "bar" ;
ASSERT_STRNE ( a , b ); // pass!
ASSERT_STRNE ( a , a ); // fail!
}Affirme que les chaînes x et y sont égales jusqu'à la longueur de la chaîne x.
UTEST ( foo , bar ) {
char * a = "foobar" ;
char * b = "foo" ;
ASSERT_STRNEQ ( a , a ); // pass!
ASSERT_STRNEQ ( b , b ); // pass!
ASSERT_STRNEQ ( a , b ); // pass!
}Affirme que les chaînes x et y ne sont pas égales jusqu'à la longueur de la chaîne x.
UTEST ( foo , bar ) {
char * a = "foobar" ;
char * b = "bar" ;
ASSERT_STRNNE ( a , b ); // pass!
ASSERT_STRNNE ( a , a ); // fail!
}Affirme que les valeurs à virgule flottante x et y sont à la distance d'Epsilon les unes des autres.
UTEST ( foo , bar ) {
float a = 42.0f ;
float b = 42.01f ;
ASSERT_NEAR ( a , b , 0.01f ); // pass!
ASSERT_NEAR ( a , b , 0.001f ); // fail!
}Affirme que exception_type sera lancé lorsque le code x sera exécuté.
void foo ( int bar) {
if (bar == 1 )
throw std::range_error;
}
UTEST (foo, bar) {
ASSERT_EXCEPTION ( foo ( 1 ), std::range_error); // pass!
ASSERT_EXCEPTION ( foo ( 2 ), std::range_error); // fail!
ASSERT_EXCEPTION ( foo ( 1 ), std:: exception ); // fail!
}S'attend à ce que X évalue à TRUE (c'est-à-dire non nul).
UTEST ( foo , bar ) {
int i = 1 ;
EXPECT_TRUE ( i ); // pass!
EXPECT_TRUE ( 42 ); // pass!
EXPECT_TRUE ( 0 ); // fail!
}S'attend à ce que X évalue False (c'est-à-dire zéro).
UTEST ( foo , bar ) {
int i = 0 ;
EXPECT_FALSE ( i ); // pass!
EXPECT_FALSE ( 1 ); // fail!
}S'attend à ce que X et Y soient égaux.
UTEST ( foo , bar ) {
int a = 42 ;
int b = 42 ;
EXPECT_EQ ( a , b ); // pass!
EXPECT_EQ ( a , 42 ); // pass!
EXPECT_EQ ( 42 , b ); // pass!
EXPECT_EQ ( 42 , 42 ); // pass!
EXPECT_EQ ( a , b + 1 ); // fail!
}S'attend à ce que X et Y ne soient pas égaux.
UTEST ( foo , bar ) {
int a = 42 ;
int b = 13 ;
EXPECT_NE ( a , b ); // pass!
EXPECT_NE ( a , 27 ); // pass!
EXPECT_NE ( 69 , b ); // pass!
EXPECT_NE ( 42 , 13 ); // pass!
EXPECT_NE ( a , 42 ); // fail!
}S'attend à ce que x soit inférieur à y.
UTEST ( foo , bar ) {
int a = 13 ;
int b = 42 ;
EXPECT_LT ( a , b ); // pass!
EXPECT_LT ( a , 27 ); // pass!
EXPECT_LT ( 27 , b ); // pass!
EXPECT_LT ( 13 , 42 ); // pass!
EXPECT_LT ( b , a ); // fail!
}S'attend à ce que x soit inférieur ou égal à y.
UTEST ( foo , bar ) {
int a = 13 ;
int b = 42 ;
EXPECT_LE ( a , b ); // pass!
EXPECT_LE ( a , 27 ); // pass!
EXPECT_LE ( a , 13 ); // pass!
EXPECT_LE ( 27 , b ); // pass!
EXPECT_LE ( 42 , b ); // pass!
EXPECT_LE ( 13 , 13 ); // pass!
EXPECT_LE ( 13 , 42 ); // pass!
EXPECT_LE ( b , a ); // fail!
}S'attend à ce que x soit supérieur à y.
UTEST ( foo , bar ) {
int a = 42 ;
int b = 13 ;
EXPECT_GT ( a , b ); // pass!
EXPECT_GT ( a , 27 ); // pass!
EXPECT_GT ( 27 , b ); // pass!
EXPECT_GT ( 42 , 13 ); // pass!
EXPECT_GT ( b , a ); // fail!
}Attend que x soit supérieur ou égal à y.
UTEST ( foo , bar ) {
int a = 42 ;
int b = 13 ;
EXPECT_GE ( a , b ); // pass!
EXPECT_GE ( a , 27 ); // pass!
EXPECT_GE ( a , 13 ); // pass!
EXPECT_GE ( 27 , b ); // pass!
EXPECT_GE ( 42 , b ); // pass!
EXPECT_GE ( 13 , 13 ); // pass!
EXPECT_GE ( 42 , 13 ); // pass!
EXPECT_GE ( b , a ); // fail!
}S'attend à ce que les chaînes X et Y soient égales.
UTEST ( foo , bar ) {
char * a = "foo" ;
char * b = "bar" ;
EXPECT_STREQ ( a , a ); // pass!
EXPECT_STREQ ( b , b ); // pass!
EXPECT_STREQ ( a , b ); // fail!
}S'attend à ce que les chaînes X et Y ne soient pas égales.
UTEST ( foo , bar ) {
char * a = "foo" ;
char * b = "bar" ;
EXPECT_STRNE ( a , b ); // pass!
EXPECT_STRNE ( a , a ); // fail!
}S'attend à ce que les chaînes X et Y soient égales jusqu'à la longueur de la chaîne x.
UTEST ( foo , bar ) {
char * a = "foobar" ;
char * b = "foo" ;
EXPECT_STRNEQ ( a , a ); // pass!
EXPECT_STRNEQ ( b , b ); // pass!
EXPECT_STRNEQ ( a , b ); // pass!
}S'attend à ce que les chaînes X et Y ne soient pas égales jusqu'à la longueur de la chaîne x.
UTEST ( foo , bar ) {
char * a = "foobar" ;
char * b = "bar" ;
EXPECT_STRNNE ( a , b ); // pass!
EXPECT_STRNNE ( a , a ); // fail!
}S'attend à ce que les valeurs à virgule flottante X et Y soient à la distance d'Epsilon les unes des autres.
UTEST ( foo , bar ) {
float a = 42.0f ;
float b = 42.01f ;
EXPECT_NEAR ( a , b , 0.01f ); // pass!
EXPECT_NEAR ( a , b , 0.001f ); // fail!
}S'attend à ce que exception_type soit lancé lorsque le code X est exécuté.
void foo ( int bar) {
if (bar == 1 )
throw std::range_error;
}
UTEST (foo, bar) {
EXPECT_EXCEPTION ( foo ( 1 ), std::range_error); // pass!
EXPECT_EXCEPTION ( foo ( 2 ), std::range_error); // fail!
EXPECT_EXCEPTION ( foo ( 1 ), std:: exception ); // fail!
}S'attend à ce que exception_type soit lancé avec un message exception_message lorsque le code x est exécuté.
void foo ( int bar) {
if (bar == 1 )
throw std::range_error ( " bad bar " );
}
UTEST (foo, bar) {
EXPECT_EXCEPTION_WITH_MESSAGE ( foo ( 1 ), std::range_error, " bad bar " ); // pass!
EXPECT_EXCEPTION_WITH_MESSAGE ( foo ( 2 ), std::range_error, " bad bar2 " ); // fail!
EXPECT_EXCEPTION_WITH_MESSAGE ( foo ( 1 ), std:: exception , " bad bar " ); // fail!
} Cette macro vous permet de marquer un cas de test comme étant ignoré - par exemple. que le cas de test ne doit pas être exécuté. Le test cessera de fonctionner lorsque vous exécutez la macro, signalera le msg comme raison du sauté et marquez le test comme «sauté» . Ceux-ci seront signalés à la fin de l'exécution avant les échecs, et les cas de test sautés ne feront pas la sortie du processus avec un code non nul.
UTEST ( foo , bar ) {
UTEST_SKIP ( "Need to implement this test!" );
}De plus, pour donner la possibilité d'avoir des messages personnalisés dans les tests de défaut, toutes les macros peuvent être utilisées avec un suffixe appelé "_msg", qui reçoit un paramètre supplémentaire, qui est la chaîne avec le message personnalisé à imprimer en cas de défaillance.
Par exemple:
UTEST ( foo , bar ) {
int i = 1 ;
EXPECT_TRUE_MSG ( i , "custom message" ); // pass!
EXPECT_TRUE_MSG ( 42 , "custom message" ); // pass!
EXPECT_TRUE_MSG ( 0 , "custom message" ); // fail! (with the following output)
} test.cpp:42: Failure
Expected : true
Actual : false
Message : custom message
[ FAILED ] foo.bar (8086ns)
La bibliothèque prend en charge l'affirmation sur n'importe quel type entier, à virgule flottante ou pointeur intégrée.
Ceci est un logiciel gratuit et non encombré publié dans le domaine public.
Tout le monde est libre de copier, de modifier, de publier, d'utiliser, de compiler, de vendre ou de distribuer ce logiciel, soit sous forme de code source, soit en tant que binaire compilé, à quelque fin que ce soit, commercial ou non commercial, et par tous les moyens.
Dans les juridictions qui reconnaissent les lois sur le droit d'auteur, l'auteur ou les auteurs de ce logiciel consacrent tout intérêt au droit d'auteur dans le logiciel au domaine public. Nous faisons ce dévouement au profit du public dans son ensemble et au détriment de nos héritiers et successeurs. Nous avons l'intention de ce dévouement à être un acte manifeste de renoncement à la perpétuité de tous les droits présents et futurs sur ce logiciel en vertu de la loi sur le droit d'auteur.
Le logiciel est fourni "tel quel", sans garantie d'aucune sorte, express ou implicite, y compris, mais sans s'y limiter, les garanties de qualité marchande, d'adéquation à un usage particulier et de non-contrefaçon. En aucun cas, les auteurs ne seront responsables de toute réclamation, dommage ou autre responsabilité, que ce soit dans une action de contrat, de délit ou autre, découlant de, hors du logiciel ou du logiciel ou de l'utilisation ou d'autres transactions du logiciel.
Pour plus d'informations, veuillez consulter http://unlicense.org/