SlideShare une entreprise Scribd logo
1  sur  32
Télécharger pour lire hors ligne
書こう! 使おう! 単体テスト
Ryohji Ikebe, December 19, 2021
Google Test と Python unittest での単体テスト
プログラムコード
の動きを確かめる
単体テストは何のために?
お品書き
単体テストを使うために
❶ Bazel の導入と Google Test での単体テスト
❷ 単体テストの約束
❸ Python unittest パッケージでの単体テスト
❹ 単体テストのガイドライン
Bazel の導入と


Google Test での単体テスト
❶
前知識
Google Test: https://google.github.io/googletest/
• 「Bazel でビルド、 Bazel で実行」が唯一の公式サポート
• 「有志」のコントリビューションで CMake もつかえる
• 最新の「全機能」がつかえる保証はない


(不足に気づいたらコントリビュートしよう!)
Bazel のインストール
Google による現代的な make 実装:https://bazel.build
• モジュールのビルドやテスト実行のためにつかう
• 以下を bazel.exe として保存しパスを通す:
https://github.com/bazelbuild/bazel/releases/download/4.2.2/
bazel-4.2.2-windows-x86_64.exe
重要:ただしい使いかた、インストール方法は公式を読んでください。


https://docs.bazel.build/versions/4.2.2/bazel-overview.html
ワークスペースの設定
WORKSPACEファイル:Visual Studio の .sln ファイル相当
• 開発ターゲットを管理するディレクトリーの最上位に配置


(bazel コマンドは「ここ」をカレントにして実行する)
• 以下内容を 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/refs/tags/
release-1.11.0.zip"],


strip_prefix = "googletest-release-1.11.0",


sha256 =


"353571c2440176ded91c2de6d6cd88ddd41401d14692ec1f99e35d013feda55a",


)
ビルドの準備
BUILD ファイル:Visual Studio の .vcproj ファイル相当
• test ディレクトリーをつくり以下内容の BUILD ファイルを保存:


cc_test(


name = "test",


srcs = ["test.cc"],


deps = ["@com_google_googletest//:gtest_main"],


)


• ここでは test/test.cc のみからテスト実行形式を作成するように指定
• 本来の別実装ファイルをテストする方法は公式ドキュメントを参照
テストの実装
test/test.cc
#include <gtest/gtest.h>


namespace {


int factorial(int x) {


auto v = 1;


for (; x; x -= 1)


v *= x;


return v;


}


} // namespace


// 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));


}


https://google.github.io/googletest/primer.html#simple-tests の例を改変して利用。
Bazel でのテスト実行
• WORKSPACE のあるディレクトリーで以下を実行:
bazel test //test


• テストディレクトリーでのテスト実行指示(必要ならビルドも走る)
単体テストの約束
❷
テストケースの名前: test_xxx
• テストケースの関数名は test_ で始める
• すべてのテストフレームワークの祖先 JUnit からの慣習
• テストケースを「リフレクション」で自動検出するための規約
• リフレクションが使えない C/C++、 Google Test では無用
テストケースの本体
テストケースは assertEquals のために書く
• 期待する結果を「表明」する:
assertEquals("hello, world.", get_first_message());


• C言語の assert に似ているが単体テスト専用
• 失敗したら次のテストケースの確認に進む(テストはつづく)
• 言語・テストフレームワークによって様々なバリエーションがある
• フレームワークの仕様・ドキュメントをよく読む
• Google Test は ASSERT_EQ の代わりに EXPECT_EQ を推奨
1ケース、1アサーション
• 各テストケースに確かめたい内容をひとつ
• 実際にはいくつ書いてもよい。


しかし、いいテストはシンプルなテスト
テストケースの構造
前提のセットアップ、関数呼びだし、アサート
• テストケースは(ただひとつの)アサーションのためにある
テストケースの書きかた:
1. とことん具体的で身もふたもない名前をテストケースにつける
2. アサートする処理(関数)の呼びだしを書く
3. 処理の呼びだしに必要なセットアップをする
テストケースに共通なセットアップ
setUp() と tearDown()
• 複数のテストケースで共通する準備は setUp() メソッドで
• 同様にその後かたづけを tearDown() で
• テストケースの呼びだしごとに、その前後で呼ばれる
• Google Test では代わりに Fixture をつかう


