Versuchen Sie Google Mock mit C.

Überblick

Es ist ein langer Urlaub, aber ich habe keine Lust auf eine Sommerkälte, also stecke ich Google Mock in mein Zimmer. Ich verwende C aus irgendeinem Grund bei der Arbeit, daher habe ich zusammengefasst, wie Google Mock für C-Code verwendet wird. Diesmal ist die Einführung.

Versuchen Sie es diesmal

Versuchte Umgebung

Inhalt

Führen Sie Google Test ein

Es scheint, dass es viele Artikel dieses Grades gibt, also werde ich gleich darauf eingehen. Ich denke, das Folgende wird auch hilfreich sein. https://qiita.com/shohirose/items/30e39949d8bf990b0462

Ich werde vorerst einen Testcode schreiben

Angenommen, Sie haben einen solchen Code. (Ich lasse Include weg, aber ich mache es gut)

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

Der Code zum Testen des Rückgabewerts dieser test1 () Funktion wäre:

sub_test.cpp


TEST(sub_test, test01)
{
    EXPECT_EQ(6, test1(": test"));
}

Derzeit werden diese Platzierungen und Builds wie auf der folgenden Website gezeigt durchgeführt. https://techblog.kayac.com/google-test

g++ -std=c++11 test/sub_test.cpp -I. -Isrc -Igoogletest/include -Lgoogletest -lgtest -lgtest_main -lpthread

Wenn Sie dies tun, wird eine "a.out" -Datei als Testprogramm generiert und Sie können den Test ausführen.

Bereiten Sie die Testumgebung vor, indem Sie die Anordnung ändern

Wenn dies unverändert bleibt, werden der Quellcode und der Entwicklungscode von Google Test zusammengeführt. Versuchen Sie daher, die Anordnung wie folgt zu ändern.

|
+- GoogleTest
|  + ...
|
+- work 
   + sub.c
   + sub.h
   + mystr.c
   + mystr.h

Der Build zu diesem Zeitpunkt kann durch geringfügiges Ändern des oben beschriebenen Befehls durchgeführt werden, ist jedoch ärgerlich. Also werde ich Scons verwenden, die ich kürzlich bei der Arbeit gelernt habe. Ich habe es geschrieben, während ich mir Folgendes angesehen habe. [^ 2] https://scons.org/doc/0.97/HTML/scons-user/x628.html

SConstruct


env = Environment()

env.Program(
    target='sub_test',
    #Sie können mit gdb debuggen, wenn Sie keine Debug-Option hinzufügen müssen
    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',
    ],
)

Nun, das ist nicht sehr gut, weil die Zwischenprodukte mit dem Quellcode gemischt sind, aber diesmal ist es ärgerlich, also ist es das gleiche.

Verwenden Sie Google Mock

Der Inhalt von hier bezieht sich zusätzlich zum offiziellen Dokument auf die folgende Seite.

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

Warum Mock verwenden?

Der Grund für die Verwendung von Mock wird auch in der Übersetzung der offiziellen Dokumentation erläutert.

http://opencv.jp/googlemockdocs/fordummies.html

In einem normalen Programm verwenden Sie eine echte Implementierung dieser Schnittstelle. Zum Testen verwenden wir stattdessen die Scheinimplementierung. Auf diese Weise können Sie leicht überprüfen, welches Zeichnungsprimitiv aus dem Programm aufgerufen wurde, welche Argumente vorliegen und in welcher Reihenfolge. Auf diese Weise geschriebene Tests sind sehr robust (sie brechen nicht aufgrund von Änderungen im Antialiasing des Computers ab), sind leicht zu entschlüsseln und zu warten (der Zweck des Tests wird eher in Code als in einer Bilddatei ausgedrückt). ), Und die Testausführung ist viel schneller.

Persönlich denke ich, dass White-Box-Test-ähnliche Überprüfungen, wie z. B. ob sie aufgerufen werden und die Reihenfolge, für die Verwendung von Mock wichtig sind.

Jetzt erstellen wir einen Mock von str_analyze () als Modul, das mystr Mock macht. Da Google Mock jedoch für C ++ ist, kann es nicht wie für C verwendet werden.

Erstellen Sie die Schnittstellenklasse und die Mock-Klasse

