最近追加されたテスティングフレームワークを試したみた。
Djangoは基本的にはPython由来のdoctestやunittestを用いてテストを行う。最近追加されたテスティングフレームワークは、アプリケーションの直下にあるmodels.pyやtests.pyを自動的にAllテストしてくれるというもの+Viewのテストを行う疑似ブラウザともいえるClientというクラス。
Railsと同じく、Djangoもテストの前にテスト用データベース・テーブルを生成し、初期データを流し込み(fixtureは現在実装中)、テストを行い、テスト用データベースを破棄するという流れ。おいおい、そんな流れは業務系とか既存データベース使うアプリにはできんぞ、せめてビューとかシノニムとかに気づいてくれよー。
とか思いつつ。(現実的には、デフォルトのTEST_RUNNER設定であるdjango.test.simple.run_testsをそのままは利用せずに、ちょっと振る舞いをかえたTEST_RUNNERを利用することになるんだろうな。Djangoは素直にコードが書いてあるから自作も簡単だろう。)
class ExpenseItemManager(models.Manager) :
"""費目モデルのマネージャ。デフォルトのQuerysetに、非表示は取得しない、という条件を付与している。
"""
def get_query_set(self) :
return super(ExpenseItemManager, self).get_query_set().filter(visible=True)
class ExpenseItem(models.Model) :
"""費目を表すモデル。
デフォルト動作の変更をいくつか実装してある。
- デフォルトのdeleteを上書き
- デフォルトのマネージャの上書き
- カスタムマネージャの追加。
>>> invisItem = ExpenseItem.objects.create(name="Test Invisible", max_amount=4000, food_cost=False, visible=True)
>>> delItem = ExpenseItem.objects.create(name="Test Delete" , max_amount=4000, food_cost=False, visible=True)
>>> before = ExpenseItem.objects.all()
>>> invisItem in before
True
>>> delItem in before
True
>>> invisItem.visible=False
>>> invisItem.save()
>>> delItem.delete()
>>> after = ExpenseItem.objects.all()
>>> invisItem in after
False
>>> delItem in after
False
"""
name = models.CharField(_('Expense Item Name'), blank=False, maxlength=30)
max_amount = models.IntegerField(_('Max Amount'), blank=False, default=0, help_text=_('Max amount per month.'))
food_cost = models.BooleanField(_('Food Cost Flag'), default=False, help_text=_('weather food cost or not'))
visible = models.BooleanField(_('Visible Flag'), default=True, help_text=_('if expense item is invisible, you can\'t edit anymore.'))
objects = ExpenseItemManager() #デフォルトのマネージャをカスタムマネージャに変更
summary_objects = ExpenseItemSummaryManager() #サマリー用のマネージャを登録
class Admin :
list_display = ("name", "max_amount", "visible", "food_cost")
ordering = ['id']
class Meta :
verbose_name = _('Expense Item')
verbose_name_plural = _('Expense Items')
def __str__(self) :
"""オブジェクトの人間可読表現
"""
return self.name
def delete(self) :
"""費目を物理削除すると関連する出費も含めて削除されてしまうため、モデルを利用しての削除はできないようにしてある。
代わりに、削除を呼ぶと「表示フラグ」をオフにするようにし、同時にマネージャをカスタムマネージャとし、デフォルトのQuerysetに「表示フラグ」オンという条件を入れるようにした。これにより、費目を管理画面から削除すると、「削除した費目を管理画面で編集できない」「削除した費目は出費の追加画面に候補として出てこない」という動作を実現している。
"""
self.visible = False
self.save()
import unittest
from djengel.squander.models import ExpenseItem
class ExpenseItemTest(unittest.TestCase) :
def setUp(self) :
self.invisItem = ExpenseItem.objects.create(name="Test Invisible", max_amount=4000, food_cost=False, visible=True)
self.delItem = ExpenseItem.objects.create(name="Test Delete" , max_amount=4000, food_cost=False, visible=True)
def tearDown(self) :
pass
def test_normal(self) :
before = ExpenseItem.objects.all()
assert self.invisItem in before
assert self.delItem in before
def test_delete(self) :
self.delItem.delete()
after = ExpenseItem.objects.all()
assert self.delItem not in after
def test_invisible(self) :
self.invisItem.visible=False
self.invisItem.save()
after = ExpenseItem.objects.all()
assert self.invisItem not in after
import unittest
from djengel.squander.models import ExpenseItem
from django.test.client import Client
from django.contrib.auth.models import User, Permission
class SquanderViewTest(unittest.TestCase) :
def setUp(self) :
self.client = Client()
self.user = User.objects.create_user('mam', '', 'mampass')
view_permission = Permission.objects.get(codename__exact='can_view')
self.user.user_permissions = [view_permission]
def tearDown(self) :
self.user.delete()
def test_login(self) :
respon = self.client.login('/djengel/summary/2006/08/','mam', 'mampass')
last_response = respon.context[len(respon.context) - 1]
assert '2006/07/' == last_response.get('prev_month', False)
print last_response.__dict__
def test_login_failed(self) :
assert not self.client.login('/djengel/summary/2006/08/','dad', 'mampass')
#3711 対応済みです :)
2 by nakagami
09:27 on
2006-09-04
テスト入りのソースアーカイブはどっかに公開されないもんでしょうか?
3 by everes
11:08 on
2006-09-04
nakagamiさんにご指摘いただいた初期SQLの問題とf3cさんのMySQLパッチをいい感じに適用して、ほんの少しのテストコードを含ませたものを、近いうちに作成します。
が、ちょっと本業が忙しく(つらいスキーマのOracleにDjangoを突っ込んでいます)、週末待ちかもしれません。
> ymasudaさん
ひじょーに!助かります。
1 by ymasuda
07:31 on
2006-09-04