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.
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
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.
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.
Der Inhalt von hier bezieht sich zusätzlich zum offiziellen Dokument auf die folgende Seite.
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.
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));
};
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.
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.
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.
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?
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