Es scheint nicht auf der offiziellen Seite geschrieben zu sein, aber es scheint, dass Sie eine Schnittstellenklasse [^ 3] erstellen müssen, um Google Mock verwenden zu können. Also, mystr ist C, aber wenn es C ++ ist ... werde ich eine Header-Datei erstellen.

mock/mock_mystr.h


class Mystr {
public:
Mystr(void){}
virtual ~Mystr(void){}
virtual int str_analyze(const char* str, int max) = 0;
};

Schreiben Sie die entsprechende Mock-Klasse weiter.

mock/mock_mystr.h


class MockMystr : public Mystr {
 public:
  MockMystr(){}
  ~MockMystr(){}
  MOCK_METHOD2(str_analyze,
      int(const char* str, int max));
};

Entspricht Aufrufen aus dem zu testenden Code

Natürlich können Sie C ++ - Klassen nicht aus C-Code aufrufen, und es ist nicht gut, den getesteten Code neu zu schreiben. Erstellen Sie daher einen Mock, wie in Referenzseite 2 oben gezeigt.

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

Ich denke, dass "externes" C "im Allgemeinen notwendig ist, um das Mangeln zu unterdrücken.

Switch Builds zur Verwendung von Mock

Bisher habe ich fast einen Mock für die Funktion "str_analyze ()" erstellt, die ich zu einem Mock machen wollte, also werde ich diesen verwenden. Machen Sie zuerst den Körper von str_analyze () unsichtbar.

SConstruct


    source = [
        "sub.c",
-        "mystr.c",
+       #"mystr.c",
        "sub_test.cpp",
    ],

Fügen Sie dann dem Testprogramm Mock-Referenzen und -Einstellungen hinzu.

sub_test.cpp


#include "mock/mock_mystr.h"

MockMystr* mystr_mock;

//Es scheint, dass eine solche Hauptfunktion bei Verwendung von Mock erforderlich ist
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));

Ich habe auch eine Erwartung geschrieben, Mock oben anzurufen. Es heißt "EXPECT_CALL". Jetzt können Sie testen.

Zusammenfassung

Nachdem ich Google Test eingeführt und das Layout ein wenig angeordnet hatte, konnte ich Google Mock auch in C verwenden. Es gibt verschiedene Möglichkeiten, Google Mock in C zu verwenden, aber dieses Mal verwende ich im nächsten Schritt Google Mock von C.

Das Erstellen einer Schnittstellenklasse und das Erstellen einer Mock-Funktion ist mühsam, aber da jede eine einfache Beschreibung ist, denke ich, dass sie automatisiert werden könnte.

Bonus: Schnittstellenklasse und vtable für Fehler

Während dieser Zeit, als ich mit Mock spielte, bekam ich den folgenden Build-Fehler und litt eine Weile.

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, ja, ich hatte das Gefühl, dass vtable das ist, was ich von Zeit zu Zeit sehe. In meinem bisherigen Leben habe ich damit herumgespielt und dieser Fehler ist verschwunden! Ich habe Zeit in Japan verbracht, aber diesmal war ich motiviert, Nachforschungen anzustellen. Was ist virtuell? Oder vtable? Mit diesem Gefühl. Dann bin ich endlich auf der folgenden Seite angekommen.

http://yukichanko.hatenablog.com/entry/20110113/1294932335

Nun, diese Seite ist auch nicht die Antwort, aber kurz gesagt, wenn Sie eine halbfertige Schnittstellenklasse wie unten gezeigt erstellen, scheint ein solcher Fehler aufzutreten.

class Mystr {
public:
Mystr(void){};
virtual ~Mystr(void){};
virtual int str_analyze(const char* str, int max); //Keine reine virtuelle Funktion
};

Ich glaube nicht, dass ich daraus schließen kann, dass die Schnittstellenklasse nicht in Ordnung ist, indem ich die g ++ - Fehlermeldung so lese, wie sie ist, aber macht das Sinn?

Testcode, den ich gemacht habe

Ich werde es unten veröffentlichen. work01 hat kein Mock und work02 hat Mock.

https://github.com/hakua-doublemoon/GoogleTestStudy