https://google.github.io/googletest/primer.html#same-data-multiple-
tests
Python


unittest パッケージでの単体テスト
❸
Unittest パッケージ
組みこみサポート: https://docs.python.org/3/library/unittest.html
• Python をインストールしたら利用できる!
% python -m unittest




-----------------------------------------------------------


Ran 0 tests in 0.000s




OK


%
"""test-factorial.py"""


import unittest


def factorial(x: int) -> int:


"""Returns x's factorial."""


return 1


class TestFactorial(unittest.TestCase):


"""Test factorial"""


def test_handles_zero_input(self):


"""Tests factorial of 0."""


self.assertEqual(1, factorial(0))


簡単のため
実装をインポートせず
テスト内で定義
Python 単体テストの書きかた
TestCase クラスを継承し test メソッドを追加する
TestCase を継承
テストケースを
メソッドで実装
テストの実行
テストの検索と実行
• unittest パッケージ経由でテスト実装ファイルを実行
% python -m unittest test-factorial


.


-----------------------------------------------------------


Ran 1 test in 0.000s




OK


%
単体テストのガイドライン
❹
条件分岐しない
条件の数だけテストケースを書く
• ある呼びだしで結果が変わり、それを受けて次の処理が……
• テストを分ける
• セットアップで条件を「確定」する
• 「この場合の結果はこれ」というテストケースを量産する
• リファクタリングの際、壊した条件すべてを検出できる
不可!
断じて不可!!
ゴールから書く
逆順につくる:アサートから関数呼びだし、そしてセットアップ
1. アサーション(確かめたい結果)からはじめる
2. そのアサーションにたどり着くための関数を呼びだす
3. 関数を呼べるようにセットアップする
新規実装では「使いやすい」インターフェース(API)を設計できる。


理にかなった呼びだし。(テストしやすい=直感的につかえる)


単純なセットアップ。(呼びだしの手間をとことん削減)
三角測量
関数をふたつ以上のテストケースでカバー
test_double_1_makes_2() = assertEq(2, get_double(1))


• このテストだけでは get_double(_) = 2 という実装の不正を見抜けない
test_double_0_makes_zero() = assertEq(0, get_double(0))


• テストケースがふたつあれば、実装の不正・サボりを見つけやすくなる
Python 例のコード修正
• サボっていました。実装を
• 複数のテストケースでカバー
• わかりづらい実装の説明にも
三角測量の実際
単体テストの(真の意味での)単体化
モックオブジェクト、依存関係の抽出
• ネットワークへのアクセス、ファイルシステム、データベース接続、……
• これらを必要とする関数にはその「模倣」オブジェクトの注入で対処
• Dependency Injection, Mock Object
• 例えば:
• ファイル名を渡すのでなく、ファイル内容を渡すようインターフェース変更
• ファイルポインター渡しに変え、テストでは open_memstream に差し替え
ビルドへの組みこみ
ビルド後ステップで単体テストを実行
• ビルドとセットで単体テストを実行する
• コードの追加・変更で既存コードを壊していないと確信できる
重要:単体テストの実行時間を短くする。(目指せ! 全ケース実行1秒以内)
テストのリズム ∼ 失敗するテストから始める
フレームワークに保護されていると確かめることから
1. テストケースに assertFail() を書く
• テストして「失敗」する
2. 未実装の関数呼びだしを書く
• ビルドして「失敗」する
3. 「バカ」な実装でアサートを通す
• テストが通る! やった!
4. バカな実装をつかまえるテストケー
スを追加する
• テストが「失敗」する
5. きちんと実装する
• テストが通る! かんぺき
『テスト駆動開発入門』
参考(?): REPL からテストへ
動かせるドキュメントの作成
• これ、どういう動きだったっけ?
• gcc <<EOF -x c && ./a.out


