Rozpoczęcie pracy z CppUTest

Ptak

14 maj 2017

Email

1 min read

Rozpoczęcie pracy z CppUTest

Najważniejsze informacje

    • CppUTest to lekki, aktywnie utrzymywany framework do testowania w stylu xUnit dla C/C++, z warstwą integracyjną C, która działa bezproblemowo nawet w kodzie intensywnie opartym na C.

    • Możesz go zainstalować za pomocą menedżerów pakietów (dystrybucje Linux, Homebrew) lub sklonować repozytorium GitHub.

    • Minimalna konfiguracja składa się z:

      • katalogu produkcyjnego src/,

      • katalogu testowego t/,

      • urządzenia do uruchamiania testów (CommandLineTestRunner), oraz

      • modułów testowych używających bloków TEST_GROUP i TEST().

    • CppUTest dostarcza pomocnika MakefileWorker.mk, który upraszcza budowanie testów, łączenie bibliotek i obsługę flag.

    • Wykrywanie wycieków pamięci jest domyślnie włączone przez nadpisania malloc/free, wychwytując wycieki w testowanym kodzie źródłowym.

    • Pokrycie kodu za pomocą gcov łatwo integruje się poprzez włączenie CPPUTEST_USE_GCOV=Y, generując pełne raporty z pokrycia i podsumowania HTML.

    • Framework zawiera zaawansowane funkcje: mockowanie, wtyczki, skrypty pomocnicze oraz bezpośrednią interoperacyjność z C — przydatne dla złożonych kodów korporacyjnych.

Podsumowanie pytań i odpowiedzi

  • Czym jest CppUTest i dlaczego warto go używać?

    To solidny, stylu xUnit framework testowy dla C/C++ z czystym API, wbudowanymi makrami asercji, wykrywaniem wycieków i aktywnym rozwojem — idealny dla systemów dziedzictwa lub nowoczesnych.

  • Jak zorganizować podstawowy projekt używając CppUTest?

    src/
      code/
        code.cpp
        code.h
      main.cpp
    t/
      main.cpp (test runner)
      test.cpp (test suite)
  • Jak uruchomić wszystkie testy?

    Tester używa:

    return CommandLineTestRunner::RunAllTests(ac, av);
  • Jak budujesz testy bez ręcznej konfiguracji opcji kompilatora?

    Użyj MakefileWorker.mk z CppUTest, który automatycznie obsługuje flagi, łączenie i wykonywanie testów.

  • Czy CppUTest może automatycznie wykrywać wycieki pamięci?

    Tak. Nadpisuje malloc/free podczas budowy testów, zgłaszając:

    • który test wyciekł,

    • gdzie to miało miejsce,

    • wielkość wycieku i zawartość pamięci.

    Przykład nieudanej jednoznacznej informacji:

    Memory leak(s) found.
    Allocated at: code.c line 6
    Leak size: 1
  • Jak mogę wygenerować pokrycie kodu?

    1. Włącz: CPPUTEST_USE_GCOV=Y

    2. Upewnij się, że filterGcov.sh jest dostępny w $(CPPUTEST_HOME)/scripts/.

    3. Uruchom: make gcov

      To generuje .gcov, tekst podsumowania i raporty pokrycia w formacie HTML.

  • Co jeszcze może zrobić CppUTest poza podstawowym testowaniem?

    • framework do mockowania

    • system wtyczek

    • skrypty automatyzacji pomocniczej

    • integracja z natywnym C

    • rozbudowane makra asercji

  • Dla kogo CppUTest jest najbardziej odpowiedni?

    Zespoły pracujące z systemami wbudowanymi, platformami C, usługami C++ lub dowolnym środowiskiem, w którym niezawodność i bezpieczeństwo pamięci muszą być nieustannie weryfikowane.

W SparkPost poświęcamy dużo czasu i wysiłku na testowanie naszego kodu. Nasza platforma jest napisana w C, a ostatnio badałem integrację z frameworkiem do testów jednostkowych o nazwie „CppUTest”, który oferuje testowanie w stylu xUnit dla C/C++. Ten framework jest solidny, bogaty w funkcje i znajduje się w aktywnej fazie rozwoju, co czyni go świetnym wyborem. Oferuje również warstwę integracyjną w C, co ułatwiło korzystanie z naszego kodu C na platformie, mimo że większość frameworka jest napisana w C++. Ten samouczek omawia, jak rozpocząć pracę z CppUTest w swoich projektach.

