IT Talks

Google C++ Testing Framework ์‹œ์ž‘ํ•˜๊ธฐ

OkOJJ 2011. 9. 15. 18:07



Google C++ Testing Framework ์‹œ์ž‘ํ•˜๊ธฐ




Introduction

Google C++ Testing Framework(์ดํ•˜ google test)์€ ๋” ๋‚˜์€ C++ test๋ฅผ ์œ„ํ•œ tool์ด๋‹ค. ๋˜ Linux, Mac, Windows ๋ชจ๋‘์—์„œ ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•˜๋‹ค.
์ข‹์€ test๋ฅผ ์œ„ํ•ด Google test๊ฐ€ ์ดˆ์ ์„ ๋งž์ถ”๊ณ  ์žˆ๋Š” ๋‚ด์šฉ์€ ์•„๋ž˜์™€ ๊ฐ™๋‹ค.

1. Test๋Š” ๋…๋ฆฝ์ ์ด์–ด์•ผ ํ•˜๊ณ  ๋ฐ˜๋ณต๊ฐ€๋Šฅํ•ด์•ผ ํ•œ๋‹ค.
  Success ํ˜น์€ Fail์ธ test๋ฅผ debug ํ•˜๋Š” ์ผ์€ ํž˜๋“  ์ผ์ด๋ผ google test๋Š” test๋ฅผ ๋ณ„๋„์˜ object๋กœ ๋ถ„๋ฆฌํ•ด ๋…๋ฆฝ์ ์œผ๋กœ ์ˆ˜ํ–‰๋˜๋„๋ก ๋งŒ๋“ ๋‹ค. Test fail์ธ ๊ฒฝ์šฐ google test์—์„œ๋Š” ์‹คํŒจํ•œ case๋งŒ ๋ณ„๋„๋กœ ์ˆ˜ํ–‰ํ•ด ๋น ๋ฅธ debugging์ด ๊ฐ€๋Šฅํ•˜๋„๋ก ์ง€์›ํ•œ๋‹ค.

2. Test๋Š” ์ž˜ ์กฐ์ง๋˜์–ด ์žˆ์–ด์•ผ ํ•˜๊ณ , test๋˜๋Š” code์˜ ๊ตฌ์กฐ๋ฅผ ์ž˜ ๋ฐ˜์˜ํ•˜๊ณ  ์žˆ์–ด์•ผ๋งŒ ํ•œ๋‹ค.
  Google test๋Š” ๊ฐ™์ด ๊ณต์œ ํ•  ์ˆ˜ ์žˆ๋Š” data์™€ subroutine์„ ๊ฐ€์ง„ testcase๋“ค๋กœ ๊ตฌ์„ฑํ•˜๋Š” ๊ฒƒ์ด ๊ฐ€๋Šฅํ•˜๋‹ค. ์ด๋Ÿฌํ•œ ๊ณตํ†ต์ ์ธ ํŒจํ„ด๋“ค์ด test๋ฅผ ์ดํ•ดํ•˜๊ธฐ ์‰ฝ๊ฒŒ ํ•˜๊ณ  ์œ ์ง€๋ณด์ˆ˜๊ฐ€ ์šฉ์ดํ•˜๊ฒŒ ๋งŒ๋“ค์–ด์ค€๋‹ค.

3. Test๋Š” portable ํ•ด์•ผํ•˜๋ฉฐ ์žฌ์‚ฌ์šฉ์ด ๊ฐ€๋Šฅํ•ด์•ผ ํ•œ๋‹ค.
  Open source community๋Š” ํ”Œ๋žซํผ์— ์ข…์†์ ์ธ ๋งŽ์€ source code๋“ค์„ ๋ณด์œ ํ•˜๊ณ  ์žˆ์œผ๋ฉฐ ์ด๋“ค์„ testํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” test ๋˜ํ•œ ํŠน์ • ํ”Œ๋žซํผ์— ์ข…์†์ ์ด์–ด์•ผ ํ•œ๋‹ค. ๊ทธ๋ž˜์„œ google test๋Š” ๋‹ค์–‘ํ•œ OS์™€ compiler๋ฅผ ์ง€์›ํ•˜๋ฉฐ ๋‹ค์–‘ํ•œ ์„ค์ •์œผ๋กœ ๋™์ž‘์ด ๊ฐ€๋Šฅํ•˜๋‹ค.

4. Test๊ฐ€ ์‹คํŒจํ–ˆ์„ ๋•Œ, ๋ฌธ์ œ์— ๋Œ€ํ•œ ์ •๋ณด๋“ค์„ ๊ฐ€๋Šฅํ•œ ๋งŽ์ด ์ œ๊ณตํ•ด์•ผ ํ•œ๋‹ค.
  Google test๋Š” ์ฒซ๋ฒˆ์งธ ์‹คํŒจ ์‹œ์ ์—์„œ ๋ฉˆ์ถ”์ง€ ์•Š๋Š”๋‹ค. ๋Œ€์‹ ์— ํ˜„์žฌ์˜ test๋Š” ์ค‘๋‹จ์‹œํ‚ค๊ณ , ๋‹ค์Œ์˜ test๋กœ ๊ณ„์† ์ง„ํ–‰๋˜๋„๋ก ํ•œ๋‹ค. ํ˜„์žฌ์˜ test๊ฐ€ ์ง€๋‚˜๊ฐ„ ํ›„์— ์น˜๋ช…์ ์ด์ง€ ์•Š์€ ์‹คํŒจ์— ๋Œ€ํ•ด report ํ•˜๋„๋ก ์„ค์ •ํ•˜๋Š” ๊ฒƒ์ด ๊ฐ€๋Šฅํ•ด์„œ ์—ฌ๋Ÿฌ๊ฐœ์˜ bug๋“ค์„ ๋ฐœ๊ฒฌํ•˜๊ณ  ์ˆ˜์ •ํ•  ์ˆ˜ ์žˆ๋‹ค.

