测试基于第三方服务的功能

时间:2019-03-20 13:42:13

标签: python unit-testing web-services testing

我正试图弄清楚如何为一个函数创建单元测试,该行为基于第三方服务。

假设这样的函数:

def sync_check():
    delta_secs = 90
    now = datetime.datetime.now().utcnow()
    res = requests.get('<url>')
    alert = SlackAlert()
    last_value = res[-1]['date'] # Last element of the array is the most recent
    secs = (now - last_value).seconds

    if secs >= delta_secs:
        alert.notify("out of sync. Delay: {} seconds".format(secs))
    else:
        alert.notify('in sync')

为此功能编写单元测试的最佳实践是什么?我需要测试if和else分支,但这取决于第三方服务。

我想到的第一件事是创建一个假的Web服务器并指向该服务器(更改url),但是这样,代码库将包含测试逻辑,例如:

if test:
    url = <mock_web_server_url>
else:
    url = <third_party_service_url>

此外,单元测试将触发闲置警报,这不必发生。

所以我应该再次更改代码库,例如:

if secs >= delta_secs:
    if test:
        logging.debug("out of sync alert sent - testing mode")
    else:
        alert.notify("out of sync. Delay: {} seconds".format(secs))
else:
    if test:
        logging.debug("in sync alert sent - testing mode")
    else:
        alert.notify('in sync')

我不太喜欢。

我是否缺少解决此问题的设计?

1 个答案:

答案 0 :(得分:0)

签出来测试依赖于第三方服务的代码,而不必像示例中那样检查您是否以测试模式运行。基本思想是使松弛警报服务成为函数的参数,因此对于单元测试,您可以使用伪造的服务,该伪造的服务以您希望的方式执行每次测试。

您的代码最终看起来像这样:

def sync_check(alert):
    delta_secs = 90
    now = datetime.datetime.now().utcnow()
    res = requests.get('<url>')
    last_value = res[-1]['date'] # Last element of the array is the most recent
    secs = (now - last_value).seconds

    if secs >= delta_secs:
        alert.notify("out of sync. Delay: {} seconds".format(secs))
    else:
        alert.notify('in sync')

在一个测试用例中,您可以将警报对象简化为:

class TestAlert:
    def __init__(self):
        self.message = None

    def notify(self, message):
        self.message = message

然后可以通过传递TestAlert类的实例来测试函数,并通过访问message属性来检查记录的输出(如果需要)。此代码将无法访问任何第三方服务。

def test_sync_check():
    alert = TestAlert()
    sync_check(alert)
    assert alert.message == 'in sync'