Files
superset2/tests/integration_tests/dao/conftest.py
Amin Ghadersohi dced2f8564 feat: Add BaseDAO improvements and test reorganization (#35018)
Co-authored-by: bito-code-review[bot] <188872107+bito-code-review[bot]@users.noreply.github.com>
Co-authored-by: Claude <noreply@anthropic.com>
2025-09-16 18:15:16 -07:00

144 lines
4.5 KiB
Python

# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
"""
Fixtures for DAO integration tests.
This module provides fixtures that replicate the unit test behavior by using
an in-memory SQLite database for each test to ensure data isolation and avoid
conflicts between test runs.
Key features:
- In-memory SQLite database created per test
- Proper Flask-SQLAlchemy session patching
- Security manager session handling
- Automatic cleanup after each test
"""
from typing import Generator
from unittest.mock import patch
import pytest
from flask import Flask
from flask_appbuilder.security.sqla.models import User
from sqlalchemy import create_engine
from sqlalchemy.orm import Session, sessionmaker
from sqlalchemy.pool import StaticPool
from superset.extensions import db
from tests.integration_tests.test_app import app as superset_app
@pytest.fixture(scope="module", autouse=True)
def setup_sample_data() -> None:
"""
Override parent conftest setup_sample_data to prevent loading sample data.
This prevents the parent conftest from loading CSS templates and other
sample data that could interfere with DAO integration tests.
"""
pass
@pytest.fixture
def app() -> Flask:
"""Get the Superset Flask application instance."""
return superset_app
@pytest.fixture
def app_context(app: Flask) -> Generator[Session, None, None]:
"""
Create an in-memory SQLite database for each test.
This fixture replicates the unit test behavior by providing a fresh
in-memory database for each test, ensuring complete data isolation
and avoiding conflicts between test runs.
Args:
app: Flask application instance
Yields:
Session: SQLAlchemy session connected to in-memory database
"""
# Create in-memory SQLite engine with StaticPool to avoid connection issues
engine = create_engine(
"sqlite:///:memory:",
poolclass=StaticPool,
connect_args={"check_same_thread": False},
)
# Create session bound to in-memory database
session_factory = sessionmaker(bind=engine)
session = session_factory()
# Make session compatible with Flask-SQLAlchemy expectations
session.remove = lambda: None
session.get_bind = lambda *args, **kwargs: engine
with app.app_context():
# Patch db.session to use our in-memory session
with patch.object(db, "session", session):
# Import models to ensure they're registered
from flask_appbuilder.security.sqla.models import User as FABUser
# Create all tables in the in-memory database
# Flask-AppBuilder models use a different metadata object
# We need to create tables from both metadata objects
# First create Flask-AppBuilder tables (User, Role, etc.)
FABUser.metadata.create_all(engine)
# Then create Superset-specific tables
db.metadata.create_all(engine)
try:
yield session
finally:
# Clean up: rollback any pending transactions
session.rollback()
session.close()
engine.dispose()
@pytest.fixture
def user_with_data(app_context: Session) -> Session:
"""
Create a test user in the database.
Some DAO tests expect a user with specific attributes to exist.
This fixture creates that user and returns the database session.
Args:
app_context: Database session from app_context fixture
Returns:
Session: The same database session with test user created
"""
# Create test user with expected attributes
user = User(
username="testuser",
first_name="Test",
last_name="User",
email="testuser@example.com",
active=True,
)
db.session.add(user)
db.session.commit()
return app_context