W SparkPost poświęcamy dużo czasu i wysiłku na testowanie naszego kodu. Nasza platforma jest napisana w C, a ostatnio badałem integrację z frameworkiem do testów jednostkowych o nazwie „CppUTest”, który oferuje testowanie w stylu xUnit dla C/C++. Ten framework jest solidny, bogaty w funkcje i znajduje się w aktywnej fazie rozwoju, co czyni go świetnym wyborem. Oferuje również warstwę integracyjną w C, co ułatwiło korzystanie z naszego kodu C na platformie, mimo że większość frameworka jest napisana w C++. Ten samouczek omawia, jak rozpocząć pracę z CppUTest w swoich projektach.

W SparkPost poświęcamy dużo czasu i wysiłku na testowanie naszego kodu. Nasza platforma jest napisana w C, a ostatnio badałem integrację z frameworkiem do testów jednostkowych o nazwie „CppUTest”, który oferuje testowanie w stylu xUnit dla C/C++. Ten framework jest solidny, bogaty w funkcje i znajduje się w aktywnej fazie rozwoju, co czyni go świetnym wyborem. Oferuje również warstwę integracyjną w C, co ułatwiło korzystanie z naszego kodu C na platformie, mimo że większość frameworka jest napisana w C++. Ten samouczek omawia, jak rozpocząć pracę z CppUTest w swoich projektach.

Zainteresowany więcej?

To tylko wierzchołek góry lodowej, jeśli chodzi o wszystkie funkcje zawarte w tym narzędziu. Oprócz podstaw omówionych tutaj, ma również framework do mockowania, bezpośrednią warstwę integracyjną C oraz framework wtyczek, żeby wymienić tylko kilka ważnych. Repozytorium zawiera również całą katalog pomocniczych skryptów, które mogą pomóc zautomatyzować niektóre rutynowe części pracy z frameworkiem.

Mam nadzieję, że informacje tutaj pomogą Ci poprawić jakość Twojego kodu C/C++ dzięki temu wspaniałemu narzędziu!

To tylko wierzchołek góry lodowej, jeśli chodzi o wszystkie funkcje zawarte w tym narzędziu. Oprócz podstaw omówionych tutaj, ma również framework do mockowania, bezpośrednią warstwę integracyjną C oraz framework wtyczek, żeby wymienić tylko kilka ważnych. Repozytorium zawiera również całą katalog pomocniczych skryptów, które mogą pomóc zautomatyzować niektóre rutynowe części pracy z frameworkiem.

Mam nadzieję, że informacje tutaj pomogą Ci poprawić jakość Twojego kodu C/C++ dzięki temu wspaniałemu narzędziu!

To tylko wierzchołek góry lodowej, jeśli chodzi o wszystkie funkcje zawarte w tym narzędziu. Oprócz podstaw omówionych tutaj, ma również framework do mockowania, bezpośrednią warstwę integracyjną C oraz framework wtyczek, żeby wymienić tylko kilka ważnych. Repozytorium zawiera również całą katalog pomocniczych skryptów, które mogą pomóc zautomatyzować niektóre rutynowe części pracy z frameworkiem.

Mam nadzieję, że informacje tutaj pomogą Ci poprawić jakość Twojego kodu C/C++ dzięki temu wspaniałemu narzędziu!

Pobieranie CppUTest

Strona projektu CppUTest jest dostępna na oficjalnej stronie, a repozytorium znajduje się na githubie. Jest również dostępny w repozytoriach zarządzania pakietami dla wielu dystrybucji Linuxa, a także w homebrew na Mac OS. Przykłady, które następują, były wykonane na Mac OS X, ale pochodzą z kodu napisanego dla Red Hat, systemu operacyjnego, na którym działa nasza platforma.

Podstawy są dobrze udokumentowane na stronie głównej CppUTest. Przechodzimy przez to szybko, aby dotrzeć do niektórych ciekawszych funkcji.

