เริ่มหัดเขียน unit test C++ ด้วย Google Test

Thanabodee C.
2 min readJun 3, 2017

--

เมื่อวันก่อนนัดกับพี่ตู่และกลุ่ม clockup studio เพื่อเรียนรู้เรื่อง unit test สำหรับงานเกมด้วย C++ กัน แต่เสียดายงานเข้าเลยไม่ได้ฟังทั้งหมด T_T แต่ก็ยังดีที่ได้ไปตอนที่พี่ตู่พาทำ setup และ run test พอดีเลยได้กลับมาศึกษาเพิ่มเติมและสรุปในนี้เลยดีกว่า

เครื่องมือที่ใช้มีอะไรบ้าง

  1. C/C++ compiler ผมใช้ clang ที่มากับ command line tools ของ macOS หรือจะใช้ gcc ก็ได้ไม่ว่ากัน
  2. cmake สำหรับ build sources code
  3. git สำหรับ clone

เริ่มขั้นตอนแรกติดตั้ง Google Test

ด้วยการ clone source code จาก https://github.com/google/googletest

$ git clone https://github.com/google/googletest.git

จากนั้นทำการ compile ตัว Google Test ด้วย CMake

$ cd googletest
$ mkdir build
$ cmake -DCMAKE_BUILD_TYPE=Release ..
$ make
$ make install # ถ้าติด permission ให้ใช้ sudo นะ

สร้างเทสไฟล์

ผมสร้างไฟล์ชื่อ FizzBuzzTest.cc และเขียนดังนี้

#include <gtest/gtest.h>TEST(FizzBuzzTest, Fizz) {
}
int main(int argc, char **argv) {
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}

เทสของ Google Test จะประกอบไปด้วยสองส่วนคือ

  1. test function ตัว Google Test จะใช้ macro ชื่อว่า TEST ที่รับชื่อ test suite กับ test case และมี {} สำหรับ detail ของ test case นั้นๆ
  2. main function เนื่องจากการ run test ใน C/C++ เราจะต้อง compile เป็น binary ก่อนเสมอ ข้างในจะต้องเรียก InitGoogleTest เพื่อทำให้ Google Test parse flags ได้ และเรียก RUN_ALL_TESTS เพื่อรันการทดสอบ (RUN_ALL_TESTSเป็น macro นะครับ)

Compile เทสและรัน

โดย

$ clang++ -I/usr/local/include -L/usr/local/lib -lgtest FizzBuzzTest.cc -o FizzBuzzTest
$ ./FizzBuzzTest

ผลลัพธ์ที่ได้จากการรันเทสคือ

[==========] Running 1 test from 1 test case.
[----------] Global test environment set-up.
[----------] 1 test from FizzBuzzTest
[ RUN ] FizzBuzzTest.Fizz
[ OK ] FizzBuzzTest.Fizz (0 ms)
[----------] 1 test from FizzBuzzTest (0 ms total)
[----------] Global test environment tear-down
[==========] 1 test from 1 test case ran. (0 ms total)
[ PASSED ] 1 test.

เริ่มต้นการเขียนเทส

เริ่มเขียนเทสใน TEST(FizzBuzzTest, Fizz) โดย

TEST(FizzBuzzTest, Fizz) {
EXPECT_EQ("Fizz", fizzbuzz::Say(3).c_str());
}

ใช้ EXPECT_EQ สำหรับเปรียบเทียบผลลัพธ์ ซึ่ง parameter ตัวแรกคือผลลัพธ์ที่คาดหวัง (expect) และ output ที่ได้จาก function ที่เราทดสอบ (actual)

จากนั้นทำการ compile และ run เพื่อดูผล ซึ่งจะต้อง compile ไม่ผ่านนะ เพราะเรายังไม่ได้เริ่ม implement เลย

Implement code ให้เร็วที่สุด

โดยผมสร้่าง function ไว้ภายในไฟล์เทส เพื่อให้เห็นภาพว่ามันสามารถเรียกได้จริง

namespace fizzbuzz {
std::string Say(const int n) {
return "Fizz";
}
}

จากนั้นทำการ compile และ run อีกรอบผลที่ได้ควรจะรันผ่าน

เริ่ม move code ไปอยู่อีกไฟล์

จริงๆ แล้วโค้ดของเราไม่ควรจะอยู่ในไฟล์เทส เพราะฉะนั้นผมจะสร้างไฟล์ชื่อ FizzBuzz.cc เพื่อเก็บ function ของเราและ FizzBuzz.hสำหรับ header ของ function

// in FizzBuzz.h#ifndef FIZZBUZZ_H
#define FIZZBUZZ_H
namespace fizzbuzz {
std::string Say(const int);
}
#endif // end FIZZBUZZ_H// in FizzBuzz.cc
#include <iostream>
#include "FizzBuzz.h"std::string fizzbuzz::Say(const int n) {
return "Fizz";
}

จากนั้นทำการแก้ไขวิธีการ compile โดยเพิ่มไฟล์ FizzBuzz.cc เข้าไปตอน compile ด้วย

$ clang++ -L/usr/local/lib -I/usr/local/include -lgtest FizzBuzz.cc FizzBuzzTest.cc -o FizzBuzzTest
$ ./FizzBuzzTest

เท่านี้ก็เริ่มต้นเขียนเทสต่อๆ ไปได้แล้ว :)

--

--