Flask test_client不在unittest.TestCase的setUp()处重新启动

Ada*_*tan 3 unit-testing nose flask

我正在用flask写一个小的REST服务:

from flask import Flask
app = Flask(__name__)

app.config['count']=0

@app.route("/count")
def get_count():
    app.config['count']+=1
    return str(app.config['count']-1)

@app.route("/reset")
def reset():
    app.config['count']=0
    return str(app.config['count'])

if __name__ == "__main__":
    app.run(debug = True)
Run Code Online (Sandbox Code Playgroud)

顺序调用/count应该返回0, 1, 2, ...。呼叫/reset应重置计数器。

为了对其进行测试,我遵循了烧瓶和鼻子教程 ::

#!/usr/bin/python

import flask_server as server
import unittest
from nose.tools import assert_equals

class TestUnitBase(unittest.TestCase):

    def setUp(self):
        print "Setting up!"
        server.app.testing=True
        self.app = server.app.test_client()

    def test_count_is_zero_in_new_server(self):
        """/count should return 0 for a new server"""
        response       = self.app.get("/count")
        data, status   = response.data, response.status
        assert_equals(int(data), 0)
        print data, status

    def test_count_is_zero_in_new_server_again(self):
        """Asserts that the uptime response contains "boot" and "test" elements."""
        response       = self.app.get("/count")
        data, status   = response.data, response.status
        assert_equals(int(data), 0)
        print data, status

if __name__ == '__main__':
    import nose
    nose.run(argv=[__file__, '--with-doctest', '-v', '-s'])
Run Code Online (Sandbox Code Playgroud)

这些方法是相同的,我希望它们都能通过,但是:

 $ nosetests -vs location_update_server/server/test_flask_server.py
/count should return 0 for a new server ... Setting up!
0 200 OK
ok
Asserts that the uptime response contains "boot" and "test" elements. ... Setting up!
FAIL

======================================================================
FAIL: Asserts that the uptime response contains "boot" and "test" elements.
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/home/adam/vioozer/servers/location_update_server/server/test_flask_server.py", line 28, in test_count_is_zero_in_new_server_again
    assert_equals(int(data), 0)
AssertionError: 1 != 0

----------------------------------------------------------------------
Ran 2 tests in 0.025s

FAILED (failures=1)
Run Code Online (Sandbox Code Playgroud)

setUp方法的确调用了两次,但是服务器仅创建了一次。如何设置测试,以便每次调用都setUp()可以启动一个新服务器counter=0

Mig*_*uel 6

您需要为每个测试创建一个新的应用程序,以便每个测试开始将请求发送到全新的服务器。“应用程序”是指class的实例Flask

不幸的是,这是一个不平凡的变化。在官方文档:应用程序工厂中解释了基础知识。

按照参考页中的说明进行操作后,您将不再打电话

app = Flask(__name__)
Run Code Online (Sandbox Code Playgroud)

在全局范围内,您将拥有一个create_app()返回该app对象的函数。然后每个测试都可以自己进行。您发送到全新app对象的任何请求都将是第一个。

切换到应用程序工厂的棘手部分是,一旦将app创建的内容移至函数中,就不app.route()能再使用它来定义路由,因为app不再在全局范围内定义路由。解决方案是使用在运行时附加到应用程序的蓝图。

附带说明一下,调用测试客户端的标准做法self.app如下:

self.app = server.app.test_client()
Run Code Online (Sandbox Code Playgroud)

非常令人困惑。现在您有两app件事。我更喜欢称其为客户端,因为它就是这样:

self.client = server.app.test_client()
Run Code Online (Sandbox Code Playgroud)

最后,请注意,由于依赖于调用顺序,您的REST API并不是真正的RESTful,这种不确定的行为实际上是造成您的问题的原因。您的/count路线并不真正代表一种资源,它代表一种行动。GET请求应该是只读的,对资源的更改通常应随PUT请求一起发出。