Strona projektu CppUTest jest dostępna na oficjalnej stronie, a repozytorium znajduje się na githubie. Jest również dostępny w repozytoriach zarządzania pakietami dla wielu dystrybucji Linuxa, a także w homebrew na Mac OS. Przykłady, które następują, były wykonane na Mac OS X, ale pochodzą z kodu napisanego dla Red Hat, systemu operacyjnego, na którym działa nasza platforma.

Podstawy są dobrze udokumentowane na stronie głównej CppUTest. Przechodzimy przez to szybko, aby dotrzeć do niektórych ciekawszych funkcji.

Strona projektu CppUTest jest dostępna na oficjalnej stronie, a repozytorium znajduje się na githubie. Jest również dostępny w repozytoriach zarządzania pakietami dla wielu dystrybucji Linuxa, a także w homebrew na Mac OS. Przykłady, które następują, były wykonane na Mac OS X, ale pochodzą z kodu napisanego dla Red Hat, systemu operacyjnego, na którym działa nasza platforma.

Podstawy są dobrze udokumentowane na stronie głównej CppUTest. Przechodzimy przez to szybko, aby dotrzeć do niektórych ciekawszych funkcji.

Kładzenie fundamentów

Najpierw należy napisać trochę kodu!

Nasz projekt testowy będzie miał plik 'main' i zawierał bibliotekę narzędziową o nazwie 'code'. Biblioteka dostarczy prostą funkcję, która zwróci 1 (na razie). Pliki będą uporządkowane w ten sposób:

├── src
├── code
├── code.cpp
└── code.h
└── main.cpp
└── t
    ├── main.cpp
    └── test.cpp

Zacznijmy od napisania plików src/

// 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

Teraz zróbmy testy, które będą znajdować się w katalogu t/.  Pierwszą rzeczą do zrobienia jest skonfigurowanie runnera testów, który uruchomi nasze pliki testowe. To także jest funkcja 'main' , która wykona się, gdy to wszystko zostanie skompilowane:

// t/main.cpp
#include "CppUTest/CommandLineTestRunner.h"
int main(int ac, char** av) {
return CommandLineTestRunner::RunAllTests(ac, av);
}

Teraz możemy napisać nasz pierwszy moduł testowy:

// t/test.cpp
#include "CppUTest/TestHarness.h"
#include "code.h"
TEST_GROUP(AwesomeExamples)
{
};
TEST(AwesomeExamples, FirstExample)
{
    int x = test_func();
    CHECK_EQUAL(1, x);
}

Następnie musimy napisać pliki make.  Będziemy potrzebować dwóch: jednego dla plików projektu w src/, i jednego dla testów.

Najpierw należy napisać trochę kodu!

Nasz projekt testowy będzie miał plik 'main' i zawierał bibliotekę narzędziową o nazwie 'code'. Biblioteka dostarczy prostą funkcję, która zwróci 1 (na razie). Pliki będą uporządkowane w ten sposób:

├── src
├── code
├── code.cpp
└── code.h
└── main.cpp
└── t
    ├── main.cpp
    └── test.cpp

Zacznijmy od napisania plików src/

// 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

Teraz zróbmy testy, które będą znajdować się w katalogu t/.  Pierwszą rzeczą do zrobienia jest skonfigurowanie runnera testów, który uruchomi nasze pliki testowe. To także jest funkcja 'main' , która wykona się, gdy to wszystko zostanie skompilowane:

// t/main.cpp
#include "CppUTest/CommandLineTestRunner.h"
int main(int ac, char** av) {
return CommandLineTestRunner::RunAllTests(ac, av);
}

Teraz możemy napisać nasz pierwszy moduł testowy:

// t/test.cpp
#include "CppUTest/TestHarness.h"
#include "code.h"
TEST_GROUP(AwesomeExamples)
{
};
TEST(AwesomeExamples, FirstExample)
{
    int x = test_func();
    CHECK_EQUAL(1, x);
}

Następnie musimy napisać pliki make.  Będziemy potrzebować dwóch: jednego dla plików projektu w src/, i jednego dla testów.

Najpierw należy napisać trochę kodu!

Nasz projekt testowy będzie miał plik 'main' i zawierał bibliotekę narzędziową o nazwie 'code'. Biblioteka dostarczy prostą funkcję, która zwróci 1 (na razie). Pliki będą uporządkowane w ten sposób:

