Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to Completely Teardown Flask App After Each Test in pytest?

I am testing my Flask app using Pytest. I have 3 files

tests/
--conftest.py
--test_one.py
--test_two.py

If I run test_one.py or test_two.py using the following command, it will work without issue.

python -m pytest tests/test_one.py

The issue arises when I try to run all tests with the following command:

python -m pytest tests

I get this error:

AssertionError: View function mapping is overwriting an existing endpoint function: serve_static

Im not actually surprised by this error since init_app(app) gets called twice (once per file) and I don't ever teardown the actual app.

My question is, Is there a way to completely teardown a flask app and rebuild it for each individual test? I am looking for the actual commands to do the tearing down (i.e. app.teardown())

Edit: I am open to alternative ways of setting up a Flask app testing environment, if it would solve this problem (without creating new ones).

Edit 2: I found this question. It is similar and would solve my problem but it involves importing inside a function. I suspect there has to be a better way.

conftest.py

import os
import pytest

from app import app, init_app
from config import TestConfig


@pytest.fixture(scope='function')
def client():

    app.config.from_object(TestConfig)

    with app.test_client() as client:
        with app.app_context():
            init_app(app)
        yield client

    try:
        os.remove('tests/testing.db')
    except FileNotFoundError:
        pass

app/__init__.py

app = Flask(__name__)
app.url_map._rules.clear()
db = SQLAlchemy(app)
migrate = Migrate(app, db)

def init_app(app):
    ...
like image 696
noslenkwah Avatar asked Oct 25 '25 13:10

noslenkwah


1 Answers

I would create a Class in each of your files which inherits TestCase. This way you can use the function setup() to generate your testclient as a Instance-Variable before each test. This way you can be sure that each test has the same environment to work with.

from unittest import TestCase
from app import app as application

class TestApplication(TestCase):
  def setUp(self):
    self.client = application.app.test_client()

  def test_sth(self):
    r = self.client.get('/approute2sth')
    self.assertEqual(r.status_code, 200)

  def test_sth_else(self):
    r = self.client.get('/approute2sth_else')
    self.assertEqual(r.status_code, 200)
like image 58
jan-seins Avatar answered Oct 28 '25 03:10

jan-seins



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!