Last active
August 29, 2015 14:19
-
-
Save 0xfffffff7/2abda0214ee17cc0a180 to your computer and use it in GitHub Desktop.
Pythonのデバッグとテストモジュール ref: http://qiita.com/0xfffffff7/items/b0c3a747522943df434f
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
test = 0 | |
data = "assertion error" | |
try: | |
assert test,data | |
except AssertionError: | |
print data | |
finally: | |
print "the end" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
if __debug__: | |
if not test | |
raise AssertionError, data |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# 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) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# 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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
nosetest | |
..... | |
---------------------------------------------------------------------- | |
Ran 5 tests in 0.004s | |
OK |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
pip install coverage |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# 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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# 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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
coverage xml |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# coding: UTF-8 | |
class Widget(object): | |
def __init__(self): | |
self.value = 10 | |
def Additional(self, add): | |
self.value += add | |
return self.value |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
100 | |
21 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# 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() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# 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() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
mock = Mock(spec=SomeClass) | |
isinstance(mock, SomeClass) #これが成功する |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# 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() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@patch('sys.stdout', new_callable=StringIO) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
pip install webtest | |
pip install django-webtest |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# sudo python manage.py test testapp |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Creating test database for alias 'default'... | |
. | |
---------------------------------------------------------------------- | |
Ran 1 test in 0.175s | |
OK | |
Destroying test database for alias 'default'... |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
exc_type, exc_value, exc_traceback = sys.exc_info() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
error | |
the end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
pip install nose |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment