■ はじめに
https://dk521123.hatenablog.com/entry/2019/10/02/223658
の続き。
目次
【1】Tips 1)基本的なテンプレート 2)出力値の確認 3)例外に関する試験 【2】サンプル 1)簡単なクラスの単体試験 2)メソッドの単体試験 3)例外の単体試験 4)継承したクラスの単体試験&setUp/tearDown
【1】Tips
1)基本的なテンプレート
import unittest # from 【対象ファイル】 import 【対象メソッド】 from sample import is_prime # clsss 【ファイル名】Test(unittest.TestCase): class SampleTest(unittest.TestCase): # テストを書いていく def test_is_prime_yes(self): for i in [2, 3, 5, 7, 11, 13, 17, 19]: self.assertTrue(is_prime(i)) # ... if __name__ == '__main__': unittest.main()
2)出力値の確認
構文
# 期待値と同じかどうか self.assertEqual(【値1】, 【値2】) # boolean self.assertTrue(【Boolean値】) self.assertFalse(【Boolean値】)
3)例外に関する試験
構文
with self.assertRaises(【例外】): # 例外を出すメソッドをコール
例
def test_is_prime_raise_error(self): with self.assertRaises(TypeError): is_prime('dummy')
参考文献
https://hiroronn.hatenablog.jp/entry/20181004/1538611164
【2】サンプル
1)簡単なクラスの単体試験
calculator.py (単体試験の対象クラス)
class Calculator(object): def plus(self, x, y): return x + y
calculator_test.py
import unittest import calculator class CalculatorTest(unittest.TestCase): def test_plus(self): claz = calculator.Calculator() self.assertEqual(claz.plus(2, 1), 3) if __name__ == '__main__': unittest.main()
出力結果(成功時)
---------------------------------------------------------------------- Ran 1 test in 0.001s OK
出力結果(「self.assertEqual(claz.plus(2, 1), 4)」と修正し意図的に失敗させた場合)
====================================================================== FAIL: test_plus (__main__.CalculatorTest) ---------------------------------------------------------------------- Traceback (most recent call last): File "c:\Users\Daisuke\Documents\Python Scripts\calculator_test.py", line 7, in test_plus self.assertEqual(claz.plus(2, 1), 4) AssertionError: 3 != 4 ---------------------------------------------------------------------- Ran 1 test in 0.002s FAILED (failures=1)
2)メソッドの単体試験
test_file_path_utils.py
import unittest # 対象のPythonファイル import file_path_utils class FilePathUtilsTest(unittest.TestCase): def test_convert_file_extention(self): file_name = 'hello.world.txt' extention = 'csv' expected = 'hello.world.csv' actual = file_path_utils.convert_file_extention(file_name, extention) self.assertEqual(expected, actual) if __name__ == '__main__': unittest.main()
file_path_utils.py
import os def convert_file_extention(file_name, extention): file_name_without_extention = os.path.splitext(file_name)[0] return "{}.{}".format(file_name_without_extention, extention)
3)例外の単体試験
calculator.py
def add(num1, num2): if (not num1 or not num2): raise ValueError('input is None') return num1 + num2
calculator.py
import unittest import calculator class CalculatorTest(unittest.TestCase): def test_add(self): self.assertEqual(calculator.add(2, 1), 3) with self.assertRaises(ValueError): calculator.add(None, 1) with self.assertRaises(ValueError): calculator.add(1, None) if __name__ == '__main__': unittest.main()
4)継承したクラスの単体試験&setUp/tearDown
[親クラス] base_demo_class.py
class BaseDemoClass(object): def __init__(self): self.base_value = 'World' def say_hello(self): return f'Hello {self.base_value}!' def say_hi(self, name): return f'Hi, {name}'
[テスト対象クラス] demo_class.py
from base_demo_class import BaseDemoClass class DemoClass(BaseDemoClass): def __init__(self): super().__init__() self.value = 'Sam' def say_thank_you(self): return f'Thank you, {self.value}!' # 簡易動作確認用 if __name__ == '__main__': print('Start') target_class = DemoClass() print(target_class.say_thank_you()) print(target_class.say_hello()) print(target_class.say_hi('Mike')) print('Done')
test_demo_class.py
import unittest from demo_class import DemoClass class TestDemoClass(unittest.TestCase): # テストクラスが初期化される際に一度だけ呼ばれる @classmethod def setUpClass(cls): print('setUpClass') # テストクラスが解放される際に一度だけ呼ばれる @classmethod def tearDownClass(cls): print('tearDownClass') # テストメソッドを実行するたびに呼ばれる def setUp(self): print('setUp') self.target_class = DemoClass() # テストメソッドの実行が終わるたびに呼ばれる def tearDown(self): print('tearDown') # 1) say_hello def test_say_hello(self): self.assertEqual( self.target_class.say_hello(), 'Hello World!') # 2) say_hi def test_say_hi(self): self.assertEqual( self.target_class.say_hi('Kevin'), 'Hi, Kevin') # 3) say_thank_you def test_say_thank_you(self): self.assertEqual( self.target_class.say_thank_you(), 'Thank you, Sam!') if __name__ == '__main__': unittest.main()
参考文献
https://code-schools.com/python-unittest/
https://www.python.ambitious-engineer.com/archives/828
関連記事
単体試験 / unittest ~ 入門編 ~
https://dk521123.hatenablog.com/entry/2019/10/02/223658
単体試験 / mox ~ 入門編 ~
https://dk521123.hatenablog.com/entry/2020/01/19/000000
単体試験 / nose ~ 入門編 ~
https://dk521123.hatenablog.com/entry/2020/01/20/221014
単体試験 / pytest ~ 入門編 ~
https://dk521123.hatenablog.com/entry/2020/12/13/224810