20111130 oa gtest
DESCRIPTION
This is my presentation at BalaBit OpenAcademy about the GoogleTest FrameworkTRANSCRIPT
Google TestGoogle TestCzigány AndrásCzigány András
TémákTémák● Unit teszt: mire jó, miért, mikor, mivel?Unit teszt: mire jó, miért, mikor, mivel?
● Google Test FrameworkGoogle Test Framework
● AlapokAlapok
● FinomságokFinomságok
● ExtrákExtrák
● Lépjünk szintet: Google Mock FrameworkLépjünk szintet: Google Mock Framework
Unit tesztUnit teszt
Unit teszt: mire jó?Unit teszt: mire jó?● Unit: a kód legkisebb, önmagában tesztelhető egységeUnit: a kód legkisebb, önmagában tesztelhető egysége
● C → függvényC → függvény
● C++ → osztályC++ → osztály
● Izoláltan teszteljük a szoftver építőkockáit.Izoláltan teszteljük a szoftver építőkockáit.
● Élő dokumentáció.Élő dokumentáció.
● TDD-nél tervezési funkciója is van.TDD-nél tervezési funkciója is van.
● Ösztönzi az egészséges kód létrehozását.Ösztönzi az egészséges kód létrehozását.
Unit teszt: miért?Unit teszt: miért?
● Szeretsz bugokat javítgatni?Szeretsz bugokat javítgatni?
● Szeretsz doksit írni?Szeretsz doksit írni?
● Változik az elképzelésed kódolás közben?Változik az elképzelésed kódolás közben?
● Használtál kényelmetlen legacy interfészeket?Használtál kényelmetlen legacy interfészeket?
● Írtál komplikált integrációs teszteket?Írtál komplikált integrációs teszteket?
Unit teszt: mikor?Unit teszt: mikor?
● Röviden: MINDIG :-)Röviden: MINDIG :-)
● Ha fontos a szoftver minősége.Ha fontos a szoftver minősége.
● Ha számít mennyit kell karbantartani.Ha számít mennyit kell karbantartani.
● Ha túl sok a komplikált manuális teszt.Ha túl sok a komplikált manuális teszt.
● Ha hiányos a dokumentáció.Ha hiányos a dokumentáció.
● Ha szeretnél gyakran refaktorálni.Ha szeretnél gyakran refaktorálni.
● Ha nem szeretsz tesztet írni.Ha nem szeretsz tesztet írni.
Unit teszt: mivel?Unit teszt: mivel?● Keretrendszerek: CppUnit, CxxTest, Boost.Test, Keretrendszerek: CppUnit, CxxTest, Boost.Test,
UnitTest++, Google TestUnitTest++, Google Test
● Legtöbbjük xUnit felépítésűLegtöbbjük xUnit felépítésű
● Könnyen használható eszköztár:Könnyen használható eszköztár:
● Case, fixture, suitCase, fixture, suit
● Setup, assert, teardownSetup, assert, teardown
Google TestGoogle TestMiért érdemes használni?Miért érdemes használni?
● Hordozható: exception és RTTI nélkül is megy.Hordozható: exception és RTTI nélkül is megy.
● Nem fatális assert: egy futás, összes hiba.Nem fatális assert: egy futás, összes hiba.
● Könnyű információt csatolni egy assert-hez: <<Könnyű információt csatolni egy assert-hez: <<
● Szelektív tesztfuttatás.Szelektív tesztfuttatás.
● Érték és típus parametrizált tesztek.Érték és típus parametrizált tesztek.
● Predikátum assert.Predikátum assert.
● Death assert: várt program összeomlás.Death assert: várt program összeomlás.
● Jól használható API, extra igényekhez.Jól használható API, extra igényekhez.
Alapok: TEST(...)Alapok: TEST(...)Elég a dumából, írjunk tesztet:Elég a dumából, írjunk tesztet:
#include "sample1.h"#include "gtest/gtest.h"TEST(FactorialTest, Zero) { ASSERT_EQ(1, Factorial(0));}
int main(int argc, char **argv) { testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS();}
Alapok: ASSERT_*Alapok: ASSERT_*● Érték, objektum:Érték, objektum:
● TRUE, FALSETRUE, FALSE
● EQ, NE, LT, LE, GT, GEEQ, NE, LT, LE, GT, GE
● FLOAT_EQ, DOUBLE_EQ, NEARFLOAT_EQ, DOUBLE_EQ, NEAR
● C sztring:C sztring:
● STREQ, STRNESTREQ, STRNE
● STRCASEEQ, STRCASENESTRCASEEQ, STRCASENE
● Nem fatális: EXPECT_*Nem fatális: EXPECT_*
Alapok: fixtúrák I.Alapok: fixtúrák I.class QueueTest : public ::testing::Test {
protected: virtual void SetUp() { q1_.Enqueue(1); q2_.Enqueue(2); q2_.Enqueue(3); }
// virtual void TearDown() {}
Queue<int> q0_; Queue<int> q1_; Queue<int> q2_;};
Alapok: fixtúrák II.Alapok: fixtúrák II.TEST_F(QueueTest, IsEmptyInitially) { EXPECT_EQ(0, q0_.size());}
TEST_F(QueueTest, DequeueWorks) { int* n = q0_.Dequeue(); EXPECT_EQ(NULL, n);
n = q1_.Dequeue(); ASSERT_TRUE(n != NULL); EXPECT_EQ(1, *n); EXPECT_EQ(0, q1_.size()); delete n;
n = q2_.Dequeue(); ASSERT_TRUE(n != NULL); EXPECT_EQ(2, *n); EXPECT_EQ(1, q2_.size()); delete n;}
Control flowControl flowHa control flow alapján dől el:Ha control flow alapján dől el:
● SUCCEED()SUCCEED()
● FAIL(), ADD_FAILURE(), FAIL(), ADD_FAILURE(), ADD_FAILURE_AT(“file_path”, line_number)ADD_FAILURE_AT(“file_path”, line_number)
switch(expression) { case 1: ... some checks ... case 2: ... some other checks ... default: FAIL() << "We shouldn't get here.";}
ExceptionExceptionASSERT_*, EXPECT_*:ASSERT_*, EXPECT_*:
● Típusos: THROWTípusos: THROW
● Bármi: ANY_THROWBármi: ANY_THROW
● Semmi: NO_THROWSemmi: NO_THROW
ASSERT_THROW(Foo(5), bar_exception);
EXPECT_NO_THROW({ int n = 5; Bar(&n);});
ASSERT_*, EXPECT_*:ASSERT_*, EXPECT_*:
● PRED1(bool (*pred1fv)(arg1), test_arg1)PRED1(bool (*pred1fv)(arg1), test_arg1)
● Jelenleg öt argumentumig implementált.Jelenleg öt argumentumig implementált.
// Returns true iff m and n have no common divisors except 1.bool MutuallyPrime(int m, int n) { ... }
EXPECT_PRED2(MutuallyPrime, 3, 4); // SUCCEED()EXPECT_PRED2(MutuallyPrime, 4, 10); // FAIL()
PredikátumPredikátum
Extrák: death tesztelésExtrák: death tesztelésASSERT_*, EXPECT_*:ASSERT_*, EXPECT_*:
● DEATH, DEATH_IF_SUPPORTEDDEATH, DEATH_IF_SUPPORTED
● EXITEXIT
TEST(MyDeathTest, Foo) { // This death test uses a compound statement. ASSERT_DEATH({ int n = 5; Foo(&n); }, "Error on line .* of Foo()"); }
TEST(MyDeathTest, NormalExit) { EXPECT_EXIT(NormalExit(), ::testing::ExitedWithCode(0), "Success"); }
TEST(MyDeathTest, KillMyself) { EXPECT_EXIT(KillMyself(), ::testing::KilledBySignal(SIGKILL), "Sending myself unblockable signal"); }
Extrák: SCOPED_TRACEExtrák: SCOPED_TRACEvoid Sub1(int n) { EXPECT_EQ(1, Bar(n)); EXPECT_EQ(2, Bar(n + 1));}
TEST(FooTest, Bar) { { SCOPED_TRACE("A"); Sub1(1); } // Now it won't. Sub1(9);}
Extrák: TRACE kimenetExtrák: TRACE kimenetpath/to/foo_test.cc:11: Failure
Value of: Bar(n)
Expected: 1
Actual: 2
Trace:
path/to/foo_test.cc:17: A
path/to/foo_test.cc:12: Failure
Value of: Bar(n + 1)
Expected: 2
Actual: 3
Extrák: globális fixtúraExtrák: globális fixtúraclass Environment {
public:
virtual ~Environment() {}
// Override this to define how to set up the environment.
virtual void SetUp() {}
// Override this to define how to tear down the environment.
virtual void TearDown() {}
};
// in main()AddGlobalTestEnvironment(Environment* env);
Extrák: érték paraméterExtrák: érték paraméter
class FooTest : public ::testing::TestWithParam<const char*> { // You can implement all the usual fixture class members here.};
TEST_P(FooTest, DoesBlah) { EXPECT_TRUE(foo.Blah(GetParam())); ...}
TEST_P(FooTest, HasBlahBlah) { ... }
INSTANTIATE_TEST_CASE_P(InstantiationName, FooTest, ::testing::Values("meeny", "miny", "moe"));
Extrák: érték paraméter II.Extrák: érték paraméter II.● Values(v1, v2, ..., vN)Values(v1, v2, ..., vN)
● ValuesIn(container)ValuesIn(container)
● ValuesIn(begin, end)ValuesIn(begin, end)
● Range(begin, end[, step])Range(begin, end[, step])
● Bool() = Values(false, true)Bool() = Values(false, true)
● Combine(g1, g2, ..., gN) -> requires <tr1/tuple>Combine(g1, g2, ..., gN) -> requires <tr1/tuple>
end nem része az értékhalmaznakend nem része az értékhalmaznak
Extrák: típus paraméterExtrák: típus paramétertemplate <typename T>class FooTest : public ::testing::Test { ... }
TYPED_TEST_CASE_P(FooTest);
TYPED_TEST_P(FooTest, DoesBlah) { // Inside a test, refer to TypeParam to get the type parameter. TypeParam n = 0; ...}
TYPED_TEST_P(FooTest, HasPropertyA) { ... }
REGISTER_TYPED_TEST_CASE_P(FooTest, DoesBlah, HasPropertyA);
typedef ::testing::Types<char, int, unsigned int> MyTypes;
INSTANTIATE_TYPED_TEST_CASE_P(My, FooTest, MyTypes);
INSTANTIATE_TYPED_TEST_CASE_P(My, FooTest, int);
Extrák: teszt eseményekExtrák: teszt események
● Listener APIListener API
● UnitTestUnitTest
● TestCaseTestCase
● TestInfoTestInfo
● TestPartResultTestPartResult
● Result printer (Sample 9)Result printer (Sample 9)
● Memory Leak checker (Sample 10)Memory Leak checker (Sample 10)
Extrák: unit test CLIExtrák: unit test CLI
● unit --helpunit --help
● unit --gtest_list_testsunit --gtest_list_tests
● unit --gtest_filter=<regexp>-<!regexp>unit --gtest_filter=<regexp>-<!regexp>
● unit --gtest_repeat=<times>unit --gtest_repeat=<times>
● unit --gtest_shuffleunit --gtest_shuffle
● unit --gtest_output=”xml:<output_file>”unit --gtest_output=”xml:<output_file>”
● Integrálás: debugger, test frameworkIntegrálás: debugger, test framework
● Tesztek szétosztása gépek közöttTesztek szétosztása gépek között
Google MockGoogle Mock● Osztályok izolált teszteléséhezOsztályok izolált teszteléséhez
● Elvárásokkal preparálhatjuk a függőségeketElvárásokkal preparálhatjuk a függőségeket
● Ellenőrizhetjük objektumainkat:Ellenőrizhetjük objektumainkat:
● Hányszor érték elHányszor érték el
● Milyen argumentumokkalMilyen argumentumokkal
● Mi volt a visszatérési értékMi volt a visszatérési érték
az interakció során.az interakció során.
LinkekLinkek● C++ unit teszt keretrendszerek:C++ unit teszt keretrendszerek:
http://en.wikipedia.org/wiki/List_of_unit_testing_frameworks#C.2B.2Bhttp://en.wikipedia.org/wiki/List_of_unit_testing_frameworks#C.2B.2B
● Kent Beck – xUnit testing framework:Kent Beck – xUnit testing framework:http://www.xprogramming.com/testfram.htmhttp://www.xprogramming.com/testfram.htm
● Noel Llopis – C++ framework comparison:Noel Llopis – C++ framework comparison:http://gamesfromwithin.com/exploring-the-c-unit-testing-framework-junglehttp://gamesfromwithin.com/exploring-the-c-unit-testing-framework-jungle
● CppUnit:CppUnit:https://launchpad.net/cppunit2https://launchpad.net/cppunit2
● CxxTest:CxxTest:http://cxxtest.sourceforge.net/http://cxxtest.sourceforge.net/
● UnitTest++:UnitTest++:http://unittest-cpp.sourceforge.net/http://unittest-cpp.sourceforge.net/
● Boost.Test:Boost.Test:http://www.boost.org/doc/libs/release/libs/test/index.htmlhttp://www.boost.org/doc/libs/release/libs/test/index.html
● Google Test Framework:Google Test Framework:http://code.google.com/p/googletest/http://code.google.com/p/googletest/
● Google Mock Framework:Google Mock Framework:http://code.google.com/p/googlemock/http://code.google.com/p/googlemock/
Köszönöm a Köszönöm a figyelmet!figyelmet!
Kérdések?Kérdések?