1) Ściągnij wersję instalacyjną z sieci: Link
lub wersję qt-opensource-linux-x64-5.11.2
2) Nadaj prawa wykonywania plikowi
3) uruchom plik instalacyjny
4) wybierz dodatkowo Desktop gcc 64bit
5) zaakceptuj licencję
6) ściągnij zip z git google test https://github.com/google/googletest rozpakuje do katalogu.
7) uruchom QT i daj nowy projekt/ Other Projekt/ Auto Test Project
8) wybierz Test Framework - Googletest
9) nazwij projekt i ustaw katalog gdzie rozpakowałeś Google Test z Gita (Browse)
Masz skonfigurowany Google Test w QT i utworzony projekt
Tworzenie Testów
wygląd projektu
plik main uruchamia test. Testy dopisujesz w pliku tst_t1.h (Headers)
dodaj swój plik z definicją funkcji/klasy typu cpp do Source (prawy mouse Add existing Files)
pojawi się Folder pod Source i dołączony plik, tu kalkulator.cpp (1)
Wejdź na tst_t1.h (2)
dodaj include z plikiem z prototypem twojej funkcji klasy (typ h) podaj ścieżkę,tu folder wyżej ../
(3)
W miejscu makra TEST piszesz testy.
wywołujesz swoją funkcję z konkretnymi wartościami kalkulator ( 2, 3) = wynik
i porównujesz poleceniami google test tu ASSERT_EQ(war1, war2) (4)
polecenia:
Binary Comparison
This section describes assertions that compare two values.
| Fatal assertion | Nonfatal assertion | Verifies |
|---|---|---|
ASSERT_EQ(val1, val2); | EXPECT_EQ(val1, val2); | val1 == val2 |
ASSERT_NE(val1, val2); | EXPECT_NE(val1, val2); | val1 != val2 |
ASSERT_LT(val1, val2); | EXPECT_LT(val1, val2); | val1 < val2 |
ASSERT_LE(val1, val2); | EXPECT_LE(val1, val2); | val1 <= val2 |
ASSERT_GT(val1, val2); | EXPECT_GT(val1, val2); | val1 > val2 |
ASSERT_GE(val1, val2); | EXPECT_GE(val1, val2); | val1 >= val2 |
expect_eq vs assert_eq
when they fail, ASSERT_* yields a fatal failure and returns from the current function, while EXPECT_* yields a nonfatal failure, allowing the function to continue running.
Normally,
EXPECT_* is the better option since the rest of the test can continue to run and can give useful output. However, ASSERT_* is better if the test shouldn't continue.
Przykład Tworzenia Mocków
LINK kod z github
Dla prostej klasy Kalkulator, która korzysta z obiektów Dodaj i Odejmij:
hpp
class Kalkulator { public: Kalkulator(Dodaj& aa,Odejmij& bb); int dodaj(int a,int b); int odejmij(int a,int b); private: class Dodaj& aa; class Odejmij& bb; };
cpp
#include "kalkulator.h" namespace kalk { Kalkulator::Kalkulator(class Dodaj& aa,class Odejmij& bb):aa(aa),bb(bb){} int Kalkulator::dodaj(int a, int b) { return aa.dodawanie(a,b); } int Kalkulator::odejmij(int a, int b) { return bb.odejmowanie(a,b); } }
hpp Dodaj
class Dodaj { public: Dodaj(); virtual ~Dodaj(); virtual int dodawanie(int a, int b); };
cpp Dodaj
#include "dodaj.h" Dodaj::Dodaj(){} Dodaj::~Dodaj() {} int Dodaj::dodawanie(int a, int b) { return a+b; }
Co ważne, metoda dodawanie z Klasy Dodaj musi być virtualna, ponieważ kiedy tworzymy Mocka (dziedziczącego po Dodaj) musi nadpisać oryginalną metodą (przykład mockowania niewirtualnych później)
Tworzymy Mocki tych Klas: (przykład dla Dodaj)
dod_mock.h
#ifndef DOD_MOCK_H #define DOD_MOCK_H #include "gmock/gmock.h" #include "../kalkulator/dodaj.h" namespace mocks{ class Dod_mock:public kalk::Dodaj { public: Dod_mock(); virtual ~Dod_mock(); MOCK_METHOD2( dodawanie, int(int id, int id2)); }; } //namespace mocks{ #endif // DOD_MOCK_H
dod_mock.cpp
#include "dod_mock.h"
mocks::Dod_mock::Dod_mock(){} mocks::Dod_mock::~Dod_mock(){}
i dodajemy do projektu:
Plik main wygląda standardowo, natomiast plik testowy wygląda tak:
#pragma once #include <gtest/gtest.h> #include <gmock/gmock-matchers.h> #include "dod_mock.h" #include "od_mock.h" #include "../kalkulator/kalkulator.h" using namespace testing; namespace my_test { class Base { public: Base() { vDefineDefaultActions(); } virtual ~Base() {} void vDefineDefaultActions() { // init default action // ON_CALL(m_dpool_mock, DPOOL_enSetPoolData(_, _)) // .WillByDefault(Return(E_DATA_OK)); } //dodawanie mockow NiceMock<mocks::Dod_mock> dod_mock; NiceMock<mocks::Od_mock> od_mock; }; class KlasaTestowa : public Base, public testing::Test { protected: virtual void SetUp() { kalkobj=new kalk::Kalkulator(dod_mock,od_mock); } virtual void TearDown() { delete kalkobj; } kalk::Kalkulator *kalkobj; }; TEST_F(KlasaTestowa, test1) { EXPECT_CALL(dod_mock, dodawanie(_,_)).WillOnce(Return(9)); int ret = kalkobj->dodaj(5,4); EXPECT_EQ(ret, 9); } TEST_F(KlasaTestowa, test2) { EXPECT_CALL(od_mock, odejmowanie(_,_)).Times(2).WillRepeatedly(Return(5)); kalkobj->odejmij(11,6); int ret2 = kalkobj->odejmij(11,6); EXPECT_EQ(ret2, 5); } } //namespace
Tu przykład TEST_F (nie zwykłego TEST) czyli testów bazujących na klasie w której dla każdego testu będą uruchomione standardowe zachowania:
Klasa Base posiada metodę vDefineDefaultActions uruchamianą w konstruktorze, która może uruchamiać deflautową akcję (tu wykomentowany przykład). W klasie bazowej również tworzone są obiekty Mocków, tu za pomocą makra NiceMock.
Stworzone obiekty mocków Dodaj i Odejmij będą później wykorzystane podczas tworzenia obiektu Kalkulator który przyjmuje w konstruktorze referencje na obiekty Dodaj i Odejmij.
KlasaTestowa dziedziczące po (public Base, public testing::Test ) ma dwie metody SetUp która uruchamiana jest na początek testu (tu tworzy obiekt Kalkulatora) i TearDown na koniec (zwalnia pamięć).
TEST_F (Nazwaklasy, nazwatestu)
najpierw wypisujemy czego oczekujemy że będzie wywołane:
EXPECT_CALL(obiektmocka, metoda(argumenty) . polecenie...
argumenty mogą być konkretne, albo "_" wtedy argument nie ma znaczenia
polecenia po kropce: Times (numer) - ile razy ma być wykonane
WillOnce (co ma zwrócić) - raz wykona i mock zwróci to co chcemy
WillRepeatedly(co ma zwrócić) wykona wielokrotnie, można połączyć z Times
następnie wywołujemy metodę testowanego obiektu (i expect_call będzie sprawdzał, czy wywołanie tej metody uruchomi mocka, następnie mock zwróci to co podalismy powyżej):
int ret = kalkobj->dodaj(5,4);
EXPECT_EQ(ret, 9);
tu dodatkowo sprawdzana jest poprawność zwracanej wartości.
Dynamic Mock vs Strict Mock vs Stub
SetArgReferee
podsyłanie do argumentów mocka, innych wartosci/obiektow
https://stackoverflow.com/questions/23156717/gmock-multiple-in-out-parameters-setargreferee
Mocking Private or Protected Methods
Mocking Overloaded Methods
Mocking Class Templates
Mocking Nonvirtual Methods
Mocking Free Functions
Linki:
blog Macieja Amiserowicza - LINK
Google Test dokumentacja github - LINK:
Googletest Primer na github - link1:
A quick introduction to the Google C++ Testing - link2:
Google Test Mocks: - LINK3
Programy wspomagające pisanie testów podczas pisania softu:
NCrunch - LINK
Porównanie Resharper vs. NCrunch vs. VS 2017 - LINK
Bibliotek wspomagająca mockowanie - LINK