5. Testing framework์€ test ์ž‘์„ฑ์ž๋“ค์„ ๋‹ค๋ฅธ ์ผ๋“ค์—์„œ ํ•ด๋ฐฉ์‹œํ‚ค๊ณ  test ๋‚ด์šฉ์—๋งŒ ์ง‘์ค‘ํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋งŒ๋“ค์–ด์ค˜์•ผ ํ•œ๋‹ค.
  Google test๋Š” ์ด๋ฏธ ์ •์˜๋œ test๋“ค์€ ์œ ์ง€ํ•ด ๋‘๊ธฐ ๋•Œ๋ฌธ์— test ์‹คํ–‰์„ ์œ„ํ•ด ์‚ฌ์šฉ์ž๋“ค์ด ๋˜ ๋‹ค์‹œ ๋‚˜์—ดํ•  ํ•„์š”๊ฐ€ ์—†๋„๋ก ํ•œ๋‹ค.

6. Test๋Š” ๋นจ๋ผ์•ผ๋งŒ ํ•œ๋‹ค.
  Google test๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด test ์‚ฌ์ด์—์„œ์˜ ๊ณต์œ ๋œ ์ž์›๋“ค์„ ์žฌ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

Google test๋Š” xUnit architecture ๊ธฐ๋ฐ˜์œผ๋กœ ๋งŒ๋“ค์–ด์กŒ๊ธฐ ๋•Œ๋ฌธ์— JUnit์ด๋‚˜ PyUnit์„ ์‚ฌ์šฉํ•  ๋•Œ์™€ ๋น„์Šทํ•˜์—ฌ ๋น ๋ฅด๊ฒŒ ์ ์šฉํ•˜๊ธฐ ์ข‹๋‹ค.



Setting up a New Test Project

Google test๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•ด์„  Google test๋ฅผ compile ํ•ด์„œ ์‚ฌ์šฉ์ž์˜ test์— library๋กœ link ํ•ด์•ผ๋งŒ ํ•˜๋ฉฐ, ์ž์ฃผ ์‚ฌ์šฉ๋˜๋Š” build system์— ๋Œ€ํ•œ build file์„ ์ œ๊ณตํ•˜๊ณ  ์žˆ๋‹ค.(msvc, xcode, make, codegear, scons directory) ๋งŒ์•ฝ ๊ธฐ๋ณธ์œผ๋กœ ์ œ๊ณต๋˜๋Š” ๊ฒƒ๊ณผ ๋‹ค๋ฅธ system์„ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ๋‹ค๋ฉด make/Makefile์„ ์ฐธ์กฐํ•˜๋ฉด ๋˜๋Š”๋ฐ, ๊ธฐ๋ณธ์ ์œผ๋กœ src/gtest-all.cc์™€ GTEST_ROOT, GTEST_ROOT/include๋ฅผ compile ํ•ด์•ผ๋งŒ ํ•œ๋‹ค.(GTEST_ROOT : Google test root directory)

Google test library๋ฅผ compile ํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋˜์—ˆ๋‹ค๋ฉด project๋ฅผ ์ƒ์„ฑํ•ด์„œ ์‚ฌ์šฉ์ž์˜ test program์„ ์œ„ํ•œ build target์„ ์ˆ˜ํ–‰ํ•ด์•ผ๋งŒ ํ•œ๋‹ค. ๋˜ ์‚ฌ์šฉ์ž์˜ test๋ฅผ compile ํ•  ๋•Œ, compiler๊ฐ€ gtest/gtest.h๋ฅผ ์ฐพ์„ ์ˆ˜ ์žˆ๊ฒŒ GTEST_ROOT/include ๋ฅผ ํฌํ•จํ•ด์•ผ๋งŒ ํ•œ๋‹ค.



Basic Concepts

Google test๋ฅผ ์‚ฌ์šฉํ•  ๋•Œ condition์ด true์ธ์ง€๋ฅผ ํ™•์ธํ•˜๋Š” assertion์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์œผ๋กœ ์‹œ์ž‘ํ•˜๋Š” ๊ฒƒ์ด ์ข‹๋‹ค. Assertion์˜ ๊ฒฐ๊ณผ๋Š” success, nonfatal failure, fatal failure ์ค‘์— ํ•˜๋‚˜๊ฐ€ ๋  ์ˆ˜ ์žˆ์œผ๋ฉฐ, fatal failure๊ฐ€ ๋ฐœ์ƒํ–ˆ๋‹ค๋ฉด ํ˜„์žฌ์˜ function์€ ์ค‘๋‹จ๋  ๊ฒƒ์ด๋‹ค. (ํ•˜์ง€๋งŒ ์ „์ฒด program์€ ์ •์ƒ์ ์œผ๋กœ ์ง„ํ–‰๋จ)

Testcase๋Š” ํ•˜๋‚˜ ์ด์ƒ์˜ test๋กœ ๊ตฌ์„ฑ๋  ์ˆ˜ ์žˆ๋Š”๋ฐ ์‚ฌ์šฉ์ž๋Š” code์˜ ๊ตฌ์กฐ๋ฅผ ๋ฐ˜์˜ํ•  ์ˆ˜ ์žˆ๋„๋ก ์—ฌ๋Ÿฌ๊ฐœ์˜ testcase๋“ค๋กœ grouping์ด ๊ฐ€๋Šฅํ•˜๋ฉฐ, ๋ณต์ˆ˜์˜ test๊ฐ€ common object๋‚˜ subroutine์„ ๊ณต์œ ํ•ด์•ผ ํ•œ๋‹ค๋ฉด ๊ทธ๋Ÿฐ ๊ฒƒ๋“ค์„ test fixture class์— ๋„ฃ์–ด๋‘๊ณ  ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.



