【问题标题】:How to write unit tests with files which directly or indirectly `import greengrasssdk`如何使用直接或间接“import greengrassdk”的文件编写单元测试
【发布时间】:2019-06-14 11:55:08
【问题描述】:

每当文件导入 import greengrasssdk 时,单元测试都会失败,因为我的本地计算机上不存在模块 greengrass_common,我无法通过 pip 安装它。

我正在使用 PyCharm 执行测试。由于相同的依赖问题(相同的异常),我尝试测试的 Greengrass lambda 不会在本地执行。但是一旦 lambda 被推送到 greengrass,它就可以正常工作了。

这是一个例外:

    import greengrasssdk
  File "C:\Python27\lib\site-packages\greengrasssdk\__init__.py", line 6, 
in <module>
    from .Lambda import StreamingBody
  File "C:\Python27\lib\site-packages\greengrasssdk\Lambda.py", line 10, in 
<module>
     from greengrass_common.function_arn_fields import FunctionArnFields
ImportError: No module named greengrass_common.function_arn_fields

一个简化的代码示例是这样的:

import greengrasssdk
import logging

greengrass_iot_client = greengrasssdk.client('iot-data')
logger = logging.getLogger('logger')

def handler(event, context):
    logger.info('Event handler invoked with event: ' + str(event))

我在测试中收到以下错误消息(测试已排除在测试文件夹中,但尚未显示其他依赖问题 - 我写这个是因为一些开发人员将他们的测试放入 python 代码文件。我听说在源代码文件之外进行测试可能会导致导入问题。尽管这种情况有所不同,因为它也发生在原始代码文件中。)

import unittest
import mock
import function

类 SimpleTest(unittest.TestCase):

# NONE OF THE THREE PATCH WORK  Not in combination nor single
@mock.patch('greengrass_common')
@mock.patch('greengrass_common.function_arn_fields')
@mock.patch('greengrasssdk')
def test_that(self):
    pass

为了简化,测试用例是空的。

我希望 greengrass_common 代码存在于 Greengrass 代码之外,以便我编写单元测试。

我来自 java 世界,但与一些 python 开发人员交谈过。我们并没有真正找到解决方案。 (除了尝试在生产代码中捕获导入),但这似乎是整个项目中软件质量差的第一步。

我非常感谢您的想法/解决方案/方法和指导。

非常感谢:)。

【问题讨论】:

    标签: python-2.7 unit-testing mocking greengrass


    【解决方案1】:

    如果您检测到您正在 Greengrass 上运行,则可以有条件地导入 greengrasssdk,如果不是,则使用 boto3。我在这里写了一个对我有用的快速测试,如下所示:

    import socket
    host = socket.gethostname()
    
    client = None
    
    # Create an IoT data client with Greengrass SDK on Greengrass, boto3 locally
    if host == 'sandbox':
      import greengrasssdk
      client = greengrasssdk.client('iot-data')
    else:
      import boto3
      client = boto3.client('iot-data')
    

    基本上检查主机名是否报告为“沙盒”,然后使用 Greengrass SDK,否则使用 boto3。

    【讨论】:

      【解决方案2】:

      也有这个问题,并使用我的 conftest.py 文件中的修补程序来修补 Greengrass SDK,例如

      conftest.py

      import pytest
      from mock import MagicMock, patch
      
      MockGreengrassSdk = MagicMock()
      
      modules = {
          "greengrasssdk": MockGreengrassSdk
      }
      patcher = patch.dict("sys.modules", modules)
      patcher.start()
      

      一旦你将MockGreengrassSdk 定义为MagicMock,你就可以模拟出你想要的任何方法。我唯一不确定的是,如果您希望每次测试从 SDK 获得不同的结果,您将如何更改每次测试的结果。

      我解决这个问题的方法是在 greengrasssdk 上创建一个外观,然后我可以在上面模拟方法。在这种情况下,外观必须导入greengrasssdk,这是上面的代码将阻止您的测试失败的地方。

      总结:

      1. 在您要使用的greengrasssdk 方法上创建一个外观。

      2. 在外观中导入greengrasssdk

      3. 使用 conftest.py 文件(如上)中的修补程序代码来修补 Greengrass SDK。

      希望对您有所帮助。

      【讨论】:

        【解决方案3】:

        我刚刚遇到了同样的问题,对我来说,它通过使用 try except 语句包围导入来工作。

        try:
            import greengrasssdk
            client = greengrasssdk.client('iot-data')
        except Exception as e:
            import boto3
            client = boto3.client('iot-data')
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2018-02-03
          • 2016-03-26
          • 2011-07-22
          • 2017-06-06
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2012-02-03
          相关资源
          最近更新 更多