编写测试用例

简单地继承 TestCase 的 MyTest:

  1. from flask.ext.testing import TestCase
  2. class MyTest(TestCase):
  3. pass

你必须定义 create_app 方法,该方法返回一个 Flask 实例:

  1. from flask import Flask
  2. from flask.ext.testing import TestCase
  3. class MyTest(TestCase):
  4. def create_app(self):
  5. app = Flask(__name__)
  6. app.config['TESTING'] = True
  7. return app

如果不定义 create_appNotImplementedError 异常将会抛出。

使用 LiveServer 测试

如果你想要你的测试通过 Selenium 或者 无头浏览器(无头浏览器的意思就是无外设的意思,可以在命令行下运行的浏览器)运行,你可以使用 LiveServerTestCase:

  1. import urllib2
  2. from flask import Flask
  3. from flask.ext.testing import LiveServerTestCase
  4. class MyTest(LiveServerTestCase):
  5. def create_app(self):
  6. app = Flask(__name__)
  7. app.config['TESTING'] = True
  8. # Default port is 5000
  9. app.config['LIVESERVER_PORT'] = 8943
  10. return app
  11. def test_server_is_up_and_running(self):
  12. response = urllib2.urlopen(self.get_server_url())
  13. self.assertEqual(response.code, 200)

在这个例子中 get_server_url 方法将会返回 http://localhost:8943

测试 JSON 响应

如果你正在测试一个返回 JSON 的视图函数的话,你可以使用 Response 对象的特殊的属性 json 来测试输出:

  1. @app.route("/ajax/")
  2. def some_json():
  3. return jsonify(success=True)
  4. class TestViews(TestCase):
  5. def test_some_json(self):
  6. response = self.client.get("/ajax/")
  7. self.assertEquals(response.json, dict(success=True))

选择不渲染模板

当测试需要处理模板渲染的时候可能是一个大问题。如果在测试中你不想要渲染模板的话可以设置 render_templates 属性:

  1. class TestNotRenderTemplates(TestCase):
  2. render_templates = False
  3. def test_assert_not_process_the_template(self):
  4. response = self.client.get("/template/")
  5. assert "" == response.data

尽管可以设置不想渲染模板,但是渲染模板的信号在任何时候都会发送,你也可以使用 assert_template_used 方法来检查模板是否被渲染:

  1. class TestNotRenderTemplates(TestCase):
  2. render_templates = False
  3. def test_assert_mytemplate_used(self):
  4. response = self.client.get("/template/")
  5. self.assert_template_used('mytemplate.html')

当渲染模板被关闭的时候,测试执行起来会更加的快速并且视图函数的逻辑将会孤立地被测试。

使用 Twill

Twill 是一个用来通过使用命令行界面浏览网页的简单的语言。

Note

请注意 Twill 只支持 Python 2.x,不能在 Python 3 或者以上版本上使用。

Flask-Testing 拥有一个辅助类用来创建使用 Twill 的功能测试用例:

  1. def test_something_with_twill(self):
  2. with Twill(self.app, port=3000) as t:
  3. t.browser.go(t.url("/"))

旧的 TwillTestCase 类已经被弃用。

测试 SQLAlchemy

这部分将会涉及使用 Flask-Testing 测试 SQLAlchemy 的一部分内容。这里假设你使用的是 Flask-SQLAlchemy 扩展,并且这里的例子也不是太难,可以适用于用户自己的配置。

首先,先确保数据库的 URI 是设置成开发环境而不是生产环境!其次,一个好的测试习惯就是在每一次测试执行的时候先创建表,在结束的时候删除表,这样保证干净的测试环境:

  1. from flask.ext.testing import TestCase
  2. from myapp import create_app, db
  3. class MyTest(TestCase):
  4. SQLALCHEMY_DATABASE_URI = "sqlite://"
  5. TESTING = True
  6. def create_app(self):
  7. # pass in test configuration
  8. return create_app(self)
  9. def setUp(self):
  10. db.create_all()
  11. def tearDown(self):
  12. db.session.remove()
  13. db.drop_all()

同样需要注意地是每一个新的 SQLAlchemy 会话在测试用例运行的时候就被创建, db.session.remove() 在每一个测试用例的结尾被调用(这是为了确保 SQLAlchemy 会话及时被删除) - 这是一种常见的 “陷阱”。

另外一个 “陷阱” 就是 Flask-SQLAlchemy 会在每一个请求结束的时候删除 SQLAlchemy 会话(session)。因此每次调用 client.get() 或者其它客户端方法的后,SQLAlchemy 会话(session)连同添加到它的任何对象都会被删除。

例如:

  1. class SomeTest(MyTest):
  2. def test_something(self):
  3. user = User()
  4. db.session.add(user)
  5. db.session.commit()
  6. # this works
  7. assert user in db.session
  8. response = self.client.get("/")
  9. # this raises an AssertionError
  10. assert user in db.session

你现在必须重新添加 “user” 实例回 SQLAlchemy 会话(session)使用 db.session.add(user),如果你想要在数据库上做进一步的操作。

同样需要注意地是在这个例子中内存数据库 SQLite 是被使用:尽管它是十分的快,但是你要是使用其它类型的数据库(例如 MySQL 或者 PostgreSQL),可能上述代码就不适用。

你也可能想要在 setUp() 里为你的数据库增加一组实例一旦你的数据库的表已经创建。如果你想要使用数据集的话,请参看 Fixture,它包含了对 SQLAlchemy 的支持。