如何使用直接或间接“导入greengrasssdk”的文件编写单元测试

时间:2019-01-21 05:49:12

标签: python-2.7 unit-testing mocking greengrass

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

我正在使用PyCharm执行测试。我尝试测试的Greengrass lambda由于相同的依存关系问题(相同的异常)未在本地执行。但是,只要将lambda推入草丛中,它就可以正常工作。

这里是例外:

    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开发人员交谈。我们没有真正找到解决方案。 (除了尝试在生产代码中捕获导入),但这似乎是整个项目中不良软件质量的第一步。

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

非常感谢:)。

3 个答案:

答案 0 :(得分:0)

如果检测到您正在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')

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

答案 1 :(得分:0)

也存在此问题,并使用我的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上创建一个立面,然后可以在其上模拟方法。在这种情况下,facade必须导入greengrasssdk,这是上面的代码将阻止测试失败的地方。

总结:

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

  2. 在外观中导入greengrasssdk

  3. 使用conftest.py文件中的修补程序代码(如上所述)通过Greengrass SDK进行修补。

希望有帮助。

答案 2 :(得分:0)

我只是遇到了同样的问题,对我来说,它通过使用tryexcept语句将导入包围起来。

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