> int main() { …; }


> EOF
• 確認した結果をテストに → 動く(動かせる)ドキュメントに
• 開発者の代わりに利用者が書くテスト
まとめ
学んだこと
• Google Test での単体テストの書きかた
• Python unittest での単体テストの書きかた
• 単体テストの約束、ガイドライン
触れ(られ)なかったトピックス
• Visual Studio 2017 以降での Google
Test 統合
• https://docs.microsoft.com/en-
us/visualstudio/test/how-to-use-
google-test-for-cpp
• macOS/Linux での Google Test
• 単体テストチートシート
• アサートのパターン、例外のテスト
• リファクタリングとテスト
• 『リファクタリング』
• 『レガシーコード改善ガイド』
• テストファースト
• 『テスト駆動開発入門』
• その他のテストフレームワーク
• JUnit, CppUnit, …

Contenu connexe

Tendances

実践イカパケット解析
実践イカパケット解析実践イカパケット解析
実践イカパケット解析Yuki Mizuno
 
.NET Core時代のCI/CD
.NET Core時代のCI/CD.NET Core時代のCI/CD
.NET Core時代のCI/CDYuta Matsumura
 
DockerとPodmanの比較
DockerとPodmanの比較DockerとPodmanの比較
DockerとPodmanの比較Akihiro Suda
 
PlaySQLAlchemy: SQLAlchemy入門
PlaySQLAlchemy: SQLAlchemy入門PlaySQLAlchemy: SQLAlchemy入門
PlaySQLAlchemy: SQLAlchemy入門泰 増田
 
constexpr関数はコンパイル時処理。これはいい。実行時が霞んで見える。cpuの嬌声が聞こえてきそうだ
constexpr関数はコンパイル時処理。これはいい。実行時が霞んで見える。cpuの嬌声が聞こえてきそうだconstexpr関数はコンパイル時処理。これはいい。実行時が霞んで見える。cpuの嬌声が聞こえてきそうだ
constexpr関数はコンパイル時処理。これはいい。実行時が霞んで見える。cpuの嬌声が聞こえてきそうだGenya Murakami
 
.NET Core 3.0時代のメモリ管理
.NET Core 3.0時代のメモリ管理.NET Core 3.0時代のメモリ管理
.NET Core 3.0時代のメモリ管理KageShiron
 
BuildKitの概要と最近の機能
BuildKitの概要と最近の機能BuildKitの概要と最近の機能
BuildKitの概要と最近の機能Kohei Tokunaga
 
20分くらいでわかった気分になれるC++20コルーチン
20分くらいでわかった気分になれるC++20コルーチン20分くらいでわかった気分になれるC++20コルーチン
20分くらいでわかった気分になれるC++20コルーチンyohhoy
 
入門core.async
入門core.async入門core.async
入門core.asyncsohta
 
今日からできる!簡単 .NET 高速化 Tips
今日からできる!簡単 .NET 高速化 Tips今日からできる!簡単 .NET 高速化 Tips
今日からできる!簡単 .NET 高速化 TipsTakaaki Suzuki
 
例外設計における大罪
例外設計における大罪例外設計における大罪
例外設計における大罪Takuto Wada
 
CEDEC 2018 最速のC#の書き方 - C#大統一理論へ向けて性能的課題を払拭する
CEDEC 2018 最速のC#の書き方 - C#大統一理論へ向けて性能的課題を払拭するCEDEC 2018 最速のC#の書き方 - C#大統一理論へ向けて性能的課題を払拭する
CEDEC 2018 最速のC#の書き方 - C#大統一理論へ向けて性能的課題を払拭するYoshifumi Kawai
 
.NET 7 での ASP.NET Core Blazor の新機能ピックアップ
.NET 7 での ASP.NET Core Blazor の新機能ピックアップ.NET 7 での ASP.NET Core Blazor の新機能ピックアップ
.NET 7 での ASP.NET Core Blazor の新機能ピックアップ一希 大田
 