Assertions

Google test์˜ assertion์€ function call๋กœ ๊ตฌ์„ฑ๋œ macro์ด๋‹ค. Assertion์ด fail๋กœ ๋๋‚˜๊ฒŒ ๋˜๋ฉด, google test๋Š” assertion์˜ source file, line number, failure message ๋“ค์„ ํ™”๋ฉด์— ์ถœ๋ ฅํ•œ๋‹ค.

Assertion์€ ๊ฐ™์ง€๋งŒ ํ˜„์žฌ์˜ function์€ ๋‹ค๋ฅด๊ฒŒ ์ฒ˜๋ฆฌํ•˜๋Š” function ๋“ค์˜ ์ง์œผ๋กœ ๊ตฌ์„ฑ๋˜์–ด ์žˆ๋Š”๋ฐ, ASSERT_XXX ์˜ ํ˜•ํƒœ๋กœ ๊ตฌ์„ฑ๋œ assertion์€ fatal failure๋ฅผ ๋ฐœ์ƒ์‹œ์ผœ ํ˜„์žฌ์˜ function์„ ์ค‘๋‹จ์‹œํ‚ค๋ฉฐ, EXPECT_XXX ํ˜•ํƒœ์˜ assertion์€ nonfatal failure๋ฅผ ๋ฐœ์ƒ์‹œํ‚ค๊ณ  ํ˜„์žฌ ์ˆ˜ํ–‰์ค‘์ธ function์„ ์ค‘๋‹จ์‹œํ‚ค์ง€ ์•Š๋Š”๋‹ค.

Custom failure message ๋ฅผ ์‚ฌ์šฉํ•˜๋ ค๋ฉด, '<<' ์—ฐ์‚ฐ์ž๋ฅผ ์ด์šฉํ•ด์„œ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ๋‹ค. ์˜ˆ์ œ๋Š” ์•„๋ž˜์™€ ๊ฐ™๋‹ค.

ASSERT_EQ(x.size(), y.size()) << "Vectors x and y are of unequal length";

for (int i = 0; i < x.size(); ++i) {
  EXPECT_EQ
(x[i], y[i]) << "Vectors x and y differ at index " << i;
}

๋งŒ์•ฝ wchar_t*, TCHAR* ๋“ฑ์˜ wide string์„ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ๋‹ค๋ฉด, ์ถœ๋ ฅ๋˜๋ฉด์„œ ์ž๋™์œผ๋กœ UTF-8๋กœ ๋ณ€ํ™˜๋œ๋‹ค.



Basic Assertions


์•ž์—์„œ๋„ ์–ธ๊ธ‰๋˜์—ˆ์ง€๋งŒ ASSERT_XXX๋Š” fatal failure๋ฅผ ๋ฐœ์ƒ์‹œํ‚ค๋ฉฐ, EXPECT_XXX๋Š” nonfatal failure๋ฅผ ๋ฐœ์ƒ์‹œํ‚จ๋‹ค.



Binary Comparison

์—ฌ๊ธฐ์—์„œ๋Š” ๋‘ ๊ฐ’์„ ๋น„๊ตํ•˜๋Š” assertion ๊ตฌ๋ฌธ๋“ค์„ ์„ค๋ช…ํ•œ๋‹ค.


์‹คํŒจํ–ˆ์„ ๊ฒฝ์šฐ google test๋Š” ๋‘ ๊ฐ€์ง€ ๊ฐ’ val1, val2๋ฅผ ์ถœ๋ ฅํ•˜๊ฒŒ ๋˜๋Š”๋ฐ ์‚ฌ์šฉ์ž๊ฐ€ test ํ•˜๊ณ ์ž ํ•˜๋Š” ๊ตฌ๋ฌธ์€ actual์—, expected value๋Š” expected ํ•ญ๋ชฉ์— ๋„ฃ์–ด์ฃผ์–ด์•ผ ํ•œ๋‹ค.

์ด๋Ÿฌํ•œ assertion ๊ตฌ๋ฌธ๋“ค์€ ์‚ฌ์šฉ์ž ์ •์˜ operator๋“ค์— ๋Œ€ํ•ด์„œ๋„ ๋™์ž‘์ด ๊ฐ€๋Šฅํ•œ๋ฐ, ๋งŒ์•ฝ ์‚ฌ์šฉ์ž ์ •์˜ ์—ฐ์‚ฐ์ž๋“ค์„ ์‚ฌ์šฉํ•˜๊ฒŒ ๋œ๋‹ค๋ฉด ASSERT_XXX ๊ตฌ๋ฌธ์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ์ข‹๋‹ค. ์™œ๋ƒํ•˜๋ฉด ASSERT_XXX ๊ตฌ๋ฌธ์€ ๋น„๊ต ๊ฒฐ๊ณผ ๋ฟ๋งŒ ์•„๋‹ˆ๊ณ , ๋‘ ๊ฐœ์˜ operand ๋“ค๋„ ํ™”๋ฉด์— ์ถœ๋ ฅํ•ด์ฃผ๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

