この記事を読んだらどうなれるか
この記事を読み終わった後に、読者が以下の三つを達成できるような記事になっています。
1.ソースコードをテストすることの意義を理解する
2.Pythonのテストコードをどのように書くのか、雰囲気をつかむ
3.Pythonによるテストコードの書かれたファイルを単一で実行できる
実行環境
OS: macOS Mojava 10.14.6
Pythonバージョン: 3.7.1
テストコードを書く意義
テストはソースコードの品質を保証するために書きます。
バグのない完璧なソースコードを書きました〜と言われて渡されたソースコードを信用できるでしょうか。
全くミスしない人がいるとしたら、信用してもいいのかもしれません。しかし、人は往々にしてミスするものです。
テストがある程度書かれていれば、ソースコードの品質を信用することができます。
また、テストがあれば、ソースコードが正しく作られているかを判断する基準として利用することもできます。
それではPythonでテストを書いていきましょう!
最大公約数を算出するメソッドのテストを書く
1. テストするメソッドの仕様
テストする対象として、最大公約数を算出するメソッドを考えます。
最大公約数を英語で言うとGreatest Common Divisorです。頭文字をとってファイル名をgcd.py
としましょう。
def gcd(a, b):
# なんかしてa,bの最大公約数を算出
return # 戻り値は最大公約数
gcd()の引数a,bは整数が入力されることを想定するものとし、戻り値としてa,bの最大公約数を返します。
テストする関数の仕様が固まったところで、テストコードを書いていきましょう。
2. テストコードを書くためにimport
するのはこれ!
今回、Pythonでテストコードを記述するために使用するのは、unittest
と呼ばれるモジュールです。
標準搭載のため、インストールする必要はありません。
早速importしてみましょう。
import unittest
from gcd import gcd
テスト対象であるgcd()をテストするためにgcd.py
の関数gcd
もインポートしておきましょう。
これでテストコードを書く準備が整いました。
3. テストケースを作成しよう
次にテストケースを作成していきます。
テストケースというのは、あるモジュールや、あるクラスに備わっている機能が正しく動作することを確認するために入力と、入力から想定される出力を一つ以上定義したものです。
まずはテストケースを内包するクラスを作成します。
import unittest
from gcd import gcd
class GCDTest(unittest.TestCase):
pass
テストケースはunittestモジュールのTestCaseクラスを継承して宣言します。
unittest.TestCase
を継承することによって、テストケースを作成する上で必要なメソッド類を利用できるようになります。
クラス名(テストケース名)は、最大公約数をテストするものなので、GCDTestにしてみました。
4. テストを書いてみる
それでは最大公約数を算出するメソッドのテストを書いてみましょう。
import unittest
from gcd import gcd
class GCDTest(unittest.TestCase):
def test_gcd(self):
self.assertEqual(15, gcd(30, 15))
pass
test_gcd
と呼ばれるメソッドを実装しました。
今回は二つの整数の最大公約数を算出するメソッドを実装したいのですから、a = 30, b = 15が入力されたのであれば、戻り値は15にならなければなりません。
これをチェックしているのが、self.assertEqual(15, gcd(30, 15))
です。
gcd(30, 15)
の結果が15
であることを確認しています。
assertという英語は、「断言する」というような意味を持つ単語であることを踏まえると、理解が容易になります。
self.assertEqual(15, gcd(30, 15))
は、「gcd(30,15)の結果は15と等しくなる」ということを断言しているのです。わかりやすいですね。
5. テストを実行してみよう
テストの実行には以下のコマンドを利用します。
python -m unittest `作成したモジュール名`
今回作成したモジュールは、test_gcd.py
です。
test_gcd.py
を指定して、実行してみます。
python -m unittest test_gcd.py
失敗していますが、実装していないので当然ですね。
どこでテストが失敗したのか、実行されたテストの個数、実行時間などが示されます。
gcdメソッドを実装してもう一度実行してみましょう。
def gcd(a, b):
return b if a%b == 0 else gcd(b, a%b)
実装についてはユークリッドの互除法というのを使っています。ユークリッドの互除法は、最大公約数を高速に求められるアルゴリズムです。
ここでは触れませんので、気になる人は調べてみてください。
それでは、実装できたところで、python -m unittest test_gcd.py
を実行!
テストが通過したため、OKと表示されました。やったね。
テストを書く上で注意すること
今回書いたテストは、self.assertEqual(15, gcd(30, 15))
だけでした。
これは、テストケースとして十分でしょうか。
答えは否です。一つだけのチェックで対象のメソッドが正しく実装できているとは言えません。
なぜなら、今回のチェック項目だけでは以下のような実装でもテストケースを通過してしまうからです。
def gcd(a, b):
return 15
これではどんな入力だったとしても最大公約数は15であるということになってしまいます。
ケーステストを書く際には、入力と出力のパターンにどのようなものがあるのかを考え、網羅するように心がけましょう。
まとめ
・テストはソースコードの品質を保証するために記述する
・Pythonのテストを作成するのにはunittest
モジュールを使用する
・テストケースを作成するときは、unittest.TestCase
を継承する。
・テストケースとは、入力と、入力から想定される出力のあつまり
・python -m unittest モジュール名
で該当ファイルのテストケースを実行できる
・テストケースは入力と出力のパターンにどのようなものがあるのかを考え、十分に網羅するようにする
次の記事
本記事の内容は、とにかく雰囲気を掴む、という観点で書きました。
そのため、細かいお作法などについて触れられていません。
これについては、次の記事で補足していく予定です。
Coming Soon!