├── src
├── code
├── code.cpp
└── code.h
└── main.cpp
└── t
    ├── main.cpp
    └── test.cpp

Zacznijmy od napisania plików src/

// 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

Teraz zróbmy testy, które będą znajdować się w katalogu t/.  Pierwszą rzeczą do zrobienia jest skonfigurowanie runnera testów, który uruchomi nasze pliki testowe. To także jest funkcja 'main' , która wykona się, gdy to wszystko zostanie skompilowane:

// t/main.cpp
#include "CppUTest/CommandLineTestRunner.h"
int main(int ac, char** av) {
return CommandLineTestRunner::RunAllTests(ac, av);
}

Teraz możemy napisać nasz pierwszy moduł testowy:

// t/test.cpp
#include "CppUTest/TestHarness.h"
#include "code.h"
TEST_GROUP(AwesomeExamples)
{
};
TEST(AwesomeExamples, FirstExample)
{
    int x = test_func();
    CHECK_EQUAL(1, x);
}

Następnie musimy napisać pliki make.  Będziemy potrzebować dwóch: jednego dla plików projektu w src/, i jednego dla testów.

Plik Makefile projektu

Plik makefile projektu będzie na tym samym poziomie co katalogi ‘src’ i ‘t’ w głównym katalogu projektu. Powinien wyglądać tak:

# 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)

Zauważ, że to używa ‘make -C’  dla celów testowych – co oznacza, że wywoła ‘make’  ponownie używając pliku makefile w katalogu testowym.

W tym momencie możemy skompilować kod ‘src’ za pomocą pliku makefile i zobaczyć, że działa:

[]$ 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

Plik makefile projektu będzie na tym samym poziomie co katalogi ‘src’ i ‘t’ w głównym katalogu projektu. Powinien wyglądać tak:

# 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)

Zauważ, że to używa ‘make -C’  dla celów testowych – co oznacza, że wywoła ‘make’  ponownie używając pliku makefile w katalogu testowym.

W tym momencie możemy skompilować kod ‘src’ za pomocą pliku makefile i zobaczyć, że działa:

[]$ 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

Plik makefile projektu będzie na tym samym poziomie co katalogi ‘src’ i ‘t’ w głównym katalogu projektu. Powinien wyglądać tak:

# 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)

Zauważ, że to używa ‘make -C’  dla celów testowych – co oznacza, że wywoła ‘make’  ponownie używając pliku makefile w katalogu testowym.

W tym momencie możemy skompilować kod ‘src’ za pomocą pliku makefile i zobaczyć, że działa:

[]$ 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

Testy Makefile

Dla testów sprawy są nieco bardziej złożone, ponieważ musimy odpowiednio załadować i zintegrować się z biblioteką CppUTest.

Repozytorium CppUTest dostarcza plik o nazwie „MakefileWorker.mk”. Oferuje on wiele funkcji, które ułatwiają budowanie z CppUTest. Plik znajduje się w katalogu „build” w repozytorium git. Na potrzeby tego samouczka założymy, że został skopiowany do katalogu 't/'. Może być użyty w następujący sposób:

# 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

Uwaga: CPPUTEST_HOME musi być ustawione na miejsce, w którym zainstalowano CppUTest. Jeśli zainstalowałeś pakiet z dystrybucji, zazwyczaj będzie to w /usr/local w systemie linux/mac. Jeśli samodzielnie sklonowałeś repozytorium, jest to tam, gdzie to klonowanie się znajduje.

Te opcje są wszystkie udokumentowane w MakefileWorker.mk.

MakefileWorker.mk dodaje również kilka celów makefile, w tym następujące:

  1. wszystkie – buduje testy wskazane przez makefile

  2. czyść – usuwa wszystkie pliki obiektowe i gcov utworzone dla testów

  3. naprawdę czyść – usuwa wszelkie pliki obiektowe lub gcov w całym drzewie katalogów

  4. flagi – wypisuje wszystkie skonfigurowane flagi używane do kompilacji testów

  5. debug – wypisuje wszystkie pliki źródłowe, obiekty, zależności i 'rzeczy do czyszczenia'


Komponent

Cel

Kluczowe pliki / flagi

Uwagi

Makefile projektu

Buduje główny kod źródłowy

Makefile na poziomie root używający make -C

