ajrlewis
ajrlewis

Reputation: 3058

Flask-testing database not saving on commit

I have the following flask factory directory setup:

server/
    __init__.py
    .env
    wsgi.py
    app/
        __init__.py
        config/
            __init__.py
            config.py
            test_config.py
        models/
            __init__.py
            sku.py
        views/
            __init__.py
            sku_bp.py
    tests/
        __init__.py
        test_sku_view.py

The create_app method is defined in server/app/__init__.py:

from flask import Flask
from flask_sqlalchemy import SQLAlchemy

db = SQLAlchemy()

def create_app(config):
    app = Flask(__name__, instance_relative_config=False)
    app.config.from_object(config)
    db.init_app(app)
    with app.app_context()
        from app.views.sku_bp import sku_bp
        app.register_blueprint(sku_bp, url_prefix='/api/sku/')
        return app

And the model (server/app/models/sku.py) and blueprint (server/app/views/sku_bp.py) are given by:

from app import db

class SKU(db.Model):
    __tablename__ = 'sku'
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String, nullable=False)
    def to_dict(self):
        return {'id': self.id, 'name': self.name}

and

from flask import Blueprint, jsonify
from app.models.sku import SKU

sku_bp = Blueprint('sku_bp', __name__)

@sku_bp.route('/get/')
@sku_bp.route('/get/<string:sku_name>')
def get(sku_name: str):
    try:
        sku = SKU.query.filter_by(name=sku_name).first()
    except Exception as e:
        return jsonify({'Error': f'{e}'}), 404
    else:
        return jsonify(sku.to_dict()), 200

respectively.

I am trying to the compute unit tests in server/tests/test_sku_view.py as follows:

import unittest
import sys
sys.path.append('./')
from flask_testing import TestCase
import pandas as pd
from app.models.sku import SKU
from app.config.test_config import TestConfig
from app import create_app, db

class TestSKUView(TestConfig, TestCase):

    def create_app(self):
        return create_app(TestConfig)

    def setUp(self):
        db.create_all()
        df_sku = pd.read_csv('tests/io/test.sku.csv')
        for index, row in df_sku.iterrows():
            sku = SKU(**row)
        db.session.commit()

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

    def test_sku_view(self):
        skus = SKU.query.all()
        print(f'skus = {skus}')

def main():
    unittest.main()

if __name__ == '__main__':
    main()

where the server/tests/io/test.sku.csv file looks like this:

id,name
1,'A'
2,'B'

and the server/app/config/test_config.py file looks like this:

class TestConfig():
    DEBUG = True
    TESTING = True
    SQLALCHEMY_TRACK_MODIFICATIONS = False
    SQLALCHEMY_ECHO = True
    SQLALCHEMY_DATABASE_URI = 'sqlite:////tmp/test.db'

I call this script from within the server/ directory using python3.7 tests/test_sku_view.py. However, when I print the skus list which queries the database, nothing is returned, i.e. skus = []. Where am I going wrong here, please? I know the sku is being generated properly but it seems not to save in the database on commit ...

Upvotes: 1

Views: 497

Answers (1)

J&#252;rgen Gmach
J&#252;rgen Gmach

Reputation: 6121

You need to add a db.session.add(sku) before the commit, obviously in the for loop :-)

Upvotes: 1

Related Questions