ASSERT_EQ์—์„œ pointer๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค๋ฉด pointer์˜ ์ผ์น˜์—ฌ๋ถ€๋ฅผ ํ…Œ์ŠคํŠธํ•˜๊ฒŒ ๋œ๋‹ค. ๋งŒ์•ฝ ๋‘ ๊ฐœ์˜ ๋ฌธ์ž์—ด์„ ์‚ฌ์šฉํ–ˆ๋‹ค๋ฉด, ๋‘ ๋ฌธ์ž์—ด์˜ ๊ฐ’์ด ์ผ์น˜ํ•˜๋Š๋ƒ๋ฅผ ํ…Œ์ŠคํŠธํ•˜์ง€ ์•Š๊ณ  ๋™์ผํ•œ memory location์ธ์ง€๋ฅผ ํŒ๋‹จํ•ด์„œ ๊ฒฐ๊ณผ๋ฅผ ๋‚ด๋ณด๋‚ธ๋‹ค. ๋งŒ์•ฝ์— ๋ฌธ์ž์—ด ๊ฐ’์˜ ์ผ์น˜์—ฌ๋ถ€๋ฅผ ํ…Œ์ŠคํŠธํ•˜๊ณ  ์‹ถ๋‹ค๋ฉด ASSERT_EQ๋ฅผ ์‚ฌ์šฉํ•ด์„œ๋Š” ์•ˆ๋˜๊ณ  ๋Œ€์‹ ์— ASSERT_STREQ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๋œ๋‹ค. ํŠน๋ณ„ํ•œ ๊ฒฝ์šฐ, NULL์„ ๋น„๊ตํ•ด์•ผ ํ•˜๋Š” ๊ฒฝ์šฐ๊ฐ€ ์ƒ๊ธด๋‹ค๋ฉด ASSERT_STREQ(NULL, c_string)์„ ์‚ฌ์šฉํ•˜๋ฉด ๋˜์ง€๋งŒ, ๋‘ ๊ฐœ์˜ ๋ฌธ์ž์—ด object๋ฅผ ๋น„๊ตํ•˜๋ ค๊ณ  ํ•œ๋‹ค๋ฉด ASSERT_EQ๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค.

ASSERT ๊ตฌ๋ฌธ์€ narrow, wide string ๋ชจ๋‘์— ๋Œ€ํ•ด ๋™์ž‘ํ•œ๋‹ค.



String Comparison

๋ฌธ์ž์—ด ๋น„๊ต๋ฅผ ์œ„ํ•ด์„œ๋Š” ๋‹ค์Œ์˜ assertion ๊ตฌ๋ฌธ๋“ค์„ ์‚ฌ์šฉํ•œ๋‹ค.


์œ„์˜ assertion ๊ตฌ๋ฌธ์ค‘ CASE๊ฐ€ ํฌํ•จ๋œ ํ•ญ๋ชฉ๋“ค์ด ์žˆ๋Š”๋ฐ, CASE๋Š” ๋Œ€์†Œ๋ฌธ์ž๋ฅผ ๊ตฌ๋ณ„ํ•˜์ง€ ์•Š๋Š”๋‹ค๋Š”๊ฑธ ์˜๋ฏธํ•œ๋‹ค. ๋˜ NULL pointer์™€ ๋น„์–ด์žˆ๋Š” ๋ฌธ์ž์—ด์€ ๋‹ค๋ฆ„์„ ์œ ์˜ํ•ด์•ผ ํ•œ๋‹ค.



Simple Tests

Test๋ฅผ ์ž‘์„ฑํ•˜๊ธฐ ์œ„ํ•ด ์ผ๋‹จ ์•„๋ž˜์˜ ์ ˆ์ฐจ๋Œ€๋กœ ์ˆ˜ํ–‰ํ•œ๋‹ค.

1. Test function์„ ์ •์˜ํ•˜๊ณ  ์ด๋ฆ„ ๋ถ™์ด๊ธฐ ์œ„ํ•ด์„œ TEST() macro๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค. ์ด macro๋Š” ์ผ๋ฐ˜์ ์€ C++ function์œผ๋กœ ๊ตฌ์„ฑ๋˜์–ด ์žˆ์œผ๋ฉฐ ๊ฒฐ๊ณผ๊ฐ’์„ return ํ•˜์ง€ ์•Š๋Š”๋‹ค.

2. ์ด function์—์„œ ์‚ฌ์šฉ์ž๊ฐ€ ์›ํ•˜๋Š” ๊ฐ€๋Šฅํ•œ C++ ๊ตฌ๋ฌธ๋“ค์„ ์‚ฌ์šฉํ•˜๋ฉด ๋˜๊ณ , ๊ฐ’์˜ ๋น„๊ต๋ฅผ ์œ„ํ•ด์„œ๋Š” google test์˜ assertion ๊ตฌ๋ฌธ์„ ์‚ฌ์šฉํ•˜๋ฉด ๋œ๋‹ค.

3. Test ๊ฒฐ๊ณผ๋Š” ์ด assertion ๊ตฌ๋ฌธ์— ์˜ํ•ด ๊ฒฐ์ •๋œ๋‹ค.

TEST(test_case_name, test_name) {
 
... test body ...
}

TEST() macro์—์„œ ์ฒซ๋ฒˆ์งธ argument๋Š” testcase์˜ ์ด๋ฆ„์„ ์˜๋ฏธํ•˜๋ฉฐ ๋‘๋ฒˆ์งธ argument๋Š” testcase ์•ˆ์—์„œ์˜ test ์ด๋ฆ„์„ ์˜๋ฏธํ•œ๋‹ค. Testcase๋Š” ์—ฌ๋Ÿฌ๊ฐœ์˜ test๋ฅผ ํฌํ•จํ•  ์ˆ˜ ์žˆ๋‹ค. ๋˜ ๋‹ค๋ฅธ testcase์—์„œ ๊ฐ™์€ test ์ด๋ฆ„์„ ๊ฐ€์งˆ ์ˆ˜ ์žˆ๋‹ค.