Kompiluje src/ i deleguje testy do t/

Makefile testów

Buduje i łączy testy z CppUTest

t/Makefile odwołujący się do MakefileWorker.mk

Obsługuje kompilację testu, łączenie i flagi biblioteki

MakefileWorker.mk

Oferuje wielokrotnego użytku logikę budowy

Znajduje się w katalogu CppUTest /build

Dodaje cele: wszystkie, czyść, naprawdę czyść, flagi, debug

Integracja GCov

Umożliwia raportowanie pokrycia kodu

CPPUTEST_USE_GCOV=Y

Produkuje pliki .gcov, raporty HTML

Wykrywanie wycieków pamięci

Wykrywa wycieki malloc/free

CPPUTEST_USE_MEM_LEAK_DETECTION

Włączone domyślnie; można je wyłączyć ustawiając =N

Uruchamiacz testów

Wykonuje grupy testowe

CommandLineTestRunner

Wymagany główny punkt wejścia do uruchamiania testów

Dla testów sprawy są nieco bardziej złożone, ponieważ musimy odpowiednio załadować i zintegrować się z biblioteką CppUTest.

Repozytorium CppUTest dostarcza plik o nazwie „MakefileWorker.mk”. Oferuje on wiele funkcji, które ułatwiają budowanie z CppUTest. Plik znajduje się w katalogu „build” w repozytorium git. Na potrzeby tego samouczka założymy, że został skopiowany do katalogu 't/'. Może być użyty w następujący sposób:

# 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

Uwaga: CPPUTEST_HOME musi być ustawione na miejsce, w którym zainstalowano CppUTest. Jeśli zainstalowałeś pakiet z dystrybucji, zazwyczaj będzie to w /usr/local w systemie linux/mac. Jeśli samodzielnie sklonowałeś repozytorium, jest to tam, gdzie to klonowanie się znajduje.

Te opcje są wszystkie udokumentowane w MakefileWorker.mk.

MakefileWorker.mk dodaje również kilka celów makefile, w tym następujące:

  1. wszystkie – buduje testy wskazane przez makefile

  2. czyść – usuwa wszystkie pliki obiektowe i gcov utworzone dla testów

  3. naprawdę czyść – usuwa wszelkie pliki obiektowe lub gcov w całym drzewie katalogów

  4. flagi – wypisuje wszystkie skonfigurowane flagi używane do kompilacji testów

  5. debug – wypisuje wszystkie pliki źródłowe, obiekty, zależności i 'rzeczy do czyszczenia'


Komponent

Cel

Kluczowe pliki / flagi

Uwagi

Makefile projektu

Buduje główny kod źródłowy

Makefile na poziomie root używający make -C

Kompiluje src/ i deleguje testy do t/

Makefile testów

Buduje i łączy testy z CppUTest

t/Makefile odwołujący się do MakefileWorker.mk

Obsługuje kompilację testu, łączenie i flagi biblioteki

MakefileWorker.mk

Oferuje wielokrotnego użytku logikę budowy

Znajduje się w katalogu CppUTest /build

Dodaje cele: wszystkie, czyść, naprawdę czyść, flagi, debug

Integracja GCov

Umożliwia raportowanie pokrycia kodu

CPPUTEST_USE_GCOV=Y

Produkuje pliki .gcov, raporty HTML

Wykrywanie wycieków pamięci

Wykrywa wycieki malloc/free

CPPUTEST_USE_MEM_LEAK_DETECTION

Włączone domyślnie; można je wyłączyć ustawiając =N

Uruchamiacz testów

Wykonuje grupy testowe

CommandLineTestRunner

Wymagany główny punkt wejścia do uruchamiania testów

Dla testów sprawy są nieco bardziej złożone, ponieważ musimy odpowiednio załadować i zintegrować się z biblioteką CppUTest.

Repozytorium CppUTest dostarcza plik o nazwie „MakefileWorker.mk”. Oferuje on wiele funkcji, które ułatwiają budowanie z CppUTest. Plik znajduje się w katalogu „build” w repozytorium git. Na potrzeby tego samouczka założymy, że został skopiowany do katalogu 't/'. Może być użyty w następujący sposób:

# 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

