vendredi 19 février 2021

Flask Test Views and models: manage app and db session

I need to test some of my models and views using pytest and some fixtures; I already tested my models with a db_session fixture.

But the problem come up when I try to test the API with a fake client. How can I use: 1) The Fake Client 2) How can I manage the db.session.query, as I already have the db_session fixture?

I'm making confusion with app.test_client() and app.app_context() to try to do it. How would you test it? I'm open to a different and simple solution.

  • routes.py
from app.models import Area
from app import db

from flask import Blueprint, jsonify
from flask.views import MethodView


bp = Blueprint('main', __name__)


class AreaView(MethodView):

    def __init__(self):
        self.response = dict()

    def get(self):
        """ Get Area List """
        q_area = db.session.query(Area).all()
        for a in q_area:
            self.response[a.id] = a.name
        
        return jsonify(self.response)

bp.add_url_rule("/api/area", view_func=AreaView.as_view("area_api"))
  • conftest.py
import pytest

from sqlalchemy import create_engine
from sqlalchemy.orm import Session

from app.models import Area


@pytest.fixture(scope="session")
def engine():
    return create_engine("postgresql://test:test@localhost:5432/sftest")


@pytest.fixture(scope="session")
def tables(engine):
    Area.metadata.create_all(engine)
    yield
    Area.metadata.drop_all(engine)


@pytest.fixture
def db_session(engine, tables):
    """Returns an sqlalchemy session, and after the test tears down everything properly."""
    connection = engine.connect()
    # begin the nested transaction
    transaction = connection.begin()
    # use the connection with the already started transaction
    session = Session(bind=connection)

    yield session

    session.close()
    # roll back the broader transaction
    transaction.rollback()
    # put back the connection to the connection pool
    connection.close()


@pytest.fixture
def area():
    area_data = {
        'id': '1',
        'name': 'test_area',
    }

    area = Area(**area_data)
    return area

  • Example of a test of my models
from app.models import Area


class TestModels:
    def test_create(self, db_session, area):
        db_session.add(area)

        q_area = db_session.query(Area).get(1)

        assert q_area
  • What I need
class TestAreaView:

    def test_get(self):
        # see if the response is as I expected
        pass
    def test_post(self):
        pass

Aucun commentaire:

Enregistrer un commentaire