データベーステーブルでバックエンド操作を行うDjango manage.pyコマンドの単体テストを作成したいのですが、コードから管理コマンドを直接呼び出すにはどうすればよいですか?
Manage.pyテストを使用して設定されたテスト環境(テストデータベース、テストダミーメール送信ボックスなど)を使用できないため、tests.pyからオペレーティングシステムのシェルでコマンドを実行したくない
そのようなことをテストする最良の方法-必要な機能をコマンド自体からスタンドアロンの関数またはクラスに抽出します。 「コマンド実行」から抽象化し、追加の要件なしでテストを作成するのに役立ちます。
しかし、何らかの理由でコマンドからロジックを分離できない場合は、次のような call_command メソッドを使用して任意のコードから呼び出すことができます。
from Django.core.management import call_command
call_command('my_command', 'foo', bar='baz')
Call_commandトリックを行うのではなく、次のようにしてタスクを実行できます。
from myapp.management.commands import my_management_task
cmd = my_management_task.Command()
opts = {} # kwargs for your command -- lets you override stuff for testing...
cmd.handle_noargs(**opts)
次のコード:
from Django.core.management import call_command
call_command('collectstatic', verbosity=3, interactive=False)
call_command('migrate', 'myapp', verbosity=3, interactive=False)
...端末に入力された次のコマンドと同じです:
$ ./manage.py collectstatic --noinput -v 3
$ ./manage.py migrate myapp --noinput -v 3
Django docs からの管理コマンドの実行を参照してください。
call_commandのDjangoドキュメント は、out
をsys.stdout
にリダイレクトする必要があることに言及していません。サンプルコードは次のようになります。
from Django.core.management import call_command
from Django.test import TestCase
from Django.utils.six import StringIO
import sys
class ClosepollTest(TestCase):
def test_command_output(self):
out = StringIO()
sys.stdout = out
call_command('closepoll', stdout=out)
self.assertIn('Expected output', out.getvalue())
ネイトの答えに基づいて、私はこれを持っています:
def make_test_wrapper_for(command_module):
def _run_cmd_with(*args):
"""Run the possibly_add_alert command with the supplied arguments"""
cmd = command_module.Command()
(opts, args) = OptionParser(option_list=cmd.option_list).parse_args(list(args))
cmd.handle(*args, **vars(opts))
return _run_cmd_with
使用法:
from myapp.management import mycommand
cmd_runner = make_test_wrapper_for(mycommand)
cmd_runner("foo", "bar")
ここでの利点は、追加のオプションとOptParseを使用した場合、これが自動的に整理されることです。それは完全ではありません-そして、まだ出力をパイプしません-しかし、テストデータベースを使用します。その後、データベースの効果をテストできます。
Micheal Foordsモックモジュールを使用し、テスト期間中にstdoutを再配線することで、このテクニックをさらに活用できることを確信しています。出力、終了条件などをテストします。