Skip to content

Postgres error "SAVEPOINT can only be used in transaction blocks" when used with live_server #17

Open
@citizen-stig

Description

@citizen-stig

I have tests, that I would like to run with live_server from pytest-flask package.

I thought it works ok, but only for single request. Full repo with working example, failing test

Here are some pieces of the code:

# models.py
class Category(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String, unique=True, nullable=False)

# view
@blog.route('/categories')
def list_categories():
    return '<br/>'.join(str(x.id) + ': ' + x.name for x in models.Category.query)

factories from conftest.py

@pytest.fixture(scope='function')
def base_factory(db_session):
    class BaseFactory(factory.alchemy.SQLAlchemyModelFactory):
        class Meta:
            abstract = True
            sqlalchemy_session = db_session
            sqlalchemy_session_persistence = 'flush'
    return BaseFactory

@pytest.fixture(scope='function')
def category_factory(base_factory):
    class CategoryFactory(base_factory):
        class Meta:
            model = models.Category
        name = factory.Sequence(lambda n: u'Category %d' % n)
    return CategoryFactory

Test itself:

from flask import url_for
import requests

from demo_app import models

def test_list_categories(live_server, category_factory):
    categories = category_factory.create_batch(5)

    assert models.Category.query.count() == 5

    url = url_for('blog.list_categories', _external=True)

    response_1 = requests.get(url)

    assert response_1.status_code == 200
    data_1 = response_1.content.decode('utf-8')
    for category in categories:
        assert category.name in data_1

    assert models.Category.query.count() == 5

    response_2 = requests.get(url)

    assert response_2.status_code == 200
    data_2 = response_2.content.decode('utf-8')
    print(data_2)
    for category in categories:
        assert category.name in data_2

I'm getting error on line assert models.Category.query.count() == 5, or if I comment it out, data_2 data returned by the server is empty.

The error:

self = <sqlalchemy.dialects.postgresql.psycopg2.PGDialect_psycopg2 object at 0x104135780>
cursor = <cursor object at 0x1040ea900; closed: -1>
statement = 'SAVEPOINT sa_savepoint_23', parameters = {}
context = <sqlalchemy.dialects.postgresql.psycopg2.PGExecutionContext_psycopg2 object at 0x104321048>

    def do_execute(self, cursor, statement, parameters, context=None):
>       cursor.execute(statement, parameters)
E       sqlalchemy.exc.InternalError: (psycopg2.errors.NoActiveSqlTransaction) SAVEPOINT can only be used in transaction blocks
E       
E       [SQL: SAVEPOINT sa_savepoint_23]
E       (Background on this error at: http://sqlalche.me/e/2j85)

Full stack trace

Could you please help me, I don't know where to start to investigate this.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions