Ce sont de longues vacances, mais je n'ai pas envie d'avoir un froid d'été, alors je pousse Google Mock dans ma chambre. J'utilise C pour une raison quelconque au travail, j'ai donc résumé comment utiliser Google Mock pour le code C. Cette fois, c'est l'introduction.
Il semble qu'il existe de nombreux articles de ce degré, je vais donc y aller directement. Je pense que ce qui suit sera également utile. https://qiita.com/shohirose/items/30e39949d8bf990b0462
Supposons que vous ayez un code comme celui-ci. (J'omets Inclure, mais je le fais bien)
sub.c
#include "mystr.h"
int test1(const char* str)
{
fprintf(stderr, "test print %s\n", str);
return str_analyze(str, 10);
}
mystr.c
int str_analyze(const char* str, int max)
{
int l;
for (l = 0; l < max; l++) {
if (str[l] == '\0') break;
}
return l;
}
Le code pour tester la valeur de retour de cette fonction test1 ()
serait:
sub_test.cpp
TEST(sub_test, test01)
{
EXPECT_EQ(6, test1(": test"));
}
Pour le moment, ces emplacements et builds sont effectués comme indiqué sur le site ci-dessous. https://techblog.kayac.com/google-test
g++ -std=c++11 test/sub_test.cpp -I. -Isrc -Igoogletest/include -Lgoogletest -lgtest -lgtest_main -lpthread
Si vous faites cela, un fichier ʻa.out` sera généré comme programme de test et vous pourrez exécuter le test.
Si cela reste tel quel, le code source et le code de développement de Google Test seront fusionnés, essayez donc de modifier la disposition comme suit.
|
+- GoogleTest
| + ...
|
+- work
+ sub.c
+ sub.h
+ mystr.c
+ mystr.h
La construction à ce stade peut être effectuée en modifiant légèrement la commande écrite ci-dessus, mais c'est ennuyeux. J'utiliserai donc des scons que j'ai récemment appris au travail. Je l'ai écrit en regardant ce qui suit. [^ 2] https://scons.org/doc/0.97/HTML/scons-user/x628.html
SConstruct
env = Environment()
env.Program(
target='sub_test',
#Vous pouvez déboguer avec gdb si vous n'avez pas besoin d'ajouter une option de débogage
CCFLAGS = '-g',
source = [
"sub.c",
"mystr.c",
"sub_test.cpp",
],
LIBPATH = [
"../googletest/lib",
"../googletest/googlemock/lib",
],
LIBS = [
'libgtest.a',
'libgtest_main.a',
'libgmock.a',
'libgmock_main.a',
'pthread',
],
CPPPATH = [
'.',
'../googletest',
'../googletest/googletest',
'../googletest/googletest/include',
'../googletest/googlemock',
'../googletest/googlemock/include',
],
)
Eh bien, ce n'est pas très bon car les produits intermédiaires sont mélangés avec le code source, mais cette fois c'est ennuyeux, donc c'est pareil.
Le contenu d'ici renvoie à la page suivante en plus du document officiel.
La raison d'utiliser Mock est également expliquée dans la traduction de la documentation officielle.
http://opencv.jp/googlemockdocs/fordummies.html
Dans un programme normal, vous utiliserez une implémentation réelle de cette interface. Pour les tests, nous utiliserons plutôt l'implémentation fictive. Cela permet de vérifier facilement quelle primitive de dessin a été appelée à partir du programme, quels sont les arguments et quel est l'ordre. Les tests écrits de cette manière sont très robustes (ils ne se cassent pas en raison des changements dans l'anticrénelage de la machine), sont faciles à déchiffrer et à maintenir (le but du test est exprimé dans le code plutôt que dans un fichier image). ), Et l'exécution du test est beaucoup plus rapide.
Personnellement, je pense que les contrôles de type boîte blanche, tels que s'ils sont appelés et l'ordre, sont importants pour l'utilisation de Mock.
Maintenant, créons une maquette de str_analyze ()
en tant que module qui rend mystr Mock. Cependant, puisque Google Mock est pour C ++, il ne peut pas être utilisé tel quel pour C.
Cela ne semble pas être écrit sur la page officielle, mais il semble que vous deviez créer une classe d'interface [^ 3] pour utiliser Google Mock. Donc, mystr est C, mais si c'est C ++ ... je vais créer un fichier d'en-tête.
mock/mock_mystr.h
class Mystr {
public:
Mystr(void){}
virtual ~Mystr(void){}
virtual int str_analyze(const char* str, int max) = 0;
};
Continuez à écrire la classe Mock correspondante.
mock/mock_mystr.h
class MockMystr : public Mystr {
public:
MockMystr(){}
~MockMystr(){}
MOCK_METHOD2(str_analyze,
int(const char* str, int max));
};
Bien sûr, vous ne pouvez pas appeler des classes C ++ à partir du code C et il n'est pas bon de réécrire le code que vous testez. Par conséquent, créez une maquette comme indiqué dans la page de référence 2 ci-dessus.
mock/mock_mystr.h
extern MockMystr* mystr_mock;
extern "C" int str_analyze(const char* str, int max)
{
int ret = mystr_mock->str_analyze(str, max);
return ret;
}
Je pense que le «C externe» est généralement nécessaire pour supprimer la mutilation.
Jusqu'à présent, j'ai presque créé un Mock pour la fonction str_analyze ()
que je voulais transformer en un Mock, donc je vais l'utiliser.
Tout d'abord, rendez le corps de str_analyze ()
invisible.
SConstruct
source = [
"sub.c",
- "mystr.c",
+ #"mystr.c",
"sub_test.cpp",
],
Ensuite, ajoutez des références et des paramètres simulés au programme de test.
sub_test.cpp
#include "mock/mock_mystr.h"
MockMystr* mystr_mock;
//Il semble qu'une telle fonction principale soit nécessaire lors de l'utilisation de Mock
int main(int argc, char** argv)
{
::testing::InitGoogleMock(&argc, argv);
return RUN_ALL_TESTS();
}
TEST(sub_test, test01)
{
mystr_mock = new MockMystr();
const char* test_str = ": test";
int test_str_len = strlen(test_str);
EXPECT_CALL(mystr_mock, str_analyze(_, _))
.WillOnce(::testing::Return(test_str_len));
J'ai également écrit une attente pour appeler Mock ci-dessus. ʻEXPECT_CALL` est celui-là. Vous pouvez maintenant tester.
Après avoir présenté Google Test et organisé un peu la mise en page, j'ai également rendu possible l'utilisation de Google Mock en C. Il existe plusieurs façons d'utiliser Google Mock en C, mais cette fois, j'utilise Google Mock de C à l'étape suivante.
Créer une classe d'interface et créer une fonction Mock est un problème, mais comme chacun est une simple description, je pense que cela pourrait être automatisé.
Pendant ce temps, quand je jouais avec Mock, j'ai eu l'erreur de construction suivante et j'ai souffert pendant un moment.
sub_test.o: In function `Mystr::Mystr()':
/var/work/c/test/work/./mystr.h:5: undefined reference to `vtable for Mystr'
sub_test.o: In function `Mystr::~Mystr()':
/var/work/c/test/work/./mystr.h:6: undefined reference to `vtable for Mystr'
Ah, ouais, j'avais l'impression que vtable est celle que je vois de temps en temps. Dans ma vie jusqu'à présent, j'ai joué avec et cette erreur a disparu! J'ai passé du temps au Japon, mais cette fois, j'étais motivé pour enquêter. Qu'est-ce que le virtuel? Ou vtable? Avec ce sentiment. Puis je suis finalement arrivé à la page suivante.
http://yukichanko.hatenablog.com/entry/20110113/1294932335
Eh bien, cette page n'est pas non plus la réponse, mais en bref, si vous créez une classe d'interface à moitié terminée comme indiqué ci-dessous, il semble qu'une telle erreur se produira.
class Mystr {
public:
Mystr(void){};
virtual ~Mystr(void){};
virtual int str_analyze(const char* str, int max); //Pas une fonction virtuelle pure
};
Je ne pense pas pouvoir conclure que la classe d'interface est dans le désordre en lisant le message d'erreur g ++ tel quel, mais cela a-t-il un sens?
Je le publierai ci-dessous. work01 n'a pas de simulacre et work02 a simulé.
https://github.com/hakua-doublemoon/GoogleTestStudy
[^ 1]: J'ai utilisé Windows Docker pour la première fois cette fois, mais je sentais que je n'avais pas besoin de WSL si j'avais ça. Les performances peuvent être différentes, mais ce que vous pouvez faire n'est pas très différent. Ensuite, j'ai pensé que Docker serait plus facile à gérer. [^ 2]: SConstruct est en quelque sorte identique à Make, et je ne trouve pas de moyen sympa de l'écrire ... [^ 3]: Ce n'est que lorsque je suis arrivé ici que j'ai en quelque sorte compris la classe d'interface. J'étais un peu convaincu que cela ressemblait à un trait de rouille. [^ 4]: Il peut être préférable d'utiliser un pointeur intelligent comme indiqué dans la page de référence, mais cette fois je ne l'ai pas utilisé.
Recommended Posts