組み込みでこそC++を使う10の理由
組み込みでこそC++を使う10の理由組み込みでこそC++を使う10の理由
組み込みでこそC++を使う10の理由kikairoya
 
怖くないSpring Bootのオートコンフィグレーション
怖くないSpring Bootのオートコンフィグレーション怖くないSpring Bootのオートコンフィグレーション
怖くないSpring Bootのオートコンフィグレーション土岐 孝平
 
ライブラリ作成のすゝめ - 事例から見る個人OSS開発の効能
ライブラリ作成のすゝめ - 事例から見る個人OSS開発の効能ライブラリ作成のすゝめ - 事例から見る個人OSS開発の効能
ライブラリ作成のすゝめ - 事例から見る個人OSS開発の効能Yoshifumi Kawai
 
”30分”ぐらいでわかる「Kubernetes」について
”30分”ぐらいでわかる「Kubernetes」について”30分”ぐらいでわかる「Kubernetes」について
”30分”ぐらいでわかる「Kubernetes」についてYuya Ohara
 

Tendances (20)

実践イカパケット解析
実践イカパケット解析実践イカパケット解析
実践イカパケット解析
 
.NET Core時代のCI/CD
.NET Core時代のCI/CD.NET Core時代のCI/CD
.NET Core時代のCI/CD
 
DockerとPodmanの比較
DockerとPodmanの比較DockerとPodmanの比較
DockerとPodmanの比較
 
PlaySQLAlchemy: SQLAlchemy入門
PlaySQLAlchemy: SQLAlchemy入門PlaySQLAlchemy: SQLAlchemy入門
PlaySQLAlchemy: SQLAlchemy入門
 
constexpr関数はコンパイル時処理。これはいい。実行時が霞んで見える。cpuの嬌声が聞こえてきそうだ
constexpr関数はコンパイル時処理。これはいい。実行時が霞んで見える。cpuの嬌声が聞こえてきそうだconstexpr関数はコンパイル時処理。これはいい。実行時が霞んで見える。cpuの嬌声が聞こえてきそうだ
constexpr関数はコンパイル時処理。これはいい。実行時が霞んで見える。cpuの嬌声が聞こえてきそうだ
 
.NET Core 3.0時代のメモリ管理
.NET Core 3.0時代のメモリ管理.NET Core 3.0時代のメモリ管理
.NET Core 3.0時代のメモリ管理
 
DevOps勉強会
DevOps勉強会DevOps勉強会
DevOps勉強会
 
BuildKitの概要と最近の機能
BuildKitの概要と最近の機能BuildKitの概要と最近の機能
BuildKitの概要と最近の機能
 
Docker Swarm入門
Docker Swarm入門Docker Swarm入門
Docker Swarm入門
 
20分くらいでわかった気分になれるC++20コルーチン
20分くらいでわかった気分になれるC++20コルーチン20分くらいでわかった気分になれるC++20コルーチン
20分くらいでわかった気分になれるC++20コルーチン
 
入門core.async
入門core.async入門core.async
入門core.async
 
今日からできる!簡単 .NET 高速化 Tips
今日からできる!簡単 .NET 高速化 Tips今日からできる!簡単 .NET 高速化 Tips
今日からできる!簡単 .NET 高速化 Tips
 
例外設計における大罪
例外設計における大罪例外設計における大罪
例外設計における大罪
 
CEDEC 2018 最速のC#の書き方 - C#大統一理論へ向けて性能的課題を払拭する
CEDEC 2018 最速のC#の書き方 - C#大統一理論へ向けて性能的課題を払拭するCEDEC 2018 最速のC#の書き方 - C#大統一理論へ向けて性能的課題を払拭する
CEDEC 2018 最速のC#の書き方 - C#大統一理論へ向けて性能的課題を払拭する
 
