使用单元测试驱动开发的方式编写flask应用

  flask是个轻量级的python框架,特别适合写一个没有UI的web接口应用,并且提供了很友好的测试框架,参考链接http://flask.pocoo.org/docs/testing/,官方提供的测试范例实际上算是集成测试了,如果不想让测试依赖外部环境(比如数据库)怎么办呢?Mock!,推荐使用mockito-python,Mockito的Java版本就非常好用,python也同样给力,下载地址 http://code.google.com/p/mockito-python/ 。废话少说,来次TDD的体验吧。

先写个测试:

class LoginTest(unittest.TestCase):

def setUp(self):
self.db = mock()
self.app = myapp.create_app(self.db).test_client()

def tearDown(self):
unstub()

增加一个Post请求,用来进行登录。

def test_login(self):
rv = self.app.post('/login', data=dict(username='archie', password='mypassword'))

self.assertEqual(200, rv.status_code)
self.assertEqual('Login Successful!', rv.data)

当然,这个测试运行肯定会失败。

[wenwen@Archie flaskdemo]$ nosetests
E
======================================================================
ERROR: Failure: ImportError (No module named flaskdemo)
----------------------------------------------------------------------
Traceback (most recent call last):
......
File "/Users/wenwen/Documents/workspace/flaskdemo/flaskdemo_test.py", line 7, in <module>
import flaskdemo
ImportError: No module named flaskdemo

----------------------------------------------------------------------
Ran 1 test in 0.074s

FAILED (errors=1)

 先让测试通过吧,写个flaskdemo.py。

from flask.app import Flask

def create_app(db):
# application
app = Flask(__name__)
app.config.from_object(__name__)

@app.route("/login", methods=["POST"])
def login():
return "Login Successful!"

return app

  毫无悬念,测试通过了。但是我们还没写验证的逻辑呢,我们使用auth.py这个module里的verify这个方法来验证,这里不想牵扯到db访问的细节,也不想在运行测试的时候启动数据库,让Mock来吧,修改测试。

    def test_login(self):
when(flaskdemo.auth).verify(self.db, "archie", "mypassword").thenReturn(True)

rv = self.app.post('/login', data=dict(username='archie', password='mypassword'))

verify(flaskdemo.auth).verify(self.db, "archie", "mypassword")
self.assertEqual(200, rv.status_code)
self.assertEqual('Login Successful!', rv.data)

  测试失败了,写个auth.py,有个空方法就可以了,以后再实现,然后把它import到flaskdemo中,并调用。

@app.route("/login", methods=["POST"])
def login():
return "Login Successful!" if auth.verify(db, request.form.get("username"), request.form.get("password")) else "Login Failed!"

ok!测试通过了。

[wenwen@Archie flaskdemo]$ nosetests
.
----------------------------------------------------------------------
Ran 1 test in 0.103s

OK

  不需要启动数据库,甚至不需要写验证逻辑。同理,当依赖的复杂逻辑在另外的module中时,就可以通过mock来解耦,方便进行单元测试。




原文地址:https://www.cnblogs.com/archie/p/2402326.html