์˜ˆ๋ฅผ ๋“ค์–ด๋ณด์ž. ๊ฐ„๋‹จํ•œ function์ธ

int Factorial(int n); // Returns the factorial of n

์ด ์žˆ๋‹ค.

์ด function์„ test ํ•˜๊ธฐ ์œ„ํ•ด์„œ ์•„๋ž˜์™€ ๊ฐ™์€ testcase๋ฅผ ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ๋‹ค.

// Tests factorial of 0.
TEST
(FactorialTest, HandlesZeroInput) {
  EXPECT_EQ
(1, Factorial(0));
}

// Tests factorial of positive numbers.
TEST
(FactorialTest, HandlesPositiveInput) {
  EXPECT_EQ
(1, Factorial(1));
  EXPECT_EQ
(2, Factorial(2));
  EXPECT_EQ
(6, Factorial(3));
  EXPECT_EQ
(40320, Factorial(8));
}

Google test๋Š” testcase์— ์˜ํ•ด grouping ํ•˜๋Š” ๊ฒƒ์ด ๊ฐ€๋Šฅํ•œ๋ฐ, TEST()์˜ ์ฒซ๋ฒˆ์งธ argument๋ฅผ ๋™์ผํ•˜๊ฒŒ ์‚ฌ์šฉํ•จ์œผ๋กœ์จ ์ด๋ฅผ ๊ฐ€๋Šฅ์ผ€ ๋งŒ๋“ค ์ˆ˜ ์žˆ๋‹ค. ์œ„์˜ ์˜ˆ์ œ์—์„œ ๋ณด๋ฉด HandlesZeroInput ์ด๋ผ๋Š” test์™€ HandlesPositiveInput test๋Š” ๊ฐ๊ฐ ๋‹ค๋ฅธ test๋ฅผ ์˜๋ฏธํ•˜์ง€๋งŒ FactorialTest ๋ผ๋Š” testcase์˜ ์ด๋ฆ„์„ ๋™์ผํ•˜๊ฒŒ ์‚ฌ์šฉํ•จ์œผ๋กœ์จ grouping์ด ๊ฐ€๋Šฅํ•จ์„ ๋ณด์—ฌ์ฃผ๊ณ  ์žˆ๋‹ค.



Text Fixtures : Using the Same Data Configuration for Multiple Tests

์‚ฌ์šฉ์ž๊ฐ€ ์œ ์‚ฌํ•œ data๋ฅผ ์‚ฌ์šฉํ•ด์„œ ํ•˜๋‚˜ ์ด์ƒ์˜ test๋ฅผ ์ž‘์„ฑํ•œ๋‹ค๋ฉด, test fixture๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค. ์ด test fixture๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค๋Š” ๊ฒƒ์€ ์—ฌ๋Ÿฌ๊ฐœ์˜ ๋‹ค์–‘ํ•œ test๋ฅผ ์ž‘์„ฑํ•˜๋Š” ๊ณผ์ •์—์„œ ๊ฐ™์€ object์˜ configuration์„ ์žฌ์‚ฌ์šฉํ•œ๋‹ค๋Š” ๊ฒƒ์„ ์˜๋ฏธํ•œ๋‹ค.

Fixture๋ฅผ ์ž‘์„ฑํ•  ๋•Œ์—๋Š” ์•„๋ž˜์˜ ๋‚ด์šฉ๋Œ€๋กœ ์ˆ˜ํ–‰ํ•˜๋ฉด ๋œ๋‹ค.

1. ::testing::Test ๋กœ๋ถ€ํ„ฐ class๋ฅผ deriveํ•œ๋‹ค. Sub-class ์—์„œ fixture member์— ์ ‘๊ทผํ•ด์•ผ ํ•˜๊ธฐ ๋•Œ๋ฌธ์— protected ํ˜น์€ public ์œผ๋กœ ์ž‘์„ฑํ•ด์•ผ ํ•œ๋‹ค.

2. Class ๋‚ด๋ถ€์—์„œ ์‚ฌ์šฉ์ž๊ฐ€ ์›ํ•˜๋Š”๋Œ€๋กœ object๋“ค์„ ์„ ์–ธํ•ด ์‚ฌ์šฉํ•œ๋‹ค.

3. ํ•„์š”ํ•˜๋‹ค๋ฉด, ์ƒ์„ฑ์ž๋‚˜ SetUp() function์„ ์ž‘์„ฑํ•ด๋‘”๋‹ค.

4. ์ƒ์„ฑ์ž๋‚˜ SetUp() function์„ ์ •์˜ํ•ด์„œ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ๋‹ค๋ฉด, ํ•ด๋‹น function์—์„œ ์‚ฌ์šฉํ–ˆ๋˜ resource๋ฅผ ๋ฐ˜ํ™˜ํ•˜๊ธฐ ์œ„ํ•ด ์†Œ๋ฉธ์ž๋‚˜ TearDown() function์„ ์ž‘์„ฑํ•œ๋‹ค.

5. Subroutine ๋“ค์„ ์ž‘์„ฑํ•œ๋‹ค.