Uwaga: CPPUTEST_HOME musi być ustawione na miejsce, w którym zainstalowano CppUTest. Jeśli zainstalowałeś pakiet z dystrybucji, zazwyczaj będzie to w /usr/local w systemie linux/mac. Jeśli samodzielnie sklonowałeś repozytorium, jest to tam, gdzie to klonowanie się znajduje.

Te opcje są wszystkie udokumentowane w MakefileWorker.mk.

MakefileWorker.mk dodaje również kilka celów makefile, w tym następujące:

  1. wszystkie – buduje testy wskazane przez makefile

  2. czyść – usuwa wszystkie pliki obiektowe i gcov utworzone dla testów

  3. naprawdę czyść – usuwa wszelkie pliki obiektowe lub gcov w całym drzewie katalogów

  4. flagi – wypisuje wszystkie skonfigurowane flagi używane do kompilacji testów

  5. debug – wypisuje wszystkie pliki źródłowe, obiekty, zależności i 'rzeczy do czyszczenia'


Komponent

Cel

Kluczowe pliki / flagi

Uwagi

Makefile projektu

Buduje główny kod źródłowy

Makefile na poziomie root używający make -C

Kompiluje src/ i deleguje testy do t/

Makefile testów

Buduje i łączy testy z CppUTest

t/Makefile odwołujący się do MakefileWorker.mk

Obsługuje kompilację testu, łączenie i flagi biblioteki

MakefileWorker.mk

Oferuje wielokrotnego użytku logikę budowy

Znajduje się w katalogu CppUTest /build

Dodaje cele: wszystkie, czyść, naprawdę czyść, flagi, debug

Integracja GCov

Umożliwia raportowanie pokrycia kodu

CPPUTEST_USE_GCOV=Y

Produkuje pliki .gcov, raporty HTML

Wykrywanie wycieków pamięci

Wykrywa wycieki malloc/free

CPPUTEST_USE_MEM_LEAK_DETECTION

Włączone domyślnie; można je wyłączyć ustawiając =N

Uruchamiacz testów

Wykonuje grupy testowe

CommandLineTestRunner

Wymagany główny punkt wejścia do uruchamiania testów

Pokrycie kodu

Testowanie jednostkowe nie byłoby pełne bez raportu pokrycia. Narzędziem do tego dla projektów używających gcc jest gcov, dostępne jako część standardowego zestawu narzędzi gcc. Cpputest łatwo integruje się z gcov, wystarczy dodać tę linię do pliku makefile:

CPPUTEST_USE_GCOV=Y

Następnie musimy upewnić się, że skrypt filterGcov.sh z tego repo znajduje się w ‘/scripts/filterGcov.sh’ w stosunku do miejsca, w którym ustawiłeś ‘CPPUTEST_HOME’. Musi mieć również odpowiednie uprawnienia do wykonywania.

W przykładowym pliku Makefile, zostałby wdrożony do ‘/usr/local/scripts/filterGcov.sh’. Jeśli uruchamiasz CppUTest z wykonanego repo, wszystko powinno działać bez modyfikacji.

Majac to, możesz po prostu uruchomić ‘make gcov’ i analiza zostanie wygenerowana dla Ciebie. W naszym przypadku będziemy musieli użyć ‘make -B’, aby odbudować pliki obiektowe z włączonym gcov:

[]$ 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

To wygeneruje szereg plików w nowym katalogu ‘gcov’. Są to:

  1. code.cpp.gcov – rzeczywisty plik ‘gcov’ dla testowanego kodu

  2. gcov_error.txt – raport o błędach (w naszym przypadku powinien być pusty)

  3. gcov_output.txt – rzeczywiste wyjście polecenia gcov, które zostało uruchomione

  4. gcov_report.txt – podsumowanie pokrycia dla każdego testowanego pliku

  5. gcov_report.txt.html – wersja html raportu gcov

Testowanie jednostkowe nie byłoby pełne bez raportu pokrycia. Narzędziem do tego dla projektów używających gcc jest gcov, dostępne jako część standardowego zestawu narzędzi gcc. Cpputest łatwo integruje się z gcov, wystarczy dodać tę linię do pliku makefile:

CPPUTEST_USE_GCOV=Y

