0

I just got into testing my flask application with pytest, and it mostly works as expected. Unfortunately the test uses the live DB instead a mock one. I'm quite sure this has to do with the fact, that flask-security is using peewee's database_wrapper instead of an "straightforward" database.

Here's some code. This is from the test:

@pytest.fixture
def client():
db_fd, belavoco_server.app.config['DATABASE']  = {  'name': 'userLogin_TEST.db',
                                                    'engine': 'peewee.SqliteDatabase' }                                                   }

belavoco_server.app.config['TESTING'] = True
client = belavoco_server.app.test_client()

#this seems not to help at all
with belavoco_server.app.app_context():
     belavoco_server.users.user_managment.db_wrapper.init_app(belavoco_server.app)

yield client

os.close(db_fd)
os.unlink(belavoco_server.app.config['DATABASE'])

This is some code from my bv_user_model.py

app.config['DATABASE'] = {
    'name': 'userLogin.db',
    'engine': 'peewee.SqliteDatabase',
}

app.config['SECURITY_URL_PREFIX'] = "/users"

# Create a database instance that will manage the connection and
# execute queries
db_wrapper = FlaskDB(app)

class Role(db_wrapper.Model, RoleMixin):
    name = CharField(unique=True, default="standard")
    description = TextField(null=True)

    def __repr__(self):
        return self.name

When preforming the test, Flask is using the userLogin.db instead of userLogin_TEST.db. I suppose this is because of the db_wrapper in bv_user_model.py - but I did not find a way to change this behaviour. Any help would be greatly appreciated!

leosok
  • 302
  • 1
  • 5
  • 15
  • Your example is not reproducible and that may be the reason why this question has not received enough attention. The fixture appears to be malformatted (no indent). And what is `belavoco_server`? Also, may I ask what is the purpose of unpacking the dictionary keys into `db_fd and belavoco_server.app.config['DATABASE']`? It does not make any sense to me as `db_df` would be a string, not a file descriptor. – krassowski May 18 '19 at 08:58
  • You are right, the question was not well asked, but I really got lost with this problem, because the code itself worked and I am new to tests. `belavoco_server` is the name of the whole project, the app is created therein. You're right, the unpacking makes no sense, it comes from the code before, which was creating a temporary file with `tempfile.mkstemp()` which returns a pair. – leosok May 21 '19 at 00:16
  • I did find a solution after all, using the same BaseModel and initializing the database with a temporary file as I did for other tests. Because the example of flask-security used a database wrapper I thought I had to use FlaskDB. Without it, everything works fine. – leosok May 21 '19 at 00:16

1 Answers1

1

The root of the issue seems to be this in bv_user_model:

app.config['DATABASE'] = {
    'name': 'userLogin.db',
    'engine': 'peewee.SqliteDatabase',
}

Since you are using FlaskDB with the app that has the production credentials, it seems like the db_wrapper will "remember" that and not be overridden by your tests.

The most straightforward answer would be to not use your app to create the FlaskDB instance directly

db = FlaskDB()

And then later on initialize it on your app

from models import db
def create_app():
    app = ...
    app.config["DATABASE"] = ...
    db.init_app(app)
    ...
    return app

Which would let you have a separate function like this which you can use for testing.

def create_test_app():
    app = ...
    app.config["DATABASE"] = ...test credentials...
    db.init_app(app)
    ...
    return app

and when you create your models, use the FlaskDB instance just the same as you were already.

db = FlaskDB()
class Role(db.Model, RoleMixin):
    ...
Ethan McCue
  • 883
  • 1
  • 8
  • 17
  • Thank you, you nailed the problem. I found a solution myself, in the meantime, by ditching FlaskDB and returning to a BaseModel and initiation with `database.init(database_name)` if `not app.config['TESTING']`. This is what worked for all the other tests, but (as I'm explaining in a comment above) I was thinking I had to use a db_wrapper to use flask-security. – leosok May 21 '19 at 00:25
  • I have never opend and closed connections manually with peewee and Flask. Apparently FlaskDB does this for you. I have used Flask an peewee for a while and never had any problem with not closing connections, I was always assuming they were closed automatically. When using the Models obviously a connection is opend. Should I use a hook to close it when a request ends? – leosok May 21 '19 at 00:34