.NET 7 での ASP.NET Core Blazor の新機能ピックアップ
.NET 7 での ASP.NET Core Blazor の新機能ピックアップ.NET 7 での ASP.NET Core Blazor の新機能ピックアップ
.NET 7 での ASP.NET Core Blazor の新機能ピックアップ
 
組み込みでこそC++を使う10の理由
組み込みでこそC++を使う10の理由組み込みでこそC++を使う10の理由
組み込みでこそC++を使う10の理由
 
怖くないSpring Bootのオートコンフィグレーション
怖くないSpring Bootのオートコンフィグレーション怖くないSpring Bootのオートコンフィグレーション
怖くないSpring Bootのオートコンフィグレーション
 
C#で速度を極めるいろは
C#で速度を極めるいろはC#で速度を極めるいろは
C#で速度を極めるいろは
 
ライブラリ作成のすゝめ - 事例から見る個人OSS開発の効能
ライブラリ作成のすゝめ - 事例から見る個人OSS開発の効能ライブラリ作成のすゝめ - 事例から見る個人OSS開発の効能
ライブラリ作成のすゝめ - 事例から見る個人OSS開発の効能
 
”30分”ぐらいでわかる「Kubernetes」について
”30分”ぐらいでわかる「Kubernetes」について”30分”ぐらいでわかる「Kubernetes」について
”30分”ぐらいでわかる「Kubernetes」について
 

Similaire à 書こう! 使おう! 単体テスト

書こう! 使おう! 単体テスト
書こう! 使おう! 単体テスト書こう! 使おう! 単体テスト
書こう! 使おう! 単体テストryohji ikebe
 
TDD勉強会キックオフ for Java
TDD勉強会キックオフ for JavaTDD勉強会キックオフ for Java
TDD勉強会キックオフ for JavaYuta Kawadai
 
20190722 Building handy CI with zuul and OpenStack
20190722 Building handy CI with zuul and OpenStack20190722 Building handy CI with zuul and OpenStack
20190722 Building handy CI with zuul and OpenStackAkihiro Motoki
 
Azure DevOpsとVisual Studio App CenterをモバイルアプリのCI/CDに活用しよう
Azure DevOpsとVisual Studio App CenterをモバイルアプリのCI/CDに活用しようAzure DevOpsとVisual Studio App CenterをモバイルアプリのCI/CDに活用しよう
Azure DevOpsとVisual Studio App CenterをモバイルアプリのCI/CDに活用しようShinya Nakajima
 
継続的インテグレーション3分クッキング
継続的インテグレーション3分クッキング継続的インテグレーション3分クッキング
継続的インテグレーション3分クッキングTakayuki Kondou
 
Code igniterでテスト駆動開発 資料作成中
Code igniterでテスト駆動開発 資料作成中Code igniterでテスト駆動開発 資料作成中
Code igniterでテスト駆動開発 資料作成中Takako Miyagawa
 
Eclipse を使った java 開発 111126 杉浦
Eclipse を使った java 開発 111126 杉浦Eclipse を使った java 開発 111126 杉浦
Eclipse を使った java 開発 111126 杉浦urasandesu
 
Firefoxの開発プロセス
Firefoxの開発プロセスFirefoxの開発プロセス
Firefoxの開発プロセスMakoto Kato
 
Getting Started with Testing using PHPUnit
Getting Started with Testing using PHPUnitGetting Started with Testing using PHPUnit
Getting Started with Testing using PHPUnitAtsuhiro Kubo
 
究極のバッチフレームワーク(予定)
究極のバッチフレームワーク(予定)究極のバッチフレームワーク(予定)
究極のバッチフレームワーク(予定)fumoto kazuhiro
 
CIBC workshop by imagire
CIBC workshop by imagireCIBC workshop by imagire
CIBC workshop by imagireTakashi Imagire
 
Pythonを取り巻く開発環境 #pyconjp
Pythonを取り巻く開発環境 #pyconjpPythonを取り巻く開発環境 #pyconjp
Pythonを取り巻く開発環境 #pyconjpYoshifumi Yamaguchi
 
