【问题标题】:Is it possible to run unit tests on code that uses subprocess?是否可以对使用子进程的代码运行单元测试?
【发布时间】:2020-02-21 05:48:44
【问题描述】:

我的 Django 应用程序有一些管理命令,它们使用 subprocess.Popen(['manage.py', '<command>', ...) 启动其他管理命令。它们保持这样主要是为了并行运行进程并防止一个命令干扰另一个命令。

但是,在编写单元测试时,这些新流程不使用测试环境和数据库,因此会失败。

现在,我添加了一个运行 call_command() 而不是 Popen() 的设置(见下文):

        if settings.TESTING:
            self.returncode = call_command(self.command, *params)
        else:
            self.process = subprocess.Popen(['python', 'manage.py', self.command] + params)

            # ... later on:
            self.process.wait()
            self.returncode = self.process.returncode

但是,子进程调用和等待所涉及的逻辑仍未测试。是否可以在单元测试中测试子进程调用?

注意:测试数据库不是内存中的 SQLite - 我知道那是行不通的。这是一个实际的数据库,每次运行都会创建和销毁。

【问题讨论】:

  • 听起来代码命中的数据库应该由环境变量控制。当您开始测试并启动测试数据库时,您还可以设置环境变量。
  • 如果您将其视为单元测试,请模拟您的命令调用以返回数据或确保命令调用者正常工作所需的任何内容 - 1 个单元。然后编写另一个测试来仅测试命令 - 另一个单元。
  • @ToanQuocHo 这实际上很有意义。如果你把它变成一个答案,我会接受它。

标签: python django unit-testing


【解决方案1】:

如果您将其视为单元测试,那么您可以模拟您的命令调用以返回模拟数据,以确保命令调用者正常工作。

对于命令代码的覆盖率,您还可以使用 Django 提供的call_command 方法仅针对该命令编写另一个单元测试。

像这样:

class TestYourCommandCaller(TestCase):
    ...

    @mock.patch('subprocess.Popen')
    def test_your_business_which_call_the_command(self, mock_process):
        # Mock your process

        call_your_function_which_create_processes()

        # Assert your process have been called

另一个测试你的命令也覆盖命令代码:

class TestYourCommand(TestCase):
    def test_command_call(self):
        call_command('command_name', *params)

        # Assert the result

【讨论】:

    猜你喜欢
    • 2012-07-23
    • 1970-01-01
    • 2016-02-06
    • 2017-09-27
    • 1970-01-01
    • 2019-08-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多