使用pytest

时间:2019-01-05 08:59:14

标签: python flask mocking pytest

tl; dr 我正在寻找测试烧瓶应用程序的最佳实践,该烧瓶应用程序在其路由下使用外部API,也许这是我在测试阶段必须使用模拟服务器来模拟外部API的地方。


好吧,我所能找到的pytest-mock和类似的软件包是我可以模拟一个函数并为测试断言准备好结果。但不幸的是,我找不到适合自己情况的最佳实践解释:

我有一个flask应用程序,在某些路由下,我使用外部API,并且我想使用模拟服务器替换那些实际的外部API URL。我得出了两个看似公平​​的解决方案:

在测试时使用测试URL

到目前为止,我可以通过app.config动态设置不同的URL,以便可以在我的conftest.py中使用测试URL进行调用,实际上,我的应用程序将由主要网址。现在,我的问题是如何在pytest fixture设置阶段自动运行模拟服务器,以占用测试URL本地主机端口。我之所以自动说是因为我自己可以天真地在后台运行一个手动模拟应用程序,这对于自动测试而言是愚蠢且无用的

使用模拟功能,而不是将请求发送到主URL

我意识到我可以设置一个模拟程序,该函数返回我想要的值,并在调用待测试应用程序的同时使用它。但关键是我想在我的应用程序中使用模拟 ,而不是将返回值与模拟生成的值进行比较

那我在哪里,该怎么办?!

以下是示例:

我的烧瓶应用程序:

app = Flask(__name__)

@app.route('/test')
def test():
    value = request.args.get('dummy_val')

    # using external APIs
    # This is where I need mock server
    output = requests.get(
         'http://external.api/some/url',
         params={'val':value}
    )
    return output*2

我的测试文件:

def test_can_double_value(test_client):
    result = test_client('/test', query_string={'dummy_val':'foo'})
    # test if status code == 200
    # test if string equals to something
    # blah blah blah

2 个答案:

答案 0 :(得分:0)

感谢jonrsharpe,我现在知道可以使用responses库来完成此操作。现在,如果我们要在灯具中模拟API,可以按以下步骤完成:

conftest.py

import response
from pytest import fixture

@fixture
def client():
    # add response
    responses.add(responses.GET,
        'http://mock.api/v',
        json={'key': 'value'},
        status=200
    )
    # do fixture stuff -> here it is yielding app test client
    app.config['TESTING'] = True
    client = app.test_client() 

    yield client

test_module.py

import response

@response.activate
def test_can_connect(client):
    result = client.get('/test')
    assert result.status_code == 200

app.py

@app.route('/test')
def test():
    res = requests.get('http://mock.api/v')
    # blah blah
responses文档中的

评论中,建议我们在测试功能中添加一个响应。但是当我想将其添加到灯具中时,这就是我的方法。

答案 1 :(得分:0)

回答得有点晚,但我刚才偶然发现了相同的问题。 以前的答案似乎可以在实践中解决问题,但如果您从理论上考虑问题,我认为您有两种选择。

要么:

  • 在“请求”级别上模拟界面,效果很好,但是按照我之前的建议将测试代码暴露给实现细节
  • 在代码中为这些服务创建适配器,并在测试代码中将其替换为模拟/存根。
  • 使用测试装置,您可以使用以下摘要中的代码来启动自己的网络服务器以进行该过程: https://gist.github.com/eruvanos/f6f62edb368a20aaa880e12976620db8

最后一种方法的好处非常简单。您可以在测试时按原样保留代码,而无需进行存根/模拟,并在系统外创建模拟,您可以在其中自由控制模拟,而不必担心实际的实现(就像以前一样,您必须知道该服务是通过请求调用的。)