【问题标题】:Python 3 how to write unit tests for try except outside functions in modulesPython 3如何为try编写单元测试,模块中的外部函数除外
【发布时间】:2020-04-15 11:18:35
【问题描述】:

我想知道如何为try exceptblocks 编写 Python 3 单元测试 在 Python 模块中的函数定义之外定义的。

想象一下,在package/module.py 我有一段代码,例如:

导入操作系统

try:
  CONSTANT = os.environ['NOT_EXISTING_KEY']
except KeyError:
  CONSTANT = False
finally:
  del os

(请不要介意实际代码,我知道在这种特定情况下我可以使用os.getenv('NOT_EXISTING_KEY', False),我感兴趣的是真正测试模块中的try-except块(函数之外)行为符合预期。

如何编写单元测试来检查 package.module.CONSTANT 是否设置为预期值?

在 unittest 文件中(我使用 pytest)我有类似的东西:

from package.module import CONSTANT

def test_constant_true():
  assert CONSTANT == 'expected_value'

测试如果 try 块正确执行,那么 CONSTANT 是否符合预期。

但是,我不知道如何模拟导入机制,以便 try 块中的 os.environ 引发异常,我可以测试 CONSTANT 是否设置为 False。

我该怎么做?

【问题讨论】:

  • 你试过monkeypatch.setenv()吗?
  • 使用mock 或自定义monkeypatch。

标签: python unit-testing pytest python-module python-unittest.mock


【解决方案1】:

您可以使用monkeypatch设置环境变量,但您必须重新加载模块才能使更改生效:

from importlib import reload

from package import module


def test_constant_true(monkeypatch):
    monkeypatch.setenv('MY_KEY', '42')
    reload(module)
    assert module.CONSTANT == '42'


def test_constant_false():
    reload(module)
    assert not module.CONSTANT

鉴于package/module.py的这个内容:

import os

try:
    CONSTANT = os.environ['MY_KEY']
except KeyError:
    CONSTANT = False

【讨论】:

  • 我认为可以通过使用引发所需错误的模拟来改进答案,以测试是否正确捕获了异常,但“重新加载”功能是我解决问题所需的关键,非常感谢!
  • 我认为异常是不需要测试的实现细节——相关部分是设置变量——但这当然是基于意见的。很高兴我能帮上忙!
【解决方案2】:

您可以使用mock.patch.dict 模拟环境并将值导入您的单元测试方法中。像这样:

from unittest import TestCase, mock

class YourTest(TestCase):
    @mock.patch.dict('os.environ', {'NOT_EXISTING_KEY': 'value'})
    def test_constant_key_defined(self, mocked):
        """ Tests when the key is defined """
        from package.module import CONSTANT
        self.assertEqual(CONSTANT, 'value')

    def test_constant_key_not_defined(self):
        """ Tests when the key is not defined """
        from package.module import CONSTANT
        self.assertEqual(CONSTANT, 'value')

您可以使用importlib.reload,就像@mrbean-bremen 的答案,我不熟悉。

【讨论】:

  • 这不会让我碰巧测试引发错误时会发生什么
  • 如果您想测试何时引发错误,只需删除模拟。只需创建另一个没有模拟的方法并做同样的事情。我会更新答案。
猜你喜欢
  • 1970-01-01
  • 2020-10-27
  • 1970-01-01
  • 2020-10-13
  • 1970-01-01
  • 2020-01-18
  • 2013-08-12
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多