[^ 1]: Ich habe dieses Mal zum ersten Mal Windows Docker verwendet, aber ich hatte das Gefühl, dass ich keine WSL benötige, wenn ich diese hätte. Die Leistung mag unterschiedlich sein, aber was Sie tun können, ist nicht viel anders. Dann dachte ich, dass Docker einfacher zu verwalten wäre. [^ 2]: Irgendwie ist SConstruct dasselbe wie Make, und ich kann keinen coolen Weg finden, es zu schreiben ... [^ 3]: Erst als ich hierher kam, verstand ich die Interface-Klasse irgendwie. Ich war ein wenig überzeugt, dass es sich wie ein Rostmerkmal anfühlte. [^ 4]: Es ist vielleicht besser, einen intelligenten Zeiger zu verwenden, wie auf der Referenzseite gezeigt, aber diesmal habe ich ihn nicht verwendet.

Recommended Posts

Versuchen Sie Google Mock mit C.
Probieren Sie OpenCV mit Google Colaboratory aus
Versuchen Sie, Python mit Google Cloud-Funktionen zu verwenden
Versuchen Sie, Google Chrome mit Python und Selenium auszuführen
Authentifizieren Sie Google mit Django
Versuchen Sie es mit Python.
C / C ++ - Debugging mit gdb
Getestet mit boto3 + mock
Versuchen Sie SNN mit BindsNET
Probieren Sie die C ++ - API von NNabla aus
Versuchen Sie eine Regression mit TensorFlow
Versuchen Sie, Python mit pybind11 in ein C ++ - Programm einzubetten
Versuchen Sie die Funktionsoptimierung mit Optuna
Versuchen Sie es mit TensorFlow
Versuchen Sie, PythonTex mit Texpad zu verwenden.
Testen Sie eingebettete Software mit Google Test
Versuchen Sie die Kantenerkennung mit OpenCV
Versuchen Sie, RBM mit Chainer zu implementieren.
Probieren Sie StyleGAN mit Google Colaboratory aus
Versuchen Sie es mit matplotlib mit PyCharm
Versuchen Sie, mit einer Shell zu programmieren!
Versuchen Sie die GUI-Programmierung mit Hy
Versuchen Sie Auto Encoder mit Pytorch
Probieren Sie die Python-Ausgabe mit Haxe 3.2 aus
Versuchen Sie die Matrixoperation mit NumPy
Lernen Sie Python mit Google Colaboratory
Versuchen Sie, XOR mit PyTorch zu implementieren
Versuchen Sie, CNN mit ChainerRL auszuführen
Über das Lernen mit Google Colab
Probieren Sie verschiedene Dinge mit PhantomJS aus
Versuchen Sie Deep Learning mit FPGA
Versuchen Sie, Python mit Try Jupyter auszuführen
Formatieren Sie die Sprachquelle C mit pycparser
Versuchen Sie, Parfüm mit Go zu implementieren
Hängen Sie Google Drive mit google-drive-ocamlfuse ein
Greifen Sie mit Python auf Google Drive zu
Probieren Sie Selenium Grid mit Docker aus
Versuchen Sie die Gesichtserkennung mit Python
Übersetzen - Hilfe von PHP_UML mit Google Übersetzung
Versuchen Sie es mit Kaggle leicht maschinell
Versuchen Sie TensorFlow MNIST mit RNN
Versuchen Sie, Jupyter Hub mit Docker zu erstellen
Versuchen Sie es mit Folium mit Anakonda
Versuchen Sie, eine lineare Regression mit Pytorch mit Google Colaboratory zu implementieren
Versuchen Sie, Google Map und Geography Map mit Python anzuzeigen
Probieren Sie Deep Learning mit FPGA-Select-Gurken aus
Persönlicher Spickzettel von Google Test / Mock
Versuchen Sie es mit Python + Beautiful Soup
Löse ABC163 A ~ C mit Python
Lernen stärken 13 Probieren Sie Mountain_car mit ChainerRL aus.
Erstellen Sie Awaitable mit der Python / C-API
Versuchen Sie, Facebook mit Python zu betreiben
Schreiben der C-Sprache mit Sympy (Metaprogrammierung)
Versuchen Sie die Singularwertzerlegung mit Python
Versuchen Sie es mit TensorFlow Part 2
Versuchen Sie es mit einer http-Eingabeaufforderung mit interaktivem http-Zugriff
Probieren Sie die Audiosignalverarbeitung mit librosa-Beginner aus