1 googletest ダウンロード/公式サンプル分析
1.1 googletest ソースコードをダウンロードしてコンパイルする
ソースコードのダウンロードとコンパイル
// 下载
git clone https://github.com/google/googletest
// 现在官方已经把 gtest 和 gmock 一起维护,所以这个 git 仓库还包含了 gmock。
// 编译、安装
cd googletest-main
mkdir build install
cd build
cmake -DCMAKE_INSTALL_PREFIX=../install
make -j
make install
コンパイル設定
.so ライブラリと公式サンプル バイナリ ファイルを生成する必要がある場合は、ソース コードの一番外側の CMakeLists.txt を変更して
ダイナミック ライブラリまたはスタティック ライブラリを生成する必要があり、BUILD_SHARED_LIBS を変更して
サンプル テスト ビン ファイルを生成する必要があります。 gtest_build_samples を変更する必要がある
L20 を ON に変更すると、googletest に付属のサンプルがビルド ディレクトリ内の実行可能ファイルにコンパイルされていることがわかります。
1.2 googletest の構文
TEST マクロ
TEST(test_case_name, test_name) マクロは、テスト ケースを定義するために使用されます。ここで、test_case_name はテスト ケースの名前、test_name はテストの名前です。例えば:
TEST(MyTestSuite, MyTest) {
// 测试代码
}
ASSERT マクロ
ASSERT_ () マクロは、結果が期待を満たすかどうかをアサートするために使用されます。ASSERT_TRUE (
condition): 条件は true
ASSERT_FALSE(condition): 条件は false
ASSERT_EQ(val1, val2): 2 つの値は等しい
ASSERT_NE( val1, val2): 2 つの値が等しくない
ASSERT_LT(val1, val2): 最初の値が 2 番目の値より小さい
ASSERT_LE(val1, val2): 最初の値が次の値以下である2 番目の値
ASSERT_GT(val1, val2): 最初の値が 2 番目の値より大きい
ASSERT_GE(val1, val2): 最初の値が 2 番目の値以上である
次に例を示します。
TEST(MyTestSuite, MyTest) {
int a = 1;
int b = 2;
ASSERT_TRUE(a < b);
ASSERT_EQ(a + b, 3);
}
アサーションが失敗すると、テスト ケースも失敗します。
EXPECT マクロ
EXPECT_ () マクロはASSERT_() マクロと同じように動作しますが、チェックが失敗してもテスト ケースの実行は終了しません。例えば:
TEST(MyTestSuite, MyTest) {
int a = 1;
int b = 2;
EXPECT_TRUE(a < b);
EXPECT_EQ(a + b, 3);
}
ASSERT マクロと EXCEPT マクロの違い:
ASSERT が失敗すると、致命的なエラーとみなされ、現在の関数 (関数のみ) が終了します。EXPECT が失敗した場合でも、現在の関数は引き続き実行されるため、関数内の複数の失敗が同時に報告される可能性があります。現在のチェックポイントが失敗した後の関数のその後の検査が無意味であると考えない限り、通常は EXPECT レベルのアサーションを使用します。
SetUp および TearDown
SetUp() および TearDown() 関数は、各テスト ケースの実行の前後に呼び出して、テスト環境を初期化およびクリーンアップできます。例えば:
class MyTestSuite : public ::testing::Test {
protected:
void SetUp() override {
// 初始化代码
}
void TearDown() override {
// 清理代码
}
};
TEST_F(MyTestSuite, MyTest) {
// 测试代码
}
パラメトリック テスト
パラメトリック テストを使用すると、一連の入力に対するさまざまな条件下でプログラムの出力が期待を満たすかどうかをテストできます。例えば:
class MyTestSuite : public ::testing::TestWithParam<int> {
};
TEST_P(MyTestSuite, MyTest) {
int input = GetParam();
// 测试代码
}
INSTANTIATE_TEST_SUITE_P(MyTestSuiteInstantiationName, MyTestSuite, ::testing::Values(1, 2, 3));
この例では、MyTestSuite は TestWithParam から継承しており、これがパラメーター化されたテストであることを示しています。GetParam() 関数は、現在のテスト ケースのパラメーター値を取得できます。INSTANTIATE_TEST_SUITE_P マクロは、テスト ケースをインスタンス化するために使用されます。最初のパラメーターはインスタンス化の名前、2 番目のパラメーターはテスト ケースの名前、3 番目のパラメーターはパラメーター値のリストです。
予期される例外 例外が
発生したときのプログラムの動作をテストする必要がある場合は、EXPECT_THROW() マクロと ASSERT_THROW() マクロを使用できます。例えば:
TEST(MyTestSuite, MyTest) {
std::vector<int> v;
EXPECT_THROW(v.at(0), std::out_of_range);
}
この例では、EXPECT_THROW() マクロは、v.at(0) の実行時に std::out_of_range 例外がスローされることが予期されることを示しています。例外がスローされない場合、テスト ケースは失敗します。
1.3 公式サンプル分析
インストール時にダウンロードしたコードには 10 個のサンプルが含まれており、make を直接実行してルート ディレクトリで実行できます。サンプル フォルダーに入り、各関数コードと対応するテスト ファイルを読みます。これは、すぐに開始するのに役立ちます。以下に簡単な例を見てみましょう。
サンプル1
#include <limits.h>
#include "sample1.h"
#include "gtest/gtest.h"
// Tests factorial of negative numbers.
TEST(FactorialTest, Negative) {
// This test is named "Negative", and belongs to the "FactorialTest"
// test case.
EXPECT_EQ(1, Factorial(-5));
EXPECT_EQ(1, Factorial(-1));
EXPECT_GT(Factorial(-10), 0);
}
...
TEST(IsPrimeTest, Positive) {
EXPECT_FALSE(IsPrime(4));
EXPECT_TRUE(IsPrime(5));
EXPECT_FALSE(IsPrime(6));
EXPECT_TRUE(IsPrime(23));
}
サンプル 1 では、主に TEST() マクロを使用した単純なテスト ケースの作成を示します。
test_case_nameは関数のテストケースに対応し、test_nameはこのテストケースの下のシーンのテストセットに対応することができる。これら 2 つの名前は任意に選択できますが、意味のあるものでなければなりません。
Sample1 の実行結果は次のとおりです。
2 独自のコードで gtest を使用する
gtest をライブラリにコンパイルする方法は上記で説明しましたが、自分のプロジェクトで gtest を使用する場合は、記録されたプロジェクト ディレクトリにインストールのヘッダー ファイルとライブラリ ファイルをインクルードする必要があります。
プロジェクトのディレクトリは以下のとおりです。
// CMakeLists.txt
cmake_minimum_required(VERSION 3.10)
project(GTEST_USAGE)
set(CMAKE_CXX_COMPILE_FLAGS "std=c++11")
include_directories(${
CMAKE_CURRENT_SOURCE_DIR}/install/include)
file(GLOB CPP_FILES ${
CMAKE_CURRENT_SOURCE_DIR}/*.c*)
link_directories(${CMAKE_CURRENT_SOURCE_DIR}/install/lib)
add_executable(GTEST_USAGE ${CPP_FILES})
target_link_libraries(GTEST_USAGE
gtest
)
// main.cpp
#include <gtest/gtest.h>
#include<numeric>
int main(int argc, char **argv)
{
testing::InitGoogleTest(&argc, argv)
return 0;
}
ここでは独自のコードを書かず、公式のsample4をテストコード
sample4.ccとして直接使用します。
// Copyright 2005, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// A sample program demonstrating using Google C++ testing framework.
#include "sample4.h"
#include <stdio.h>
// Returns the current counter value, and increments it.
int Counter::Increment() {
return counter_++; }
// Returns the current counter value, and decrements it.
// counter can not be less than 0, return 0 in this case
int Counter::Decrement() {
if (counter_ == 0) {
return counter_;
} else {
return counter_--;
}
}
// Prints the current counter value to STDOUT.
void Counter::Print() const {
printf("%d", counter_); }
サンプル4.h
// Copyright 2005, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// A sample program demonstrating using Google C++ testing framework.
#ifndef GOOGLETEST_SAMPLES_SAMPLE4_H_
#define GOOGLETEST_SAMPLES_SAMPLE4_H_
// A simple monotonic counter.
class Counter {
private:
int counter_;
public:
// Creates a counter that starts at 0.
Counter() : counter_(0) {
}
// Returns the current counter value, and increments it.
int Increment();
// Returns the current counter value, and decrements it.
int Decrement();
// Prints the current counter value to STDOUT.
void Print() const;
};
#endif // GOOGLETEST_SAMPLES_SAMPLE4_H_
サンプル4_unittest.cc
// Copyright 2005, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "sample4.h"
#include "gtest/gtest.h"
namespace {
// Tests the Increment() method.
TEST(Counter, Increment) {
Counter c;
// Test that counter 0 returns 0
EXPECT_EQ(0, c.Decrement());
// EXPECT_EQ() evaluates its arguments exactly once, so they
// can have side effects.
EXPECT_EQ(0, c.Increment());
EXPECT_EQ(1, c.Increment());
EXPECT_EQ(2, c.Increment());
EXPECT_EQ(3, c.Decrement());
}
} // namespace
操作の結果は次のようになります。