django で作成メソッドのリファクタリングをしたくなり、
django-nose をインストールしたものの、
テスト書き始めでいきなりどうして良いのかわからなくなったので、
個人的にわからなかったポイントをメモします。
前提
django を使用していて、
且つ、
以下を参考にdjango-nose をインストールしていること
Tips
1. Testクラスはどこに置けば良いか?
{Django_Project_Home}/{Target_App}/tests 配下に、
__init__.py と一緒に配置しました。
__init__.py にはログ出力用途で以下の記述をしてあります。
def setup_package():
print('')
print(__name__, '__init__.py : setup_package() ========================================')
def teardown_package():
print(__name__, '__init__.py : teardown_package() =====================================')
2. 標準出力にTest のログを出力する。
test コマンドでテストが実行できますが、デフォルトだと test に仕込んだ print の結果が出力されません。
python manage.py test
-s オプションを付与することで、printの結果が標準出力されます。
python manage.py test -s
settings.py の NOSE_ARGS に'--nocapture''--nologcapture',のオプションを追加しても出力されるようになります。
NOSE_ARGS = [
.......
'--nocapture',
'--nologcapture',
]
参考サイトは、NOSE_ARGS に指定するの押しでしたが、真面目に実装する時は、logger使うかと思うので、
-s オプションによる実行で十分に個人的には思います。
3. テストデータを投入したい。
sqlite を使用している限りはテスト実行時は、デフォルト動作で何もしなくても、
開発環境とは別のデータベースが作成されました。
データがからっぽでテスト実行時にマスタデータを投入したかったので、
以下のように実装しました。
import unittest
from django.core import management
from analyze_metrics_view.forms import get_category_choicese_relations, get_veiw_choices_relations
class TestSelectViewForm(unittest.TestCase):
@classmethod
def setup_class(clazz):
print(__name__, ": setup_class")
management.call_command('loaddata', 'fixture/initial_data.json', verbosity=0)
pass
# このクラスのテストケースをすべて実行した後に1度だけ実行する
@classmethod
def teardown_class(clazz):
print(__name__, ": teardown_class")
management.call_command('flush', verbosity=0, interactive=False)
pass
django-nose の機能というか、django のコマンドを直接実行する形で、
テストデータを投入します。
initial_data は作成しておく必要があります。
-
参考サイト(
initial_dataの作成)
Providing initial data for models | Django documentation | Django -
参考サイト(テスト中のデータ投入)
How to load fixtures only once in django unit tests ? - Stack Overflow
4. 辞書を Assert したい。
参考サイトのみ記載。どちらでもアサートできました。
副作用なかったのでassert all の方がよさそうです。
- 参考サイト
Pythonでdictを比較してassertしたい - Life is Really Short, Have Your Life!! python - Assert that two dictionaries are almost equal - Stack Overflow
5. Tupleを Assert したい。
nose.tools の assert_equals でassert できました。
2次元Tuple だったのですが、普通にOKでした。
nose.tools.assert_equals(expect, result)
6. Testcaseが unittest.TestCase を継承するかしないかで、setupメソッドの挙動が変わる。
辞書のassertのため unittest.TestCase を途中から継承してテストケースを作ったのですが、
setup メソッドが呼び出されなくなりました。
import unittest
class TestSelectViewForm(unittest.TestCase):
# このクラスの各テストケースを実行する前に実行する
def setup(self):
print(__name__, ": setup")
pass
# このクラスの各テストケースを実行した後に実行する
def teardown(self):
print(__name__, ":teardown")
pass
setup をsetUp 、teardown を tearDown にしたら、call されるようになりました。
継承すると微妙に処理が変わるのかもしれません。
しないとどちらの記述方でも呼ばれる。。 PEP8 としては、setup、`teardown が正しいっぽいので、
なるべく継承しないようにした方がいいのかな? とか思いました。
※まあ、、どっちでも良いですが。
以上です。
コメント