Erste Schritte mit CppUTest
Vogel
14.05.2017
1 min read

Wichtige Erkenntnisse
CppUTest ist ein leichtgewichtiges, aktiv gepflegtes xUnit-ähnliches Test-Framework für C/C++, mit einer C-Integrationsschicht, die nahtlos selbst in C-lastigen Codebasen funktioniert.
Sie können es über Paketmanager (Linux-Distros, Homebrew) installieren oder das GitHub-Repo klonen.
Ein minimales Setup besteht aus:
einem Produktionsverzeichnis
src/,einem Testverzeichnis
t/,einem Test-Runner (
CommandLineTestRunner), undTestmodulen, die
TEST_GROUPundTEST()-Blöcke verwenden.
CppUTest liefert einen MakefileWorker.mk-Helfer, der das Erstellen von Tests, Verknüpfen von Bibliotheken und Verwalten von Flags vereinfacht.
Speicherleck-Erkennung ist standardmäßig durch malloc/free Overrides aktiviert und entdeckt Lecks innerhalb des getesteten Quellcodes.
Code-Abdeckung über gcov integriert sich problemlos durch Aktivierung von
CPPUTEST_USE_GCOV=Y, erstellt vollständige Abdeckungsberichte und HTML-Zusammenfassungen.Das Framework umfasst erweiterte Features: Mocking, Plugins, Hilfsskripte und direkte C-Interoperabilität — nützlich für komplexe Enterprise-Codebasen.
Q&A Highlights
Was ist CppUTest und warum verwenden?
Es ist ein robustes, xUnit-Style-Testframework für C/C++ mit einer klaren API, eingebauten Assert-Makros, Leck-Erkennung und aktiver Entwicklung — ideal für Legacy- oder moderne Systeme.
Wie strukturiert man ein grundlegendes Projekt mit CppUTest?
src/ code/ code.cpp code.h main.cpp t/ main.cpp (test runner) test.cpp (test suite)
Wie führt man alle Tests aus?
Der Testlauf verwendet:
return CommandLineTestRunner::RunAllTests(ac, av);
Wie erstellen Sie Tests, ohne die Compiler-Optionen manuell zu konfigurieren?
Verwenden Sie
MakefileWorker.mkvon CppUTest, das Flags, Verlinkung und Testausführung automatisch handhabt.Kann CppUTest Speicherlecks automatisch erkennen?
Ja. Es überschreibt malloc/free während der Test-Builds und berichtet:
welcher Test ausgelaufen ist,
wo es aufgetreten ist,
Leckgröße und Speicherinhalte.
Beispiel für einen Fehlerausgang:
Memory leak(s) found. Allocated at: code.c line 6 Leak size: 1
Wie generiere ich Code Coverage?
Aktivieren:
CPPUTEST_USE_GCOV=YStellen Sie sicher, dass
filterGcov.shverfügbar ist unter$(CPPUTEST_HOME)/scripts/.Ausführen: make
gcovDies erzeugt
.gcov, Zusammenfassungstext und HTML-Abdeckungsberichte.
Was kann CppUTest über grundlegende Tests hinaus noch leisten?
Mocking-Framework
Plugin-System
Automatisierungsskripte für Hilfsprogramme
Native C-Integration
Umfangreiche Assertions-Makros
Für wen ist CppUTest am besten geeignet?
Teams, die mit Embedded-Systems, C-Plattformen, C++-Diensten oder jeder Umgebung arbeiten, in der Zuverlässigkeit und Speichersicherheit kontinuierlich validiert werden müssen.
Bei SparkPost investieren wir viel Zeit und Mühe in das Testen unseres Codes. Unsere Plattform ist in C geschrieben, und kürzlich habe ich die Integration mit einem Unit-Test-Framework namens „CppUTest“ recherchiert, das xUnit-ähnliches Testen für C/C++ bietet. Dieses Framework ist robust, funktionsreich und wird aktiv weiterentwickelt, was es zu einer großartigen Wahl macht. Es bietet auch eine C-Integrationsschicht, die die Verwendung mit unserem Plattform-C-Code erleichterte, obwohl der Großteil des Frameworks in C++ geschrieben ist. Dieses Tutorial erklärt, wie Sie mit CppUTest in Ihren eigenen Projekten beginnen können.
Bei SparkPost investieren wir viel Zeit und Mühe in das Testen unseres Codes. Unsere Plattform ist in C geschrieben, und kürzlich habe ich die Integration mit einem Unit-Test-Framework namens „CppUTest“ recherchiert, das xUnit-ähnliches Testen für C/C++ bietet. Dieses Framework ist robust, funktionsreich und wird aktiv weiterentwickelt, was es zu einer großartigen Wahl macht. Es bietet auch eine C-Integrationsschicht, die die Verwendung mit unserem Plattform-C-Code erleichterte, obwohl der Großteil des Frameworks in C++ geschrieben ist. Dieses Tutorial erklärt, wie Sie mit CppUTest in Ihren eigenen Projekten beginnen können.
Bei SparkPost investieren wir viel Zeit und Mühe in das Testen unseres Codes. Unsere Plattform ist in C geschrieben, und kürzlich habe ich die Integration mit einem Unit-Test-Framework namens „CppUTest“ recherchiert, das xUnit-ähnliches Testen für C/C++ bietet. Dieses Framework ist robust, funktionsreich und wird aktiv weiterentwickelt, was es zu einer großartigen Wahl macht. Es bietet auch eine C-Integrationsschicht, die die Verwendung mit unserem Plattform-C-Code erleichterte, obwohl der Großteil des Frameworks in C++ geschrieben ist. Dieses Tutorial erklärt, wie Sie mit CppUTest in Ihren eigenen Projekten beginnen können.
CppUTest herunterladen
Die CppUTest-Projektseite ist auf der offiziellen Website verfügbar, und das Repository befindet sich auf GitHub. Es ist auch in den Paketverwaltungs-Repositories für viele Linux-Distros sowie in Homebrew auf Mac OS enthalten. Die folgenden Beispiele wurden auf Mac OS X ausgeführt, stammen jedoch aus Code, der für Red Hat geschrieben wurde, das Betriebssystem, auf dem unsere Plattform läuft.
Die Grundlagen sind gut auf der Startseite von CppUTest dokumentiert. Wir werden das im Schnelldurchlauf durchgehen und zu einigen der interessanteren Funktionen gelangen.
Die CppUTest-Projektseite ist auf der offiziellen Website verfügbar, und das Repository befindet sich auf GitHub. Es ist auch in den Paketverwaltungs-Repositories für viele Linux-Distros sowie in Homebrew auf Mac OS enthalten. Die folgenden Beispiele wurden auf Mac OS X ausgeführt, stammen jedoch aus Code, der für Red Hat geschrieben wurde, das Betriebssystem, auf dem unsere Plattform läuft.
Die Grundlagen sind gut auf der Startseite von CppUTest dokumentiert. Wir werden das im Schnelldurchlauf durchgehen und zu einigen der interessanteren Funktionen gelangen.
Die CppUTest-Projektseite ist auf der offiziellen Website verfügbar, und das Repository befindet sich auf GitHub. Es ist auch in den Paketverwaltungs-Repositories für viele Linux-Distros sowie in Homebrew auf Mac OS enthalten. Die folgenden Beispiele wurden auf Mac OS X ausgeführt, stammen jedoch aus Code, der für Red Hat geschrieben wurde, das Betriebssystem, auf dem unsere Plattform läuft.
Die Grundlagen sind gut auf der Startseite von CppUTest dokumentiert. Wir werden das im Schnelldurchlauf durchgehen und zu einigen der interessanteren Funktionen gelangen.
Das Fundament legen
Zuerst einmal, schreiben wir etwas Code!
Unser Testprojekt wird eine „main“-Datei haben und eine Dienstprogrammbibliothek namens „code“ enthalten. Die Bibliothek wird eine einfache Funktion bereitstellen, die 1 zurückgibt (vorerst). Die Dateien werden wie folgt angeordnet sein:
├── src │ ├── code │ │ ├── code.cpp │ │ └── code.h │ └── main.cpp └── t ├── main.cpp └── test.cpp
Beginnen wir damit, die src/-Dateien zu schreiben
// src/main.cpp #include <stdlib.h> #include <stdio.h> #include "code.h" int main(void) { test_func(); printf("hello world!\n"); exit(0); }
// src/code/code.cpp #include <stdlib.h> #include "code.h" int test_func() { return 1; }
// src/code/code.h #ifndef __code_h__ #define __code_h__ int test_func(); #endif
Jetzt machen wir die Tests, die im t/-Verzeichnis liegen werden. Das Erste, was zu tun ist, ist einen Testrunner einzurichten, der unsere Testdateien ausführt. Dies ist auch die „main“-Funktion, die ausgeführt wird, sobald dies alles kompiliert ist:
// t/main.cpp #include "CppUTest/CommandLineTestRunner.h" int main(int ac, char** av) { return CommandLineTestRunner::RunAllTests(ac, av); }
Nun können wir unser erstes Testmodul schreiben:
// t/test.cpp #include "CppUTest/TestHarness.h" #include "code.h" TEST_GROUP(AwesomeExamples) { }; TEST(AwesomeExamples, FirstExample) { int x = test_func(); CHECK_EQUAL(1, x); }
Als Nächstes müssen wir Makefiles schreiben. Wir brauchen zwei: eines für die Projektdateien unter src/, und eines für die Tests.
Zuerst einmal, schreiben wir etwas Code!
Unser Testprojekt wird eine „main“-Datei haben und eine Dienstprogrammbibliothek namens „code“ enthalten. Die Bibliothek wird eine einfache Funktion bereitstellen, die 1 zurückgibt (vorerst). Die Dateien werden wie folgt angeordnet sein:
├── src │ ├── code │ │ ├── code.cpp │ │ └── code.h │ └── main.cpp └── t ├── main.cpp └── test.cpp
Beginnen wir damit, die src/-Dateien zu schreiben
// src/main.cpp #include <stdlib.h> #include <stdio.h> #include "code.h" int main(void) { test_func(); printf("hello world!\n"); exit(0); }
// src/code/code.cpp #include <stdlib.h> #include "code.h" int test_func() { return 1; }
// src/code/code.h #ifndef __code_h__ #define __code_h__ int test_func(); #endif
Jetzt machen wir die Tests, die im t/-Verzeichnis liegen werden. Das Erste, was zu tun ist, ist einen Testrunner einzurichten, der unsere Testdateien ausführt. Dies ist auch die „main“-Funktion, die ausgeführt wird, sobald dies alles kompiliert ist:
// t/main.cpp #include "CppUTest/CommandLineTestRunner.h" int main(int ac, char** av) { return CommandLineTestRunner::RunAllTests(ac, av); }
Nun können wir unser erstes Testmodul schreiben:
// t/test.cpp #include "CppUTest/TestHarness.h" #include "code.h" TEST_GROUP(AwesomeExamples) { }; TEST(AwesomeExamples, FirstExample) { int x = test_func(); CHECK_EQUAL(1, x); }
Als Nächstes müssen wir Makefiles schreiben. Wir brauchen zwei: eines für die Projektdateien unter src/, und eines für die Tests.
Zuerst einmal, schreiben wir etwas Code!
Unser Testprojekt wird eine „main“-Datei haben und eine Dienstprogrammbibliothek namens „code“ enthalten. Die Bibliothek wird eine einfache Funktion bereitstellen, die 1 zurückgibt (vorerst). Die Dateien werden wie folgt angeordnet sein:
├── src │ ├── code │ │ ├── code.cpp │ │ └── code.h │ └── main.cpp └── t ├── main.cpp └── test.cpp
Beginnen wir damit, die src/-Dateien zu schreiben
// src/main.cpp #include <stdlib.h> #include <stdio.h> #include "code.h" int main(void) { test_func(); printf("hello world!\n"); exit(0); }
// src/code/code.cpp #include <stdlib.h> #include "code.h" int test_func() { return 1; }
// src/code/code.h #ifndef __code_h__ #define __code_h__ int test_func(); #endif
Jetzt machen wir die Tests, die im t/-Verzeichnis liegen werden. Das Erste, was zu tun ist, ist einen Testrunner einzurichten, der unsere Testdateien ausführt. Dies ist auch die „main“-Funktion, die ausgeführt wird, sobald dies alles kompiliert ist:
// t/main.cpp #include "CppUTest/CommandLineTestRunner.h" int main(int ac, char** av) { return CommandLineTestRunner::RunAllTests(ac, av); }
Nun können wir unser erstes Testmodul schreiben:
// t/test.cpp #include "CppUTest/TestHarness.h" #include "code.h" TEST_GROUP(AwesomeExamples) { }; TEST(AwesomeExamples, FirstExample) { int x = test_func(); CHECK_EQUAL(1, x); }
Als Nächstes müssen wir Makefiles schreiben. Wir brauchen zwei: eines für die Projektdateien unter src/, und eines für die Tests.
Projekt Makefile
Die Projekt-Makefile wird auf der gleichen Ebene wie die 'src'- und 't'-Verzeichnisse im Projektstamm liegen. Es sollte so aussehen:
# Makefile SRC_DIR = ./src CODE_DIR = $(SRC_DIR)/code OUT = example TEST_DIR = t test: make -C $(TEST_DIR) test_clean: make -C $(TEST_DIR) clean code.o: gcc -c -I$(CODE_DIR) $(CODE_DIR)/code.cpp -o $(CODE_DIR)/code.o main: code.o gcc -I$(CODE_DIR) $(CODE_DIR)/code.o $(SRC_DIR)/main.cpp -o $(OUT) all: test main clean: test_clean rm $(SRC_DIR)/*.o $(CODE_DIR)/*.o $(OUT)
Beachten Sie, dass dies 'make -C' für die Testziele verwendet – bedeutet, dass es 'make' erneut mit der Makefile im Testverzeichnis aufrufen wird.
An diesem Punkt können wir den 'src'-Code mit der Makefile kompilieren und sehen, dass es funktioniert:
[]$ make main gcc -c -I./src/code ./src/code/code.cpp -o ./src/code/code.o gcc -I./src/code ./src/code/code.o ./src/main.cpp -o example []$ ./example hello world
Die Projekt-Makefile wird auf der gleichen Ebene wie die 'src'- und 't'-Verzeichnisse im Projektstamm liegen. Es sollte so aussehen:
# Makefile SRC_DIR = ./src CODE_DIR = $(SRC_DIR)/code OUT = example TEST_DIR = t test: make -C $(TEST_DIR) test_clean: make -C $(TEST_DIR) clean code.o: gcc -c -I$(CODE_DIR) $(CODE_DIR)/code.cpp -o $(CODE_DIR)/code.o main: code.o gcc -I$(CODE_DIR) $(CODE_DIR)/code.o $(SRC_DIR)/main.cpp -o $(OUT) all: test main clean: test_clean rm $(SRC_DIR)/*.o $(CODE_DIR)/*.o $(OUT)
Beachten Sie, dass dies 'make -C' für die Testziele verwendet – bedeutet, dass es 'make' erneut mit der Makefile im Testverzeichnis aufrufen wird.
An diesem Punkt können wir den 'src'-Code mit der Makefile kompilieren und sehen, dass es funktioniert:
[]$ make main gcc -c -I./src/code ./src/code/code.cpp -o ./src/code/code.o gcc -I./src/code ./src/code/code.o ./src/main.cpp -o example []$ ./example hello world
Die Projekt-Makefile wird auf der gleichen Ebene wie die 'src'- und 't'-Verzeichnisse im Projektstamm liegen. Es sollte so aussehen:
# Makefile SRC_DIR = ./src CODE_DIR = $(SRC_DIR)/code OUT = example TEST_DIR = t test: make -C $(TEST_DIR) test_clean: make -C $(TEST_DIR) clean code.o: gcc -c -I$(CODE_DIR) $(CODE_DIR)/code.cpp -o $(CODE_DIR)/code.o main: code.o gcc -I$(CODE_DIR) $(CODE_DIR)/code.o $(SRC_DIR)/main.cpp -o $(OUT) all: test main clean: test_clean rm $(SRC_DIR)/*.o $(CODE_DIR)/*.o $(OUT)
Beachten Sie, dass dies 'make -C' für die Testziele verwendet – bedeutet, dass es 'make' erneut mit der Makefile im Testverzeichnis aufrufen wird.
An diesem Punkt können wir den 'src'-Code mit der Makefile kompilieren und sehen, dass es funktioniert:
[]$ make main gcc -c -I./src/code ./src/code/code.cpp -o ./src/code/code.o gcc -I./src/code ./src/code/code.o ./src/main.cpp -o example []$ ./example hello world
Tests Makefile
Für die Tests sind die Dinge etwas komplexer, da wir die CppUTest-Bibliothek ordnungsgemäß laden und integrieren müssen.
Das CppUTest-Repository stellt eine Datei namens „MakefileWorker.mk“ bereit. Sie bietet viele Funktionen, die das Bauen mit CppUTest einfach machen. Die Datei befindet sich im Verzeichnis „build“ im Git-Repository. Für dieses Tutorial gehen wir davon aus, dass sie in das Verzeichnis ‘t/’ kopiert wurde. Sie kann wie folgt verwendet werden:
# we don’t want to use relative paths, so we set these variables PROJECT_DIR=/path/to/project SRC_DIR=$(PROJECT_DIR)/src TEST_DIR=$(PROJECT_DIR)/t # specify where the source code and includes are located INCLUDE_DIRS=$(SRC_DIR)/code SRC_DIRS=$(SRC_DIR)/code # specify where the test code is located TEST_SRC_DIRS=$(TEST_DIR) # what to call the test binary TEST_TARGET=example # where the cpputest library is located CPPUTEST_HOME=/usr/local # run MakefileWorker.mk with the variables defined here include MakefileWorker.mk
Beachten Sie, dass CPPUTEST_HOME auf den Ort gesetzt werden muss, an dem CppUTest installiert wurde. Wenn Sie ein Distro-Paket installiert haben, befindet sich dies normalerweise unter /usr/local auf einem Linux/Mac-System. Wenn Sie das Repository selbst ausgecheckt haben, befindet es sich dort, wo dieses Checkout gemacht wurde.
Diese Optionen sind alle in MakefileWorker.mk dokumentiert.
MakefileWorker.mk fügt auch einige Makefile-Ziele hinzu, darunter die folgenden:
all – erstellt die im Makefile angegebenen Tests
clean – entfernt alle für die Tests erzeugten Objekt- und gcov-Dateien
realclean – entfernt alle Objekt- oder gcov-Dateien im gesamten Verzeichnisbaum
flags – listet alle konfigurierten Flags auf, die zum Kompilieren der Tests verwendet werden
debug – listet alle Quelldateien, Objekte, Abhängigkeiten und ‚zu bereinigende Objekte‘ auf
Für die Tests sind die Dinge etwas komplexer, da wir die CppUTest-Bibliothek ordnungsgemäß laden und integrieren müssen.
Das CppUTest-Repository stellt eine Datei namens „MakefileWorker.mk“ bereit. Sie bietet viele Funktionen, die das Bauen mit CppUTest einfach machen. Die Datei befindet sich im Verzeichnis „build“ im Git-Repository. Für dieses Tutorial gehen wir davon aus, dass sie in das Verzeichnis ‘t/’ kopiert wurde. Sie kann wie folgt verwendet werden:
# we don’t want to use relative paths, so we set these variables PROJECT_DIR=/path/to/project SRC_DIR=$(PROJECT_DIR)/src TEST_DIR=$(PROJECT_DIR)/t # specify where the source code and includes are located INCLUDE_DIRS=$(SRC_DIR)/code SRC_DIRS=$(SRC_DIR)/code # specify where the test code is located TEST_SRC_DIRS=$(TEST_DIR) # what to call the test binary TEST_TARGET=example # where the cpputest library is located CPPUTEST_HOME=/usr/local # run MakefileWorker.mk with the variables defined here include MakefileWorker.mk
Beachten Sie, dass CPPUTEST_HOME auf den Ort gesetzt werden muss, an dem CppUTest installiert wurde. Wenn Sie ein Distro-Paket installiert haben, befindet sich dies normalerweise unter /usr/local auf einem Linux/Mac-System. Wenn Sie das Repository selbst ausgecheckt haben, befindet es sich dort, wo dieses Checkout gemacht wurde.
Diese Optionen sind alle in MakefileWorker.mk dokumentiert.
MakefileWorker.mk fügt auch einige Makefile-Ziele hinzu, darunter die folgenden:
all – erstellt die im Makefile angegebenen Tests
clean – entfernt alle für die Tests erzeugten Objekt- und gcov-Dateien
realclean – entfernt alle Objekt- oder gcov-Dateien im gesamten Verzeichnisbaum
flags – listet alle konfigurierten Flags auf, die zum Kompilieren der Tests verwendet werden
debug – listet alle Quelldateien, Objekte, Abhängigkeiten und ‚zu bereinigende Objekte‘ auf
Für die Tests sind die Dinge etwas komplexer, da wir die CppUTest-Bibliothek ordnungsgemäß laden und integrieren müssen.
Das CppUTest-Repository stellt eine Datei namens „MakefileWorker.mk“ bereit. Sie bietet viele Funktionen, die das Bauen mit CppUTest einfach machen. Die Datei befindet sich im Verzeichnis „build“ im Git-Repository. Für dieses Tutorial gehen wir davon aus, dass sie in das Verzeichnis ‘t/’ kopiert wurde. Sie kann wie folgt verwendet werden:
# we don’t want to use relative paths, so we set these variables PROJECT_DIR=/path/to/project SRC_DIR=$(PROJECT_DIR)/src TEST_DIR=$(PROJECT_DIR)/t # specify where the source code and includes are located INCLUDE_DIRS=$(SRC_DIR)/code SRC_DIRS=$(SRC_DIR)/code # specify where the test code is located TEST_SRC_DIRS=$(TEST_DIR) # what to call the test binary TEST_TARGET=example # where the cpputest library is located CPPUTEST_HOME=/usr/local # run MakefileWorker.mk with the variables defined here include MakefileWorker.mk
Beachten Sie, dass CPPUTEST_HOME auf den Ort gesetzt werden muss, an dem CppUTest installiert wurde. Wenn Sie ein Distro-Paket installiert haben, befindet sich dies normalerweise unter /usr/local auf einem Linux/Mac-System. Wenn Sie das Repository selbst ausgecheckt haben, befindet es sich dort, wo dieses Checkout gemacht wurde.
Diese Optionen sind alle in MakefileWorker.mk dokumentiert.
MakefileWorker.mk fügt auch einige Makefile-Ziele hinzu, darunter die folgenden:
all – erstellt die im Makefile angegebenen Tests
clean – entfernt alle für die Tests erzeugten Objekt- und gcov-Dateien
realclean – entfernt alle Objekt- oder gcov-Dateien im gesamten Verzeichnisbaum
flags – listet alle konfigurierten Flags auf, die zum Kompilieren der Tests verwendet werden
debug – listet alle Quelldateien, Objekte, Abhängigkeiten und ‚zu bereinigende Objekte‘ auf
Code Coverage
Einheitstests wären ohne einen Deckungsbericht nicht vollständig. Das bevorzugte Tool für Projekte, die gcc verwenden, ist gcov, das als Teil der standardmäßigen gcc-Dienstprogramme verfügbar ist. Cpputest lässt sich leicht mit gcov integrieren, alles, was Sie tun müssen, ist, diese Zeile zur Makefile hinzuzufügen:
CPPUTEST_USE_GCOV=Y
Als nächstes müssen wir sicherstellen, dass das filterGcov.sh-Skript aus diesem Repository in „/scripts/filterGcov.sh“ relativ zu dem Ort liegt, an dem Sie „CPPUTEST_HOME“ festgelegt haben. Es muss auch über Execute-Berechtigungen verfügen.
Im Beispiel-Makefile würde es in „/usr/local/scripts/filterGcov.sh“ bereitgestellt werden. Wenn Sie CppUTest aus einem Repository-Checkout ausführen, sollte alles ohne Änderungen funktionieren.
Damit können Sie einfach „make gcov“ ausführen, und die Analyse wird für Sie generiert. In unserem Fall müssen wir „make -B“ ausführen, um die Objektdateien mit aktiviertem gcov neu zu erstellen:
[]$ make -B gcov < compilation output > for d in /Users/ykuperman/code/blogpost/qa/src/code ; do \ FILES=`ls $d/*.c $d/*.cc $d/*.cpp 2> /dev/null` ; \ gcov --object-directory objs/$d $FILES >> gcov_output.txt 2>>gcov_error.txt ; \ done for f in ; do \ gcov --object-directory objs/$f $f >> gcov_output.txt 2>>gcov_error.txt ; \ done /usr/local/scripts/filterGcov.sh gcov_output.txt gcov_error.txt gcov_report.txt example.txt cat gcov_report.txt 100.00% /Users/ykuperman/code/blogpost/qa/src/code/code.cpp mkdir -p gcov mv *.gcov gcov mv gcov_* gcov See gcov directory for details
Dies wird eine Reihe von Dateien in ein neues „gcov“-Verzeichnis ausgeben. Diese sind:
code.cpp.gcov – die tatsächliche „gcov“-Datei für den zu testenden Code
gcov_error.txt – ein Fehlerbericht (in unserem Fall sollte er leer sein)
gcov_output.txt – die tatsächliche Ausgabe des ausgeführten gcov-Kommandos
gcov_report.txt – eine Zusammenfassung der Deckung für jede geprüfte Datei
gcov_report.txt.html – eine HTML-Version von gcov_report
Einheitstests wären ohne einen Deckungsbericht nicht vollständig. Das bevorzugte Tool für Projekte, die gcc verwenden, ist gcov, das als Teil der standardmäßigen gcc-Dienstprogramme verfügbar ist. Cpputest lässt sich leicht mit gcov integrieren, alles, was Sie tun müssen, ist, diese Zeile zur Makefile hinzuzufügen:
CPPUTEST_USE_GCOV=Y
Als nächstes müssen wir sicherstellen, dass das filterGcov.sh-Skript aus diesem Repository in „/scripts/filterGcov.sh“ relativ zu dem Ort liegt, an dem Sie „CPPUTEST_HOME“ festgelegt haben. Es muss auch über Execute-Berechtigungen verfügen.
Im Beispiel-Makefile würde es in „/usr/local/scripts/filterGcov.sh“ bereitgestellt werden. Wenn Sie CppUTest aus einem Repository-Checkout ausführen, sollte alles ohne Änderungen funktionieren.
Damit können Sie einfach „make gcov“ ausführen, und die Analyse wird für Sie generiert. In unserem Fall müssen wir „make -B“ ausführen, um die Objektdateien mit aktiviertem gcov neu zu erstellen:
[]$ make -B gcov < compilation output > for d in /Users/ykuperman/code/blogpost/qa/src/code ; do \ FILES=`ls $d/*.c $d/*.cc $d/*.cpp 2> /dev/null` ; \ gcov --object-directory objs/$d $FILES >> gcov_output.txt 2>>gcov_error.txt ; \ done for f in ; do \ gcov --object-directory objs/$f $f >> gcov_output.txt 2>>gcov_error.txt ; \ done /usr/local/scripts/filterGcov.sh gcov_output.txt gcov_error.txt gcov_report.txt example.txt cat gcov_report.txt 100.00% /Users/ykuperman/code/blogpost/qa/src/code/code.cpp mkdir -p gcov mv *.gcov gcov mv gcov_* gcov See gcov directory for details
Dies wird eine Reihe von Dateien in ein neues „gcov“-Verzeichnis ausgeben. Diese sind:
code.cpp.gcov – die tatsächliche „gcov“-Datei für den zu testenden Code
gcov_error.txt – ein Fehlerbericht (in unserem Fall sollte er leer sein)
gcov_output.txt – die tatsächliche Ausgabe des ausgeführten gcov-Kommandos
gcov_report.txt – eine Zusammenfassung der Deckung für jede geprüfte Datei
gcov_report.txt.html – eine HTML-Version von gcov_report
Einheitstests wären ohne einen Deckungsbericht nicht vollständig. Das bevorzugte Tool für Projekte, die gcc verwenden, ist gcov, das als Teil der standardmäßigen gcc-Dienstprogramme verfügbar ist. Cpputest lässt sich leicht mit gcov integrieren, alles, was Sie tun müssen, ist, diese Zeile zur Makefile hinzuzufügen:
CPPUTEST_USE_GCOV=Y
Als nächstes müssen wir sicherstellen, dass das filterGcov.sh-Skript aus diesem Repository in „/scripts/filterGcov.sh“ relativ zu dem Ort liegt, an dem Sie „CPPUTEST_HOME“ festgelegt haben. Es muss auch über Execute-Berechtigungen verfügen.
Im Beispiel-Makefile würde es in „/usr/local/scripts/filterGcov.sh“ bereitgestellt werden. Wenn Sie CppUTest aus einem Repository-Checkout ausführen, sollte alles ohne Änderungen funktionieren.
Damit können Sie einfach „make gcov“ ausführen, und die Analyse wird für Sie generiert. In unserem Fall müssen wir „make -B“ ausführen, um die Objektdateien mit aktiviertem gcov neu zu erstellen:
[]$ make -B gcov < compilation output > for d in /Users/ykuperman/code/blogpost/qa/src/code ; do \ FILES=`ls $d/*.c $d/*.cc $d/*.cpp 2> /dev/null` ; \ gcov --object-directory objs/$d $FILES >> gcov_output.txt 2>>gcov_error.txt ; \ done for f in ; do \ gcov --object-directory objs/$f $f >> gcov_output.txt 2>>gcov_error.txt ; \ done /usr/local/scripts/filterGcov.sh gcov_output.txt gcov_error.txt gcov_report.txt example.txt cat gcov_report.txt 100.00% /Users/ykuperman/code/blogpost/qa/src/code/code.cpp mkdir -p gcov mv *.gcov gcov mv gcov_* gcov See gcov directory for details
Dies wird eine Reihe von Dateien in ein neues „gcov“-Verzeichnis ausgeben. Diese sind:
code.cpp.gcov – die tatsächliche „gcov“-Datei für den zu testenden Code
gcov_error.txt – ein Fehlerbericht (in unserem Fall sollte er leer sein)
gcov_output.txt – die tatsächliche Ausgabe des ausgeführten gcov-Kommandos
gcov_report.txt – eine Zusammenfassung der Deckung für jede geprüfte Datei
gcov_report.txt.html – eine HTML-Version von gcov_report
Cpputest Memory Leak Detection
Cpputest ermöglicht es Ihnen, automatisch undichte Speicher zu erkennen, indem die Standardfunktionen „malloc/free“ durch eigene Wrapper-Funktionen ersetzt werden. Dadurch kann es Lecks schnell erfassen und für jede Testausführung melden. Dies ist standardmäßig in MakefileWorker.mk aktiviert, sodass es mit den bisher beschriebenen Schritten bereits eingeschaltet ist.
Um dies zu veranschaulichen, lassen Sie uns etwas Speicher in test_func() verlieren !
Gehen wir zurück zu code.c, fügen wir der Funktion ein malloc() hinzu, so:
int test_func() { malloc(1); return 1; }
Jetzt erzeugt das folgende Fehler nach dem erneuten Kompilieren:
test.cpp:9: error: Failure in TEST(AwesomeExamples, FirstExample) Memory leak(s) found. Alloc num (4) Leak size: 1 Allocated at: ./code.c and line: 6 Type: "malloc" Memory: <
Dies zeigt, welcher Test das Leck verursachte, wo der Leck im Quellcode auftrat und was im undichten Speicher war. Sehr hilfreich!
Zu diesem Feature gibt es ein paar Vorbehalte:
Cpputest verwendet Präprozessor-Makros, um alle Aufrufe an die Standard-Speicherverwaltungsfunktionen dynamisch neu zu definieren. Das bedeutet, dass es nur für Aufrufe im getesteten Quellcode funktioniert, da dieser mit den Overrides von CppUTest kompiliert wird. Lecks in verknüpften Bibliotheken werden nicht erfasst.
Manchmal ist der Speicher, der für die gesamte Lebensdauer des Prozesses zugewiesen wird, nicht dazu gedacht, freigegeben zu werden. Dies kann viele fehlerhafte Fehler erzeugen, wenn Sie ein Modul mit diesem Verhalten testen. Um die Leckerkennung zu deaktivieren, können Sie dies tun:
CPPUTEST_USE_MEM_LEAK_DETECTION=N
Cpputest ermöglicht es Ihnen, automatisch undichte Speicher zu erkennen, indem die Standardfunktionen „malloc/free“ durch eigene Wrapper-Funktionen ersetzt werden. Dadurch kann es Lecks schnell erfassen und für jede Testausführung melden. Dies ist standardmäßig in MakefileWorker.mk aktiviert, sodass es mit den bisher beschriebenen Schritten bereits eingeschaltet ist.
Um dies zu veranschaulichen, lassen Sie uns etwas Speicher in test_func() verlieren !
Gehen wir zurück zu code.c, fügen wir der Funktion ein malloc() hinzu, so:
int test_func() { malloc(1); return 1; }
Jetzt erzeugt das folgende Fehler nach dem erneuten Kompilieren:
test.cpp:9: error: Failure in TEST(AwesomeExamples, FirstExample) Memory leak(s) found. Alloc num (4) Leak size: 1 Allocated at: ./code.c and line: 6 Type: "malloc" Memory: <
Dies zeigt, welcher Test das Leck verursachte, wo der Leck im Quellcode auftrat und was im undichten Speicher war. Sehr hilfreich!
Zu diesem Feature gibt es ein paar Vorbehalte:
Cpputest verwendet Präprozessor-Makros, um alle Aufrufe an die Standard-Speicherverwaltungsfunktionen dynamisch neu zu definieren. Das bedeutet, dass es nur für Aufrufe im getesteten Quellcode funktioniert, da dieser mit den Overrides von CppUTest kompiliert wird. Lecks in verknüpften Bibliotheken werden nicht erfasst.
Manchmal ist der Speicher, der für die gesamte Lebensdauer des Prozesses zugewiesen wird, nicht dazu gedacht, freigegeben zu werden. Dies kann viele fehlerhafte Fehler erzeugen, wenn Sie ein Modul mit diesem Verhalten testen. Um die Leckerkennung zu deaktivieren, können Sie dies tun:
CPPUTEST_USE_MEM_LEAK_DETECTION=N
Cpputest ermöglicht es Ihnen, automatisch undichte Speicher zu erkennen, indem die Standardfunktionen „malloc/free“ durch eigene Wrapper-Funktionen ersetzt werden. Dadurch kann es Lecks schnell erfassen und für jede Testausführung melden. Dies ist standardmäßig in MakefileWorker.mk aktiviert, sodass es mit den bisher beschriebenen Schritten bereits eingeschaltet ist.
Um dies zu veranschaulichen, lassen Sie uns etwas Speicher in test_func() verlieren !
Gehen wir zurück zu code.c, fügen wir der Funktion ein malloc() hinzu, so:
int test_func() { malloc(1); return 1; }
Jetzt erzeugt das folgende Fehler nach dem erneuten Kompilieren:
test.cpp:9: error: Failure in TEST(AwesomeExamples, FirstExample) Memory leak(s) found. Alloc num (4) Leak size: 1 Allocated at: ./code.c and line: 6 Type: "malloc" Memory: <
Dies zeigt, welcher Test das Leck verursachte, wo der Leck im Quellcode auftrat und was im undichten Speicher war. Sehr hilfreich!
Zu diesem Feature gibt es ein paar Vorbehalte:
Cpputest verwendet Präprozessor-Makros, um alle Aufrufe an die Standard-Speicherverwaltungsfunktionen dynamisch neu zu definieren. Das bedeutet, dass es nur für Aufrufe im getesteten Quellcode funktioniert, da dieser mit den Overrides von CppUTest kompiliert wird. Lecks in verknüpften Bibliotheken werden nicht erfasst.
Manchmal ist der Speicher, der für die gesamte Lebensdauer des Prozesses zugewiesen wird, nicht dazu gedacht, freigegeben zu werden. Dies kann viele fehlerhafte Fehler erzeugen, wenn Sie ein Modul mit diesem Verhalten testen. Um die Leckerkennung zu deaktivieren, können Sie dies tun:
CPPUTEST_USE_MEM_LEAK_DETECTION=N
Interessiert an mehr?
Dies ist nur die Spitze des Eisbergs, wenn es um all die Funktionen geht, die in diesem Tool enthalten sind. Neben den hier besprochenen Grundlagen verfügt es auch über ein Mocking-Framework, eine direkte C-Integrationsschicht und ein Plugin-Framework, um nur einige wesentliche zu nennen. Das Repo enthält auch ein ganzes Verzeichnis von Hilfsskripten, die helfen können, einige der Routineaufgaben bei der Arbeit mit dem Framework zu automatisieren.
Ich hoffe, die hier enthaltenen Informationen helfen Ihnen, die Qualität Ihres C/C++-Codes mit diesem großartigen Tool zu verbessern!
Dies ist nur die Spitze des Eisbergs, wenn es um all die Funktionen geht, die in diesem Tool enthalten sind. Neben den hier besprochenen Grundlagen verfügt es auch über ein Mocking-Framework, eine direkte C-Integrationsschicht und ein Plugin-Framework, um nur einige wesentliche zu nennen. Das Repo enthält auch ein ganzes Verzeichnis von Hilfsskripten, die helfen können, einige der Routineaufgaben bei der Arbeit mit dem Framework zu automatisieren.
Ich hoffe, die hier enthaltenen Informationen helfen Ihnen, die Qualität Ihres C/C++-Codes mit diesem großartigen Tool zu verbessern!
Dies ist nur die Spitze des Eisbergs, wenn es um all die Funktionen geht, die in diesem Tool enthalten sind. Neben den hier besprochenen Grundlagen verfügt es auch über ein Mocking-Framework, eine direkte C-Integrationsschicht und ein Plugin-Framework, um nur einige wesentliche zu nennen. Das Repo enthält auch ein ganzes Verzeichnis von Hilfsskripten, die helfen können, einige der Routineaufgaben bei der Arbeit mit dem Framework zu automatisieren.
Ich hoffe, die hier enthaltenen Informationen helfen Ihnen, die Qualität Ihres C/C++-Codes mit diesem großartigen Tool zu verbessern!