Fixture๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” TEST() ๋Œ€์‹ ์— TEST_F()๋ฅผ ์‚ฌ์šฉํ•ด์•ผ๋งŒ ํ•œ๋‹ค.
TEST()์—์„œ๋Š” ์ฒซ๋ฒˆ์งธ argument๊ฐ€ testcase์˜ ์ด๋ฆ„์ด์—ˆ์ง€๋งŒ TEST_F()๋ฅผ ์‚ฌ์šฉํ•  ๋•Œ๋Š” ์ฒซ๋ฒˆ์งธ argument๋กœ test fixture class์˜ ์ด๋ฆ„์„ ์‚ฌ์šฉํ•ด์•ผ๋งŒ ํ•œ๋‹ค.

๋ถˆํ–‰ํ•˜๊ฒŒ๋„ C++ macro ๋ผ๋Š”๊ฒŒ ๋‘๊ฐ€์ง€ type์„ ์ฒ˜๋ฆฌํ•˜๋Š” ํ•˜๋‚˜์˜ macro๋ฅผ ์ง€์›ํ•˜์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์— ์–ด์ฉ” ์ˆ˜ ์—†์ด ๋‘ ๊ฐ€์ง€์˜ macro TEST(), TEST_F()๋ฅผ ์ ์ ˆํžˆ ์‚ฌ์šฉํ•ด์•ผ๋งŒ ํ•œ๋‹ค. ๋˜ ๋‹น์—ฐํ•˜๊ฒ ์ง€๋งŒ TEST_F() macro๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ ์ด์ „์— TEST_F()์— ์‚ฌ์šฉ๋  fixture class๊ฐ€ ์ •์˜๋˜์–ด ์žˆ์–ด์•ผ๋งŒ ํ•œ๋‹ค.

TEST_F()๋ฅผ ์‚ฌ์šฉํ•  ๋•Œ, google test๋Š” ์•„๋ž˜์™€ ๊ฐ™์€ ์ ˆ์ฐจ๋ฅผ ์ˆ˜ํ–‰ํ•˜๊ฒŒ ๋œ๋‹ค.

1. Runtime ์‹œ์— test fixture๋ฅผ ์ƒ์„ฑํ•œ๋‹ค.

2. SetUp()์„ ํ˜ธ์ถœํ•ด ์ดˆ๊ธฐํ™”๋ฅผ ์ˆ˜ํ–‰ํ•œ๋‹ค.

3. Test๋ฅผ ์ˆ˜ํ–‰ํ•œ๋‹ค.

4. TearDown()์„ ํ˜ธ์ถœํ•จ์œผ๋กœ์จ resource๋ฅผ ๋ฐ˜ํ™˜ํ•˜๊ฑฐ๋‚˜ ํ•˜๋Š” ์ฒ˜๋ฆฌ๋ฅผ ํ•œ๋‹ค.

5. Test fixture๋ฅผ ์†Œ๋ฉธ์‹œํ‚จ๋‹ค. ์ฃผ์˜ํ•  ๋‚ด์šฉ์€ ๊ฐ™์€ testcase ๋‚ด๋ถ€์—์„œ์˜ ๊ฐ๊ฐ์˜ test๋Š” ๋‹ค๋ฅธ test fixture๋ฅผ ํ™•๋ณดํ•ด ์‚ฌ์šฉํ•˜๋ฉฐ google test๋Š” ๋‹ค์Œ test fixture๋ฅผ ์ƒ์„ฑํ•˜๊ธฐ ์ „์— ์ด์ „ fixture๋ฅผ ์‚ญ์ œํ•œ๋‹ค. Google test๋Š” ์—ฌ๋Ÿฌ๊ฐœ์˜ test๋ฅผ ์œ„ํ•ด ๋™์ผํ•œ test fixture๋ฅผ ์žฌ์‚ฌ์šฉํ•˜์ง€ ์•Š์œผ๋ฉฐ ํ•˜๋‚˜์˜ test๊ฐ€ test fixture์— ๊ฐ€ํ•œ ๋ณ€ํ™”๊ฐ€ ๋‹ค๋ฅธ test ๋“ค์—๋Š” ์˜ํ–ฅ์„ ์ฃผ์ง€ ์•Š์Œ์„ ์˜๋ฏธํ•œ๋‹ค.

์•„๋ž˜์˜ ์˜ˆ์ œ๋ฅผ ์‚ดํŽด๋ณด์ž. Queue๋ผ๋Š” ์ด๋ฆ„์˜ queue class์— ๋Œ€ํ•œ test๋ฅผ ์ž‘์„ฑํ•œ๋‹ค๊ณ  ์ƒ๊ฐํ•ด๋ณด์ž.

template <typename E> // E is the element type.
class Queue {
 
public:
 
Queue();
 
void Enqueue(const E& element);
  E
* Dequeue(); // Returns NULL if the queue is empty.
  size_t size
() const;
 
...
};

๊ฐ€์žฅ ๋จผ์ € fixture class๋ฅผ ์ •์˜ํ•œ๋‹ค.

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_;
};

์ด ๊ฒฝ์šฐ์— ๊ฐ test ๋งˆ๋‹ค ์†Œ๋ฉธ์ž๊ฐ€ ๋Œ€์‹  ์ˆ˜ํ–‰ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ๊นจ๋—ํ•˜๊ฒŒ ์ •๋ฆฌํ•  ํ•„์š”๊ฐ€ ์—†์–ด์„œ TestDown()์„ ์ž‘์„ฑํ•˜์ง€ ์•Š์•˜๋‹ค. ์ด ์ž‘์—…๊นŒ์ง€ ๋งˆ์นœ ํ›„์— ์•„๋ž˜์ฒ˜๋Ÿผ test fixture๋ฅผ ์ด์šฉํ•ด TEST_F()๋ฅผ ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ๋‹ค.

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;
}