Następnie musimy upewnić się, że skrypt filterGcov.sh z tego repo znajduje się w ‘/scripts/filterGcov.sh’ w stosunku do miejsca, w którym ustawiłeś ‘CPPUTEST_HOME’. Musi mieć również odpowiednie uprawnienia do wykonywania.

W przykładowym pliku Makefile, zostałby wdrożony do ‘/usr/local/scripts/filterGcov.sh’. Jeśli uruchamiasz CppUTest z wykonanego repo, wszystko powinno działać bez modyfikacji.

Majac to, możesz po prostu uruchomić ‘make gcov’ i analiza zostanie wygenerowana dla Ciebie. W naszym przypadku będziemy musieli użyć ‘make -B’, aby odbudować pliki obiektowe z włączonym gcov:

[]$ 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

To wygeneruje szereg plików w nowym katalogu ‘gcov’. Są to:

  1. code.cpp.gcov – rzeczywisty plik ‘gcov’ dla testowanego kodu

  2. gcov_error.txt – raport o błędach (w naszym przypadku powinien być pusty)

  3. gcov_output.txt – rzeczywiste wyjście polecenia gcov, które zostało uruchomione

  4. gcov_report.txt – podsumowanie pokrycia dla każdego testowanego pliku

  5. gcov_report.txt.html – wersja html raportu gcov

Testowanie jednostkowe nie byłoby pełne bez raportu pokrycia. Narzędziem do tego dla projektów używających gcc jest gcov, dostępne jako część standardowego zestawu narzędzi gcc. Cpputest łatwo integruje się z gcov, wystarczy dodać tę linię do pliku makefile:

CPPUTEST_USE_GCOV=Y

Następnie musimy upewnić się, że skrypt filterGcov.sh z tego repo znajduje się w ‘/scripts/filterGcov.sh’ w stosunku do miejsca, w którym ustawiłeś ‘CPPUTEST_HOME’. Musi mieć również odpowiednie uprawnienia do wykonywania.

W przykładowym pliku Makefile, zostałby wdrożony do ‘/usr/local/scripts/filterGcov.sh’. Jeśli uruchamiasz CppUTest z wykonanego repo, wszystko powinno działać bez modyfikacji.

Majac to, możesz po prostu uruchomić ‘make gcov’ i analiza zostanie wygenerowana dla Ciebie. W naszym przypadku będziemy musieli użyć ‘make -B’, aby odbudować pliki obiektowe z włączonym gcov:

[]$ 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

To wygeneruje szereg plików w nowym katalogu ‘gcov’. Są to:

  1. code.cpp.gcov – rzeczywisty plik ‘gcov’ dla testowanego kodu

  2. gcov_error.txt – raport o błędach (w naszym przypadku powinien być pusty)

  3. gcov_output.txt – rzeczywiste wyjście polecenia gcov, które zostało uruchomione

  4. gcov_report.txt – podsumowanie pokrycia dla każdego testowanego pliku

  5. gcov_report.txt.html – wersja html raportu gcov

Wykrywanie wycieków pamięci Cpputest

Cpputest pozwala na automatyczne wykrywanie wycieków pamięci poprzez zdefiniowanie ponownie standardowej rodziny funkcji „malloc/free” w celu użycia swoich własnych wrapperów. Pozwala to na szybkie wychwytywanie wycieków i zgłaszanie ich dla każdego wykonania testu. Jest to włączone domyślnie w MakefileWorker.mk, więc już działa z krokami przedstawionymi do tej pory.

Aby zilustrować, zróbmy wyciek pamięci w test_func() !

Wracając do code.c, dodajemy malloc()  do funkcji, w ten sposób:

int test_func() {
    malloc(1);
    return 1;
}

Teraz, po ponownym kompilowaniu, pojawia się następujący błąd:

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: <

To pokazuje, który test spowodował wyciek, gdzie wyciek wystąpił w kodzie źródłowym i co było w wyciekniętej pamięci. Bardzo pomocne!

Istnieje kilka zastrzeżeń dotyczących tej funkcji:

  1. Cpputest używa makr preprocesora do dynamicznego zdefiniowania wszystkich wywołań standardowych funkcji zarządzania pamięcią. To oznacza, że będzie działać tylko dla wywołań w kodzie źródłowym będącym przedmiotem testu, ponieważ to jest skompilowane z nadpisaniami CppUTest. Wycieków w powiązanych bibliotekach nie będzie można wychwycić.

  2. Niektóre pamięci, które są alokowane na cały czas życia procesu, nie są przeznaczone do zwolnienia. Może to spowodować wiele męczących błędów, jeśli testujesz moduł z takim zachowaniem. Aby wyłączyć wykrywanie wycieków, możesz to zrobić:

