環境
Ubuntu 20.04@WSL2
❯ lsb_release -a No LSB modules are available. Distributor ID: Ubuntu Description: Ubuntu 20.04.3 LTS Release: 20.04 Codename: focal
C++ compiler: g++
❯ g++ --version g++ (Ubuntu 9.3.0-17ubuntu1~20.04) 9.3.0 Copyright (C) 2019 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
やること
Google Testを使ったC++の単体テスト。(初心者はビルドツールはBazelを使うことを推奨している)
If you’re using GoogleTest for the first time or need a refresher, we recommend this tutorial as a starting point.
Quickstart: Building with Bazel
Bazel: ビルド・テストツール
この記事を書いている時点では、以下のバージョンをサポートしている。これ以外のバージョンでも互換はあるはずだが、動作は保証されていない。
- 18.04 (LTS)
- 16.04 (LTS)
Bazelのインストール
Bazelを直接インストールのではなく、Bazeliskというラッパーをインストールする。go install, npm installらへんでインストールするのが楽
npm install -g @bazel/bazelisk
bazelisk/README.md at master · bazelbuild/bazelisk
npmでインストール後は、 bazel
baselisk
のシンボリックリンクが追加されていた
~/.nvm/versions/node/v15.3.0/bin ※PATHがすでに通っている bazel -> ../lib/node_modules/@bazel/bazelisk/bazelisk.js ※インストール後追加されていた bazelisk -> ../lib/node_modules/@bazel/bazelisk/bazelisk.js ※インストール後追加されていた
Bazel workspaceの用意
テストコードを追加するローカルリポジトリをBazel workspaceとする
まず、このworkspace内で使用するBazelのバージョンを指定するために、リポジトリのroot直下に
.bazelversion
ファイルを用意する。cd ${workspaceとするディレクトリのパス} echo '5.1.0' > .bazelversion
Google Testの依存を追加するために、
WORKSPACE
ファイルを追加する。load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive") http_archive( name = "com_google_googletest", urls = ["https://github.com/google/googletest/archive/609281088cfefc76f9d0ce82e1ff6c30cc3591e5.zip"], strip_prefix = "googletest-609281088cfefc76f9d0ce82e1ff6c30cc3591e5", )
これでGoogleTestの依存関係を追加できているはずなので、GoogleTestをインクルードしたテストコードをビルドすることができる。
テストコードを用意して、ビルド実行
テストコード追加
#include <gtest/gtest.h> // Demonstrate some basic assertions. TEST(HelloTest, BasicAssertions) { // Expect two strings not to be equal. EXPECT_STRNE("hello", "world"); // Expect equality. EXPECT_EQ(7 * 6, 42); }
BUILD
ファイルを追加cc_test( name = "hello_test", size = "small", srcs = ["hello_test.cc"], deps = ["@com_google_googletest//:gtest_main"], )
ビルド実行
//以降は、BUILDファイルのWorkspaceのルートからの相対パス。
bazel test --test_output=all //:hello_test bazel test --test_output=all //${BUILDファイルのパス}:${name}
Googletestの書き方
テストを書く前に
用語
googletestはISTQBなどで定義される、一般的な用語の定義とは違うので、注意が必要
Meaning | googletest term | ISTQB term |
---|---|---|
grouping related tests | Test Case | Test Suite |
Exercise a particular program path with specific input values and verify the results | Test | Test Case |
Assertions
googletest assertionsはマクロ
Assertions | Description |
---|---|
ASSERT_* | generate fatal failures when they fail, and abort the current function |
EXPECT_* | generate nonfatal failures, which don’t abort the current function. |
Assertions Reference
シンプルなテストを書く
フォーマット
- 第一引数:the name of the test suite
- 第二引数:the test’s name within the test suite
※どちらもC++で有効なidentiferで、_
は使えない
TEST(TestSuiteName, TestName) {
... test body ...
}
自分はこういう風にした
インクルードが面倒でよくわからなかったので、パッケージごとにBUILDファイル用意。パッケージのディレクトリ直下に必要なファイルをすべて用意。
lib配下にパッケージのディレクトリを作成
cd lib mdkir Math ※パッケージ名の例
問題を解いたあとに、スニペットにしておきたいと思ったものを、関数にしておく
touch digit.hpp
2.の単体テストコードを用意
touch digitTest.cpp
作成したパッケージのディレクトリ内にBUILDファイルを用意
touch BUILD
cc_test( name = "lib_math_test", ※任意の名前。実行する際に使う size = "small", srcs = ["digit.hpp","digitTest.cpp"], ※テストコードと、テストコードがインクルードするファイルを記載 deps = ["@com_google_googletest//:gtest_main"], )
テスト実行
bazel test --test_output=all //lib/Math:lib_math_test ※Mathパッケージ配下のテストコードを実行する
ディレクトリ構成
lib └── Math ※パッケージ ├── BUILD ※パッケージごとに用意 ├── digit.h ※実装ファイル(今回はテンプレート関数だったので、実装もヘッダファイルで宣言。なのでヘッダファイルのみ) └── digitTest.cpp ※テストコード
テンプレート関数のテストを書く時に参考にした記事
テンプレートのヘッダを用意した場合の注意点。テンプレートはヘッダに宣言だけでなく実装も定義する。
C++ テンプレート ヘッダと実装を別にした時に起こること - Qiita