์ด test๋“ค์ด ์ˆ˜ํ–‰๋  ๋•Œ ์•„๋ž˜์™€ ๊ฐ™์€ ๊ณผ์ •์„ ๊ฑฐ์น˜๊ฒŒ ๋œ๋‹ค.

1. Google test๊ฐ€ QueueTest object๋ฅผ ์ƒ์„ฑํ•œ๋‹ค. (t1์ด๋ผ ๋ถ€๋ฅด์ž.)

2. t1.SetUp() ์ด ํ˜ธ์ถœ๋˜์–ด์„œ t1์„ ์ดˆ๊ธฐํ™”ํ•œ๋‹ค.

3. t1์˜ ์ฒซ๋ฒˆ์งธ test์ธ IsEmptyInitially๊ฐ€ ์ˆ˜ํ–‰๋œ๋‹ค.

4. Test ์ข…๋ฃŒ ํ›„์— t1.TearDown()์ด ํ˜ธ์ถœ๋˜์–ด ์ •๋ฆฌํ•œ๋‹ค.

5. t1์ด ์†Œ๋ฉธ๋œ๋‹ค.

6. ๋‹ค๋ฅธ QueueTest object์— ๋Œ€ํ•ด ์œ„์˜ ๊ณผ์ •์ด ๋ฐ˜๋ณต๋˜๋Š”๋ฐ, ์ด๋ฒˆ์—” DequeueWork test์— ๋Œ€ํ•ด ๋ฐ˜๋ณต ์ˆ˜ํ–‰๋œ๋‹ค.



Invoking the Tests

TEST()์™€ TEST_F() ๋Š” google test์—์„œ ๋‚ด๋ถ€์ ์œผ๋กœ ๋“ฑ๋ก๋œ๋‹ค. ๊ทธ๋ ‡๊ธฐ ๋•Œ๋ฌธ์— ๋‹ค๋ฅธ C++ testing framework ๋“ค๊ณผ ๋‹ฌ๋ฆฌ test๋ฅผ ์ˆ˜ํ–‰ํ•˜๊ธฐ ์œ„ํ•ด ๋‹ค์‹œ ์ •์˜ํ•  ํ•„์š”๊ฐ€ ์—†๋‹ค.

Test ๋“ค์„ ์ •์˜ํ•œ ํ›„์— RUN_ALL_TESTS()๋ฅผ ์‚ฌ์šฉํ•ด์„œ test๋ฅผ ์ˆ˜ํ–‰์‹œํ‚ฌ ์ˆ˜ ์žˆ๋‹ค. RUN_ALL_TESTS()๋Š” ๋ชจ๋“  test๊ฐ€ ์„ฑ๊ณต์ผ ๋•Œ์—๋Š” 0์„ ๋ฐ˜ํ™˜ํ•˜๊ณ  ์•„๋‹ ๊ฒฝ์šฐ์—๋Š” 1์„ returnํ•˜๋Š” macro์ด๋‹ค. RUN_ALL_TESTS()๋Š” ์•„๋ž˜์™€ ๊ฐ™์€ ๊ณผ์ •์„ ๊ฑฐ์น˜๋ฉด์„œ ์ˆ˜ํ–‰๋œ๋‹ค.

1. Google test์˜ ๋ชจ๋“  flag๋“ค์˜ ์ƒํƒœ๋ฅผ ์ €์žฅํ•œ๋‹ค.

2. ์ฒซ๋ฒˆ์งธ test๋ฅผ ์œ„ํ•œ test fixture๋ฅผ ์ƒ์„ฑํ•œ๋‹ค.

3. SetUp()์œผ๋กœ ์ดˆ๊ธฐํ™”ํ•œ๋‹ค.

4. Fixture object์™€ ํ•จ๊ป˜ test๋ฅผ ์ˆ˜ํ–‰ํ•œ๋‹ค.

5. TearDown()์„ ํ˜ธ์ถœํ•ด์„œ resource๋“ค์„ ๋ฐ˜ํ™˜ํ•˜๊ฑฐ๋‚˜ ์ •๋ฆฌํ•œ๋‹ค.

6. Fixture object๋ฅผ ์ œ๊ฑฐํ•œ๋‹ค.

7. Google test์˜ flag๋“ค์„ ๋ณต๊ตฌํ•œ๋‹ค.

8. ๋ชจ๋“  test๊ฐ€ ์™„๋ฃŒ๋  ๋•Œ ๊นŒ์ง€ ์œ„์˜ ๊ณผ์ •์„ ๋ฐ˜๋ณตํ•œ๋‹ค.

RUN_ALL_TEST()๋Š” ํ•œ ๋ฒˆ ์ด์ƒ ์ˆ˜ํ–‰ํ•˜๋Š”๊ฑธ ์ง€์›ํ•˜์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์— ๋‹จ ํ•œ๋ฒˆ๋งŒ ํ˜ธ์ถœ๋  ์ˆ˜ ์žˆ๋„๋ก ์ž‘์„ฑํ•ด์•ผ ํ•œ๋‹ค.



Writing the main() function

์•„๋ž˜์˜ ์˜ˆ์ฒ˜๋Ÿผ test์— ํ•„์š”ํ•œ test fixture๋‚˜ main() function์„ ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ๋‹ค.

#include "this/package/foo.h"
#include <gtest/gtest.h>

