Why db.session.remove() must be called?
<p>I'm following a tutorial to learn flask web developing, and here is its unit testing file:</p>

<pre><code>import unittest
from flask import current_app
from app import create_app, db

class BasicsTestCase(unittest.TestCase):
    def setUp(self):
        self.app = create_app('testing')
        self.app_context = self.app.app_context()
        self.app_context.push()
        db.create_all()

    def tearDown(self):
        db.session.remove()
        db.drop_all()
        self.app_context.pop()

    def test_foo(self):
        pass
</code></pre>

<p>Also, I've found these sentences in SQLAlchemy document:</p>

<blockquote>
  <p>Using the above flow, the process of integrating the <code>Session</code> with
  the web application has exactly two requirements:</p>
  
  <ul>
  <li><p>......</p></li>
  <li><p>Ensure that <code>scoped_session.remove()</code> is called when the web request ends, usually by integrating with the web frameworkâs event system to
  establish an âon request endâ event.</p></li>
  </ul>
</blockquote>

<p>My question is: Why do I need to call <code>db.session.remove()</code>?</p>

<p>I think as long as <code>db.session.commit()</code> is not invoked, the database won't be modified. Also, when I comment out this line, the application will still be able to pass the unit test. (In the real code, I have more reasonable test cases, rather than just <code>test_foo</code>)</p>

<p>I've consulted the documents of both Flask-SQLAlchemy and SQLAlchemy, but the former doesn't even mention <code>db.session.remove()</code>, while the latter is too abstract for me to understand.</p>

<blockquote>
  <p>Using the above flow, the process of integrating the <code>Session</code> with the web application has exactly two requirements:</p>
  
  <ul>
  <li>......</li>
  <li>Ensure that <code>scoped_session.remove()</code> is called when the web request ends, usually by integrating with the web frameworkâs event system to establish an âon request endâ event.</li>
  </ul>
</blockquote>

<p>In <strong>SQLAlchemy</strong>, above action is mentioned because sessions in web application should be <strong>scoped</strong>, meaning that each request handler creates and destroys its own session.</p>

<p>This is necessary because web servers can be multi-threaded, so multiple requests might be served at the same time, each working with a different database session.</p>

<p>This scenario is beautifully handled by <strong>Flask-SQLAlchemy</strong>, it creates a fresh or new scoped session for each request. If you dig further it you will find out <a href="https://github.com/mitsuhiko/flask-sqlalchemy/blob/master/flask_sqlalchemy/__init__.py#L819" rel="nofollow">here</a>, it also installs a hook on <code>app.teardown_appcontext</code> (for Flask >=0.9), <code>app.teardown_request</code> (for Flask 0.7-0.8), <code>app.after_request</code> (for Flask &lt;0.7) and here is where it calls <code>db.session.remove()</code>.</p>

<p>The <em>testing</em> environment does not fully replicate the environment of a real request because it does not push/pop the application context. Because of that the session is never removed at the end of the request.</p>

<p>As a side note, keep in mind that functions registered with <code>before_request</code> and <code>after_request</code> are also not called when you call <code>client.get()</code>.</p>

<p>You can force an application context automatically push and pop with a small change to your test instead of manually push in <code>setUp()</code> and pop in <code>tearDown()</code>:</p>

<pre><code>def test_foo(self):
  with app.app_context():
      client = app.test_client()
      # do testing here for your endpoints
</code></pre>

<p>with this change the test passes without manually writing <code>db.session.remove()</code>.</p>

<p>The documentation for Flask-Testing seems to be wrong or more likely outdated. Maybe things worked like they describe at some point, but that isn't accurate for current Flask and Flask-SQLAlchemy versions.</p>

<p>I hope this helps!</p>

python session flask sqlalchemy flask-sqlalchemy