CPPUTEST_USE_MEM_LEAK_DETECTION=N

Cpputest pozwala na automatyczne wykrywanie wycieków pamięci poprzez zdefiniowanie ponownie standardowej rodziny funkcji „malloc/free” w celu użycia swoich własnych wrapperów. Pozwala to na szybkie wychwytywanie wycieków i zgłaszanie ich dla każdego wykonania testu. Jest to włączone domyślnie w MakefileWorker.mk, więc już działa z krokami przedstawionymi do tej pory.

Aby zilustrować, zróbmy wyciek pamięci w test_func() !

Wracając do code.c, dodajemy malloc()  do funkcji, w ten sposób:

int test_func() {
    malloc(1);
    return 1;
}

Teraz, po ponownym kompilowaniu, pojawia się następujący błąd:

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: <

To pokazuje, który test spowodował wyciek, gdzie wyciek wystąpił w kodzie źródłowym i co było w wyciekniętej pamięci. Bardzo pomocne!

Istnieje kilka zastrzeżeń dotyczących tej funkcji:

  1. Cpputest używa makr preprocesora do dynamicznego zdefiniowania wszystkich wywołań standardowych funkcji zarządzania pamięcią. To oznacza, że będzie działać tylko dla wywołań w kodzie źródłowym będącym przedmiotem testu, ponieważ to jest skompilowane z nadpisaniami CppUTest. Wycieków w powiązanych bibliotekach nie będzie można wychwycić.

  2. Niektóre pamięci, które są alokowane na cały czas życia procesu, nie są przeznaczone do zwolnienia. Może to spowodować wiele męczących błędów, jeśli testujesz moduł z takim zachowaniem. Aby wyłączyć wykrywanie wycieków, możesz to zrobić:

CPPUTEST_USE_MEM_LEAK_DETECTION=N

Cpputest pozwala na automatyczne wykrywanie wycieków pamięci poprzez zdefiniowanie ponownie standardowej rodziny funkcji „malloc/free” w celu użycia swoich własnych wrapperów. Pozwala to na szybkie wychwytywanie wycieków i zgłaszanie ich dla każdego wykonania testu. Jest to włączone domyślnie w MakefileWorker.mk, więc już działa z krokami przedstawionymi do tej pory.

Aby zilustrować, zróbmy wyciek pamięci w test_func() !

Wracając do code.c, dodajemy malloc()  do funkcji, w ten sposób:

int test_func() {
    malloc(1);
    return 1;
}

Teraz, po ponownym kompilowaniu, pojawia się następujący błąd:

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: <

To pokazuje, który test spowodował wyciek, gdzie wyciek wystąpił w kodzie źródłowym i co było w wyciekniętej pamięci. Bardzo pomocne!

Istnieje kilka zastrzeżeń dotyczących tej funkcji:

  1. Cpputest używa makr preprocesora do dynamicznego zdefiniowania wszystkich wywołań standardowych funkcji zarządzania pamięcią. To oznacza, że będzie działać tylko dla wywołań w kodzie źródłowym będącym przedmiotem testu, ponieważ to jest skompilowane z nadpisaniami CppUTest. Wycieków w powiązanych bibliotekach nie będzie można wychwycić.

  2. Niektóre pamięci, które są alokowane na cały czas życia procesu, nie są przeznaczone do zwolnienia. Może to spowodować wiele męczących błędów, jeśli testujesz moduł z takim zachowaniem. Aby wyłączyć wykrywanie wycieków, możesz to zrobić:

CPPUTEST_USE_MEM_LEAK_DETECTION=N

Inne wiadomości

Przeczytaj więcej z tej kategorii

A person is standing at a desk while typing on a laptop.

Kompletna platforma oparta na sztucznej inteligencji, która rośnie wraz z Twoim biznesem.

A person is standing at a desk while typing on a laptop.

Kompletna platforma oparta na sztucznej inteligencji, która rośnie wraz z Twoim biznesem.