namespace {

// The fixture for testing class Foo.
class FooTest : public ::testing::Test {
 
protected:
 
// You can remove any or all of the following functions if its body
 
// is empty.

 
FooTest() {
   
// You can do set-up work for each test here.
 
}

 
virtual ~FooTest() {
   
// You can do clean-up work that doesn't throw exceptions here.
 
}

 
// If the constructor and destructor are not enough for setting up
 
// and cleaning up each test, you can define the following methods:

 
virtual void SetUp() {
   
// Code here will be called immediately after the constructor (right
   
// before each test).
 
}

 
virtual void TearDown() {
   
// Code here will be called immediately after each test (right
   
// before the destructor).
 
}

 
// Objects declared here can be used by all tests in the test case for Foo.
};

// Tests that the Foo::Bar() method does Abc.
TEST_F
(FooTest, MethodBarDoesAbc) {
 
const string input_filepath = "this/package/testdata/myinputfile.dat";
 
const string output_filepath = "this/package/testdata/myoutputfile.dat";
 
Foo f;
  EXPECT_EQ
(0, f.Bar(input_filepath, output_filepath));
}

// Tests that Foo does Xyz.
TEST_F
(FooTest, DoesXyz) {
 
// Exercises the Xyz feature of Foo.
}

}  // namespace

int main(int argc, char **argv) {
 
::testing::InitGoogleTest(&argc, argv);
 
return RUN_ALL_TESTS();
}

์ด ์˜ˆ์ œ์—์„œ main() function์— ์‚ฌ์šฉ๋œ ::testing::InitGoogleTest() function์€ google test์˜ flag๋ฅผ ์„ค์ •ํ•˜๊ธฐ ์œ„ํ•ด command line์œผ๋กœ ์ž…๋ ฅ๋œ ๊ฐ’๋“ค์„ ์‚ฌ์šฉํ•œ๋‹ค. ์ด๋Ÿฐ ๋ฐฉ๋ฒ•์€ ์‚ฌ์šฉ์ž๊ฐ€ ๋‹ค์–‘ํ•œ flag๋ฅผ ํ†ตํ•ด test program์„ ์ œ์–ด ๊ฐ€๋Šฅํ•˜๋„๋ก ํ•ด์ค€๋‹ค.



Important note for Visual C++ users

๋งŒ์•ฝ ์‚ฌ์šฉ์ž๊ฐ€ test๋ฅผ library์— ๋„ฃ์–ด๋‘์—ˆ๊ณ , main() function์ด .exe ํŒŒ์ผ ์•ˆ์—์„œ ๋ณ„๋„์˜ library๋กœ ์ž‘์„ฑ๋˜์–ด ์žˆ๋‹ค๋ฉด test๋Š” ์ˆ˜ํ–‰๋˜์ง€ ์•Š์„๊ฒƒ์ด๋‹ค. ์ด์œ ๋Š” Visual C++์˜ bug ๋•Œ๋ฌธ์ธ๋ฐ, ์‚ฌ์šฉ์ž๊ฐ€ test๋ฅผ ์ •์˜ํ–ˆ์„ ๋•Œ, google test๋Š” test๋ฅผ ๋“ฑ๋กํ•˜๊ธฐ ์œ„ํ•ด static object๋กœ ์ƒ์„ฑํ•œ๋‹ค. ์ด๋Ÿฌํ•œ object๋“ค์€ ์–ด๋””์„œ๋“  ์ฐธ์กฐ๋˜์ง€ ๋ชปํ•˜์ง€๋งŒ ์ƒ์„ฑ์ž๋“ค์€ ์—ฌ์ „ํžˆ ์ˆ˜ํ–‰ํ•˜๋ ค๊ณ  ํ•œ๋‹ค. ๊ทธ๋ž˜์„œ ์‚ฌ์šฉ์ž๋Š” main program์—์„œ test์™€ ํ•จ๊ป˜ library๋ฅผ ์ฐธ์กฐํ•ด์•ผ๋งŒ ํ•œ๋‹ค. ๊ทธ๋Ÿฌ๊ธฐ ์œ„ํ•ด์„œ๋Š” library์—์„œ ์•„๋ž˜์ฒ˜๋Ÿผ function์„ ์„ ์–ธํ•œ๋‹ค.

__declspec(dllimport) int PullInMyLibrary() { return 0; }

DLL์ด ์•„๋‹Œ static library๋กœ ์ž‘์„ฑํ–ˆ๋‹ค๋ฉด ์œ„์™€ ๊ฐ™์€ ์„ ์–ธ์€ ํ•„์š”ํ•˜์ง€ ์•Š์ง€๋งŒ, main program์—์„œ๋Š” ์•„๋ž˜์™€ ๊ฐ™์ด ์ž‘์„ฑํ•ด ์ฃผ์–ด์•ผ ํ•œ๋‹ค.

int PullInMyLibrary();
static int dummy = PullInMyLibrary();

์ถ”๊ฐ€๋กœ static library๋กœ test๋ฅผ ์ž‘์„ฑํ•œ๋‹ค๋ฉด main program์˜ linker option์— /OPT:NOREF๋ฅผ ๋„ฃ์–ด์ฃผ์–ด์•ผ ํ•˜๊ณ , test๋ฅผ DLL๋กœ ์ž‘์„ฑํ•˜๊ฒŒ ๋œ๋‹ค๋ฉด google test ์—ญ์‹œ DLL๋กœ build ํ•ด์ฃผ์–ด์•ผ test๊ฐ€ ์ œ๋Œ€๋กœ ์ˆ˜ํ–‰๋  ์ˆ˜ ์žˆ๋‹ค. ๊ทธ๋ž˜๋„ ๊ฐ€์žฅ ์†์‰ฌ์šด ๋ฐฉ๋ฒ•์€ test๋ฅผ library๋กœ ๋งŒ๋“ค์ง€ ์•Š๋Š” ๊ฒƒ์ด๋‹ค.









* ์ถœ์ฒ˜ : http://blurblah.net/194
๋ฐ˜์‘ํ˜•