Flask Login Pytest API

Configuration pytest for testing Flask API using Flask-Login (Flask-Admin, Flask-Security) in which tests bypass authorization on the site.

Description of the problem

When testing, especially when testing the API, it is necessary to bypass the authorization on the site to pass the tests. To do this, we will use the built-in functions. Below are two configurations in which everything works.

The code considers the traversal as @login_required for API paths, and authorizes the user when passing tests. As a result flask_login.current_user.id sees the specified user.

Configuration 1

File contents conftest.py. This file is used to initialize tests.

import flask_login
import pytest
from app import app, db
from app.models.users import user

@pytest.fixture
def client():
app.config[“TESTING”] = True
# Bypass @login_required
app.config[“LOGIN_DISABLED”] = True
with app.test_client() as client:
yield client

@pytest.fixture
def authenticated_request():
# Solves the problem with flask_login.current_user.id:
# AttributeError: ‘AnonymousUser’ object has no attribute ‘id’
# Creates a user authorization
with app.test_request_context():
test_user = db.session.query(user).filter_by(id=one).first()
yield flask_login.login_user(test_user)

File contents test-category.py

import json
import pytest

from app import db
from app.models.categories import Category
from app.repositories.category import get_category_by_id

headers = {“Content Type”: “application/json”}

@pytest.mark.usefixtures(“authenticated_request”)
def test_category_rename(client):
# Create test data
user_id = one
cat = Category(user_id=user_id, name=‘Test Category’)
db.session.add(cat)
db.session.commit()

#Mock
mock_name = ‘Test Category New’
mock_request_data = {
‘cat_id’:cat.id,
‘name’: mock_name,
}

# Rename category
url = ‘http://127.0.0.1:5000/categories/update/’
client.patch(url, headers=headers, data=json.dumps(mock_request_data))

# Check new name
category = get_category_by_id(user_id, cat.id)
assert category.name == mock_name

# Clear test data
db.session.delete(category)
db.session.commit()

Link to repository in GitHub.

Configuration 2

If you do not need to bypass authorization in all tests, you can bypass authorization in each individual test.

File contents conftest.py:

import pytest
from app import app, db

@pytest.fixture
def client():
app.config[“TESTING”] = True
# Bypass @login_required
app.config[“LOGIN_DISABLED”] = True
with app.test_client() as client:
yield client

File contents test_category.py:

import json
from app import db, app
from app.models.categories import Category
from app.models.users import user
from app.repositories.category import get_category_by_id

headers = {
“Content Type”: “application/json”,
}

def test_category_rename(client):
# Create test data
user_id = one
cat = Category(user_id=user_id, name=‘Test Category’)
db.session.add(cat)
db.session.commit()

#Mock
mock_name = ‘Test Category New’
mock_request_data = {
‘cat_id’:cat.id,
‘name’: mock_name,
}

with app.test_client() as client:
# Solves the problem with flask_login.current_user.id:
# AttributeError: ‘AnonymousUser’ object has no attribute ‘id’
test_user = db.session.query(user).filter_by(id=user_id).first()

@app.login_manager.request_loader
def load_user_from_request(request):
return test_user

# Tests starts here
url = ‘http://127.0.0.1:5000/categories/update/’
client.patch(url, headers=headers, data=json.dumps(mock_request_data))

# Check new name
category = get_category_by_id(user_id, 576)
assert category.name == mock_name

# Clear test data
db.session.delete(category)
db.session.commit()

Link to repository in GitHub.

Running Tests

The tests are run with the command:

Additional keys:

# -s – displays the contents of print
# -v – displays the full name of the tests
# –disable-pytest-warnings – disable warnings summary

Similar Posts

Leave a Reply

Your email address will not be published. Required fields are marked *