Skip to content

Instantly share code, notes, and snippets.

@0xfffffff7
Last active August 29, 2015 14:19
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save 0xfffffff7/2abda0214ee17cc0a180 to your computer and use it in GitHub Desktop.
Save 0xfffffff7/2abda0214ee17cc0a180 to your computer and use it in GitHub Desktop.
Pythonのデバッグとテストモジュール ref: http://qiita.com/0xfffffff7/items/b0c3a747522943df434f
test = 0
data = "assertion error"
try:
assert test,data
except AssertionError:
print data
finally:
print "the end"
if __debug__:
if not test
raise AssertionError, data
# coding: UTF-8
class NotEnoughFundsException(Exception):
pass
class BankAccount(object):
def __init__(self):
self._balance = 0
def deposit(self, amount):
self.balance += amount
def withdraw(self, amount):
self.balance -= amount
def get_balance(self):
return self._balance
def set_balance(self, value):
if value < 0:
raise NotEnoughFundsException
self._balance = value
# ゲッターとセッターを使えるようにラッパーを用意する。
# balanceに=や+でアクセスすることでこれらの関数が自動で呼ばれるようになる。
balance = property(get_balance, set_balance)
# coding: UTF-8
import unittest
class BankAccountTest(unittest.TestCase):
def _getTarget(self):
from bankaccount import BankAccount
return BankAccount
# テスト対象のインスタンスを作成する。
def _makeOne(self, *args, **kwargs):
return self._getTarget()(*args, **kwargs)
def test_construct(self):
target = self._makeOne()
self.assertEqual(target._balance, 0)
def test_deposit(self):
target = self._makeOne()
target.deposit(100)
self.assertEqual(target._balance, 100)
def test_withdraw(self):
target = self._makeOne()
target._balance = 100
target.withdraw(20)
self.assertEqual(target._balance, 80)
def test_get_blance(self):
target = self._makeOne()
target._balance = 500
self.assertEqual(target.get_balance(), 500)
def test_set_balance_not_enough_funds(self):
target = self._makeOne()
from bankaccount import NotEnoughFundsException
try:
target.set_balance(-1)
self.fail()
except NotEnoughFundsException:
pass
nosetest
.....
----------------------------------------------------------------------
Ran 5 tests in 0.004s
OK
pip install coverage
# nosetests -v --with-coverage
test_construct (test_bankaccount.BankAccountTest) ... ok
test_deposit (test_bankaccount.BankAccountTest) ... ok
test_get_blance (test_bankaccount.BankAccountTest) ... ok
test_set_balance_not_enough_funds (test_bankaccount.BankAccountTest) ... ok
test_withdraw (test_bankaccount.BankAccountTest) ... ok
Name Stmts Miss Cover Missing
-------------------------------------------
bankaccount 16 0 100%
----------------------------------------------------------------------
Ran 5 tests in 0.006s
OK
# nosetests -v -w . --with-coverage --with-xunit
test_construct (test_bankaccount.BankAccountTest) ... ok
test_deposit (test_bankaccount.BankAccountTest) ... ok
test_get_blance (test_bankaccount.BankAccountTest) ... ok
test_set_balance_not_enough_funds (test_bankaccount.BankAccountTest) ... ok
test_withdraw (test_bankaccount.BankAccountTest) ... ok
----------------------------------------------------------------------
XML: nosetests.xml
Name Stmts Miss Cover Missing
-------------------------------------------
bankaccount 16 0 100%
----------------------------------------------------------------------
Ran 5 tests in 0.006s
OK
coverage xml
# coding: UTF-8
class Widget(object):
def __init__(self):
self.value = 10
def Additional(self, add):
self.value += add
return self.value
from mock import Mock
from test import Test
def mock_value(value):
return 20 + value
if __name__ == '__main__':
# 関数を置き換えて、100を固定で返すモックにする。
Test.Widget.Additional = Mock(return_value=100)
w = Test.Widget()
print w.Additional(1)
# 固定値ではなく、なんらかの計算をする場合はside_effectでダミー関数を渡す。
Test.Widget.Additional = Mock(side_effect=mock_value)
print w.Additional(1)
somedata = 1
# キャッチしたい例外をタプルでまとめておく。
fatal_exceptions = (KeyboardInterrupt, MemoryError)
try:
assert somedata
except fatal_exceptions, inst: # 引数instで例外の内容を受け取ることができる。
print type(inst) # 例外の型を表示
print inst # 例外の内容を表示
raise
# それ以外の例外をまとめてキャッチ
except Exception, inst:
print type(inst) # 例外の型を表示
print inst # 例外の内容を表示
finally:
print "the end"
from mock import Mock
from test import Test
def mock_value(value):
return 20 + value
if __name__ == '__main__':
# クラス自体を置き換える。
Test.Widget = Mock()
# 関数の返す値を固定してしまう。
Test.Widget.return_value.Additional.return_value = 10
w = Test.Widget()
print w.Additional(1)
# 関数を入れ替える
Test.Widget.return_value.Additional = mock_value
print w.Additional(1)
# coding: UTF-8
from mock import patch
# この関数実行中だけ置き換えるメソッドと戻り値を指定
@patch("Test.Widget.Additional", return_value=10)
def test_func(m):
import Test
w = Test.Widget()
print w.Additional(1)
assert w.Additional(1) == 10
# ちなみに引数で受け取ったmはモックに置き換えられたAdditional関数
# だからこちらも結果は10になる。
# 今回はメソッドを置き換えたが、クラスの場合はクラスになる。
print m()
if __name__ == '__main__':
test_func()
# coding: UTF-8
from mock import patch
def test_func():
# このwithスコープ実行中だけ置き換えるメソッドと戻り値を指定
with patch("Test.Widget.Additional", return_value=10) as m:
import Test
w = Test.Widget()
print w.Additional(1)
assert w.Additional(1) == 10
print m()
if __name__ == '__main__':
test_func()
mock = Mock(spec=SomeClass)
isinstance(mock, SomeClass) #これが成功する
# coding: UTF-8
from mock import Mock, patch
if __name__ == '__main__':
# methodという名前で3を返すメソッドと、
# otherという名前でKeyError例外を発生させるメソッド
attrs = {'method.return_value': 3, 'other.side_effect': KeyError}
# 宣言と同時にアトリビュート追加もできる(some_attribute)。
mock = Mock(some_attribute='eggs', **attrs)
print mock.some_attribute
print mock.method()
print mock.other()
@patch('sys.stdout', new_callable=StringIO)
pip install webtest
pip install django-webtest
mysite
|-mysite
| |-__init__.py
| |-settings.py
| |-urls.py
| |-wsgi.py
|-test app
| |-__init__.py
| |-form.py
| |-modes.py
| |-views.py
| |-tests.py  このファイルに今回のテストを書く|
|-templates
|-manage.py
from django_webtest import WebTest
class TestIndex(WebTest):
def test_index(self):
res = self.app.get("/") #レスポンスを取得する
# ステータスコードやコンテンツ内容をチェックする。
assert res.status == '200 OK'
assert 'html' in res
# sudo python manage.py test testapp
import random
import unittest
class TestSequenceFunctions(unittest.TestCase):
# 毎回呼ばれる初期化処理
# この他にテスト実行後などに呼ばれるメソッドがある
def setUp(self):
self.seq = range(10)
# testで始まるメソッド名を記述する。
def test_shuffle(self):
random.shuffle(self.seq)
self.seq.sort()
# 二つの引数がイコールであることをチェックする。
# 等しくないことのチェックはassertNotEqual()で行える。
self.assertEqual(self.seq, range(10))
# 例外が発生することのチェックを行う。
# assertRaises(exception, callable, *args, **kwds)
# 第二引数の関数にargsとkwdsを渡して、第一引数で指定した例外が発生することをチェックする。
self.assertRaises(TypeError, random.shuffle, (1,2,3))
def test_choice(self):
element = random.choice(self.seq)
# 引数の値がTrueであることをチェックする。
# bool(element) is True と等価
self.assertTrue(element in self.seq)
def test_sample(self):
# exception 引数のみが渡された場合には、コンテキストマネージャが返される。
# インラインでテスト対象のコードを書くことができる。
with self.assertRaises(ValueError):
random.sample(self.seq, 20)
for element in random.sample(self.seq, 5):
self.assertTrue(element in self.seq)
if __name__ == '__main__':
# main()で実行できる。
unittest.main()
# 個別に実行するテストを取得する。
_test_choice = TestSequenceFunctions('test_choice')
_test_sample = TestSequenceFunctions('test_sample')
# テストスイートに登録してランナーでまとめて実行できる。
TestSuite = unittest.TestSuite()
TestSuite.addTest(_test_choice)
TestSuite.addTest(_test_sample)
runner = unittest.TextTestRunner()
runner.run(TestSuite)
# ローダーでまとめてテスト関数を取得できる。
suite = unittest.TestLoader().loadTestsFromTestCase(TestSequenceFunctions)
unittest.TextTestRunner(verbosity=2).run(suite)
Creating test database for alias 'default'...
.
----------------------------------------------------------------------
Ran 1 test in 0.175s
OK
Destroying test database for alias 'default'...
exc_type, exc_value, exc_traceback = sys.exc_info()
import sys
import traceback
def somework():
try:
print a # 定義されていない変数を使用する
except Exception:
print "error"
traceback.print_exc(file=sys.stdout)
finally:
print "the end"
if __name__ == '__main__':
somework()
error
Traceback (most recent call last):
File "/Users/test.py", line 8, in somework
print a
NameError: global name 'a' is not defined
the end
error
the end
import sys
import traceback
def somework():
try:
print a # 定義されていない変数を使用する
except Exception:
print "error"
exc_type, exc_value, exc_traceback = sys.exc_info()
print traceback.extract_tb(exc_traceback) # 現在の情報だけを取得
print traceback.extract_stack() # 呼び出し元の関数情報を含むタプルを取得
# タプルではなく単にリストで受け取って表示しやすくしたい場合はこれを呼ぶ。
traceback.format_tb(exc_traceback)
traceback.format_stack()
print "the end"
if __name__ == '__main__':
somework()
pip install nose
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment