我用的是烧瓶试验,它说:
另一个问题是,Flask也会在每个请求的末尾删除会话实例(与使用SQLAlchemy和scoped_session的任何线程安全应用程序一样)。因此,每次调用client.get()或其他客户端方法时,会话以及添加到它的任何对象都会被清除。
不过,我看不出来。此测试失败:
from flask import Flask
from flask.ext.sqlalchemy import SQLAlchemy
from flask.ext.testing import TestCase
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:////tmp/test.db'
db = SQLAlchemy(app)
@app.route('/')
def index():
print 'before request:', `db.session`
u = db.session.query(User).first()
u.name = 'bob'
return ''
class User(db.Model):
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String)
class SessionTest(TestCase):
def create_app(self):
return app
def test_remove(self):
db.drop_all()
db.create_all()
u = User()
u.name = 'joe'
db.session.add(u)
db.session.commit()
client = app.test_client()
client.get('/')
print 'after request:', `db.session`
print u.name
assert u not in db.session(与$ nosetests test_file.py一起运行以查看它的运行情况。)
标准:
-------------------- >> begin captured stdout << ---------------------
before request: <sqlalchemy.orm.scoping.ScopedSession object at 0x10224c610>
after request: <sqlalchemy.orm.scoping.ScopedSession object at 0x10224c610>
bob
--------------------- >> end captured stdout << ----------------------根据文档,用户u不应该在get请求之后出现在会话中,但是它是!有人知道为什么会这样吗?
此外,u.name是bob而不是joe,即使请求从未提交!(所以我确信这是同一次会议。)
为了记录在案,
$ pip freeze | grep Flask
Flask==0.10.1
Flask-Bcrypt==0.5.2
Flask-DebugToolbar==0.8.0
Flask-Failsafe==0.1
Flask-SQLAlchemy==0.16
Flask-Script==0.6.2
Flask-Testing==0.4
Flask-Uploads==0.1.3
Flask-WTF==0.8发布于 2013-10-20 02:10:29
我非常肯定,混淆来自于SQLAlchemy中的会话是限定作用域的事实,这意味着每个请求处理程序都创建和销毁自己的会话。
这是必要的,因为web服务器可以是多线程的,因此可以同时处理多个请求,每个请求处理不同的数据库会话。
因此,在请求上下文之外使用的会话可能与处理'/'路由的视图函数在结束时得到并销毁的会话不同。
更新:我仔细研究了一下,发现了这件事。
烧瓶-SQLAlchemy在app.teardown_appcontext上安装一个钩子,这里是它调用db.session.remove()的地方。
测试环境不能完全复制实际请求的环境,因为它不会推送/弹出应用程序上下文。因此,会话从未在请求结束时被移除。
另外,请记住,在调用before_request和after_request时,也不会调用在client.get()中注册的函数。
您可以通过对测试的小更改来强制应用程序上下文推送和弹出:
def test_remove(self):
db.drop_all()
db.create_all()
u = User()
u.name = 'joe'
db.session.add(u)
db.session.commit()
with app.app_context():
client = app.test_client()
client.get('/')
print 'after request:', `db.session`
print u.name
assert u not in db.session通过这一更改,测试通过了。
用于瓶测试的文档似乎是错误的,或者更可能是过时的。也许事情在某种程度上像他们所描述的那样起作用了,但对于当前的水瓶和瓶-SQLAlchemy版本来说,这是不准确的。
我希望这能帮到你!
发布于 2013-10-18 08:52:59
FlaskClient处理请求上下文,而Flask调用它是shutdown_session在app.teardown_appcontext上,因为Flask 0.9。这就是为什么在测试客户端调用之后什么都不会发生,因为flask.ext.testing.TestCase在测试的setUp之前就已经启动了应用程序上下文,并且在tearDown之后就会关闭。
发布于 2016-01-06 07:12:54
当我尝试使用烧瓶时,我也遇到了同样的问题--设法运行我的测试。在单独的线程中运行测试解决了这个问题。
import threading
# some code omited
runner = unittest.TextTestRunner(verbosity=2)
t = threading.Thread(target=runner.run, args=[test_suite])
t.start()
t.join()
# other code omitedhttps://stackoverflow.com/questions/19395697
复制相似问题