ALMツールたべくらべ
ALMツールたべくらべALMツールたべくらべ
ALMツールたべくらべKaoru NAKAMURA
 
Hello. Continuous Integration
Hello. Continuous IntegrationHello. Continuous Integration
Hello. Continuous IntegrationYuki Matsumura
 
Jenkins+Play!で気軽にCI
Jenkins+Play!で気軽にCIJenkins+Play!で気軽にCI
Jenkins+Play!で気軽にCITakafumi Ikeda
 
パッケージングの今
パッケージングの今パッケージングの今
パッケージングの今Atsushi Odagiri
 

Similaire à 書こう! 使おう! 単体テスト (20)

書こう! 使おう! 単体テスト
書こう! 使おう! 単体テスト書こう! 使おう! 単体テスト
書こう! 使おう! 単体テスト
 
TDD勉強会キックオフ for Java
TDD勉強会キックオフ for JavaTDD勉強会キックオフ for Java
TDD勉強会キックオフ for Java
 
20190722 Building handy CI with zuul and OpenStack
20190722 Building handy CI with zuul and OpenStack20190722 Building handy CI with zuul and OpenStack
20190722 Building handy CI with zuul and OpenStack
 
Gamedevenvstudy1
Gamedevenvstudy1Gamedevenvstudy1
Gamedevenvstudy1
 
Azure DevOpsとVisual Studio App CenterをモバイルアプリのCI/CDに活用しよう
Azure DevOpsとVisual Studio App CenterをモバイルアプリのCI/CDに活用しようAzure DevOpsとVisual Studio App CenterをモバイルアプリのCI/CDに活用しよう
Azure DevOpsとVisual Studio App CenterをモバイルアプリのCI/CDに活用しよう
 
継続的インテグレーション3分クッキング
継続的インテグレーション3分クッキング継続的インテグレーション3分クッキング
継続的インテグレーション3分クッキング
 
PHP agile test tips
PHP agile test tipsPHP agile test tips
PHP agile test tips
 
Code igniterでテスト駆動開発 資料作成中
Code igniterでテスト駆動開発 資料作成中Code igniterでテスト駆動開発 資料作成中
Code igniterでテスト駆動開発 資料作成中
 
Eclipse を使った java 開発 111126 杉浦
Eclipse を使った java 開発 111126 杉浦Eclipse を使った java 開発 111126 杉浦
Eclipse を使った java 開発 111126 杉浦
 
Firefoxの開発プロセス
Firefoxの開発プロセスFirefoxの開発プロセス
Firefoxの開発プロセス
 
Getting Started with Testing using PHPUnit
Getting Started with Testing using PHPUnitGetting Started with Testing using PHPUnit
Getting Started with Testing using PHPUnit
 
究極のバッチフレームワーク(予定)
究極のバッチフレームワーク(予定)究極のバッチフレームワーク(予定)
究極のバッチフレームワーク(予定)
 
CIBC workshop by imagire
CIBC workshop by imagireCIBC workshop by imagire
CIBC workshop by imagire
 
Pythonを取り巻く開発環境 #pyconjp
Pythonを取り巻く開発環境 #pyconjpPythonを取り巻く開発環境 #pyconjp
Pythonを取り巻く開発環境 #pyconjp
 
Python Autotest pdc2008w
Python Autotest pdc2008wPython Autotest pdc2008w
Python Autotest pdc2008w
 
ALMツールたべくらべ
ALMツールたべくらべALMツールたべくらべ
ALMツールたべくらべ
 
Hello. Continuous Integration
Hello. Continuous IntegrationHello. Continuous Integration
Hello. Continuous Integration
 
Jenkins+Play!で気軽にCI
Jenkins+Play!で気軽にCIJenkins+Play!で気軽にCI
Jenkins+Play!で気軽にCI
 
パッケージングの今
パッケージングの今パッケージングの今
パッケージングの今
 
Visual studio de debug
Visual studio de debugVisual studio de debug
Visual studio de debug
 

書こう! 使おう! 単体テスト