python - 在 Django 自定义管理命令中测试输入消息文本和答案

标签 python django unit-testing

我想在自定义管理命令中测试用户输入确认答案。该测试针对向用户显示的消息以及她输入的答案。

命令的代码是:

class Command(BaseCommand):

    def add_arguments(self, parser):
        parser.add_argument('id', type=int)

    def handle(self, *args, **options):
        try:
            experiment = Experiment.objects.get(pk=options['id'])
        except Experiment.DoesNotExist:
            raise CommandError(
                'Experiment with id "%d" does not exist' % (options['id'])
            )

        answer = input('Are you sure? (Y/n)')
        if answer == 'Y':
            experiment.delete()

这个accepted answer建议使用 mock ,但这是在孤独的背景下。我想测试用户输入以及可以添加到自定义命令中的其他内容。

什么是有效的方法?

最佳答案

搜索多个来源后,我找不到与我的问题类似的解决方案。因此,我混合了其中一些,使用 python mock 库得到了一个简洁的解决方案。

测试方法(在test_commands.py中):

from unittest.mock import patch
# other imports

@patch('experiments.management.commands.remove_experiment.get_input',
           return_value='Y')
    def test_remove_experiment_displays_prompt_and_user_confirm_removing(
            self, mock_user_input
    ):
        experiment = create_experiment()
        out = StringIO()
        call_command(
            'remove_experiment', experiment.id, stdout=out
        )

        self.assertEqual(mock_user_input.called, True)
        (text,), kwargs = mock_user_input.call_args
        self.assertEqual(text,
            'All versions of experiment "%s" will be destroyed and cannot be '
            'recovered. Are you sure? (Yes/n) ' % experiment.title)
        self.assertFalse(Experiment.objects.exists())

现在,在命令类中,我们将 python input() 包装在我们的方法中(就像问题中提到的 accepted answer 中所做的那样)。

my_app.management.commands.remove_experiment:

def get_input(text):
    return input(text)

class Command(BaseCommand):

    def add_arguments(self, parser):
        parser.add_argument('id', type=int)

    def handle(self, *args, **options):
        try:
            experiment = Experiment.objects.get(pk=options['id'])
        except Experiment.DoesNotExist:
            raise CommandError(
                'Experiment with id "%d" does not exist' % (options['id'])
            )

        answer = get_input('Are you sure? (Y/n)')
        if answer == 'Y':
            experiment.delete()

现在,测试将验证问题文本,在用户输入提示中是否正确,但不会将其显示在 stdout 中。此外,@patch上下文装饰器中的kwarg return_value='Y'将模拟用户答案,并且测试通过。

关于python - 在 Django 自定义管理命令中测试输入消息文本和答案,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48210488/

相关文章:

python - 将 request.user 与 Django ModelForm 一起使用

python - numpy 多维数组的条件运算

python - 查看移动浏览器时,Ipython/Jupyter Notebook HTML 未对齐

python - 我可以像 shell 命令一样调用不带括号的 Python 函数吗?如果是这样,如何?

java - 如何在java中测试本地内部类方法?

基于 Django 类的通用 View 和 ModelForms

python - Google Web Toolkit 类似于 Django 中的应用程序

django - Django 模型的测试样板 : seeking a portable, 单文件解决方案

c# - 如果我在测试时在 System.Web.UI.Util 处遇到异常,如何对我的 HtmlHelper 扩展方法进行单元测试?

python - 为不同的响应模拟 urllib2.urlopen().read()