Essayez Google Mock avec C

Aperçu

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.

Essayez cette fois

Environnement éprouvé

Contenu

Présentez Google Test

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

J'écrirai un code de test pour le moment

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.

Préparer l'environnement de test en modifiant la disposition

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.

Utilisez Google Mock

Le contenu d'ici renvoie à la page suivante en plus du document officiel.

  1. https://futurismo.biz/archives/306
  2. https://stackoverflow.com/questions/31989040/can-gmock-be-used-for-stubbing-c-functions

Pourquoi utiliser Mock

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.

Créer une classe d'interface et une classe Mock

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));
};

Correspond aux appels du code sous test

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.

Changer de build pour utiliser Mock

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.

Résumé

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é.

Bonus: classe d'interface et vtable pour l'erreur

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?

Code de test que j'ai créé

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

Essayez Google Mock avec C
Essayez OpenCV avec Google Colaboratory
Essayez d'utiliser Python avec Google Cloud Functions
Essayez d'exécuter Google Chrome avec Python et Selenium
Authentifier Google avec Django
Essayez de gratter avec Python.
Débogage C / C ++ avec gdb
Testé avec boto3 + mock
Essayez SNN avec BindsNET
Essayez l'API C ++ de NNabla
Essayez la régression avec TensorFlow
Essayez d'incorporer Python dans un programme C ++ avec pybind11
Essayez l'optimisation des fonctions avec Optuna
Essayez l'apprentissage en profondeur avec TensorFlow
Essayez d'utiliser PythonTex avec Texpad.
Tester les logiciels embarqués avec Google Test
Essayez la détection des bords avec OpenCV
Essayez d'implémenter RBM avec chainer.
Essayez StyleGAN avec Google Colaboratory
Essayez d'utiliser matplotlib avec PyCharm
Essayez de programmer avec un shell!
Essayez la programmation GUI avec Hy
Essayez Auto Encoder avec Pytorch
Essayez la sortie Python avec Haxe 3.2
Essayez l'opération matricielle avec NumPy
Étudiez Python avec Google Colaboratory
Essayez d'implémenter XOR avec PyTorch
Essayez d'exécuter CNN avec ChainerRL
À propos de l'apprentissage avec Google Colab
Essayez différentes choses avec PhantomJS
Essayez le Deep Learning avec FPGA
Essayez d'exécuter Python avec Try Jupyter
Formater la source du langage C avec pycparser
Essayez d'implémenter le parfum avec Go
Montez Google Drive avec google-drive-ocamlfuse
Accédez à Google Drive avec Python
Essayez Selenium Grid avec Docker
Essayez la reconnaissance faciale avec Python
Traduire - Aide de PHP_UML avec Google Traduction
Essayez le machine learning à la légère avec Kaggle
Essayez TensorFlow MNIST avec RNN
Essayez de créer Jupyter Hub avec Docker
Essayez d'utiliser le folium avec anaconda
Essayez d'implémenter la régression linéaire à l'aide de Pytorch avec Google Colaboratory
Essayez d'afficher la carte google et la carte géographique avec python
Essayez le Deep Learning avec les concombres FPGA-Select
Aide-mémoire personnel Google Test / Mock
Essayez de gratter avec Python + Beautiful Soup
Résoudre ABC163 A ~ C avec Python
Renforcer l'apprentissage 13 Essayez Mountain_car avec ChainerRL.
Créer Awaitable avec l'API Python / C
Essayez d'exploiter Facebook avec Python
Ecriture du langage C avec Sympy (métaprogrammation)
Essayez la décomposition de valeurs singulières avec Python
Essayez l'apprentissage en profondeur avec TensorFlow Partie 2
Essayez l'invite http avec un accès http interactif
Essayez le traitement du signal audio avec librosa-Beginner