簡體   English   中英

將表從主數據庫遷移到 test_db 進行測試,之后刪除測試數據庫(fastapi 和 pytest)

[英]Migrating tables from the main database to the test_db to perform tests, and deleting the test DB after (fastapi and pytest)

我開始按照官方文檔編寫測試模塊,並提出以下代碼:

from ..app.user.model import User
from fastapi.testclient import TestClient
from .temp_app import app

from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker
from app.server.database import get_db, Base

SQLALCHEMY_DATABASE_URL = "sqlite:///./test.db"

engine = create_engine(
    SQLALCHEMY_DATABASE_URL, connect_args={"check_same_thread": False}
)
TestingSessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)

Base.metadata.create_all(bind=engine)

def override_get_db():
    try:
        db = TestingSessionLocal()
        yield db
    finally:
        db.close()

app.dependency_overrides[get_db] = override_get_db

client = TestClient(app)

#perform tests imported from different modules

Base.metadata.drop_all(bind=engine)
#attempt to delete the database after the tests are over

SQLALCHEMY_DATABASE_URL應該在 test.db 中執行測試,而override_get_db方法應該獲取 test.db 而不是主數據庫。

當我使用指向主 SQL 數據庫的SQLALCHEMY_DATABASE_URL運行測試時,測試運行良好,但使用我的代碼我得到:

app\test\test_db.py (sqlite3.OperationalError) 沒有這樣的表:用戶

這表明我的數據庫中的表尚未遷移到 test.db。

我在官方文檔中找不到任何關於此的信息,所以如果我做錯了什么,我會有點困惑,或者只需要一些代碼將表遷移到 test.db。

有人可以幫我理解這一點,並使用測試數據庫中的所有表運行測試嗎?

另外,在 pytest 完成運行測試后 test.db 文件不會被刪除,所以我可能不明白Base.metadata.drop_all(bind=engine)是如何工作的。

感謝您的時間。

編輯:導入所有模型並設置echo=True后的日志

2022-02-04 17:43:37,691 INFO sqlalchemy.engine.Engine BEGIN (implicit)
2022-02-04 17:43:37,691 INFO sqlalchemy.engine.Engine SELECT users.id AS users_id, users."mobileNo" AS "users_mobileNo", users.email AS users_email, users."fullName" AS "users_fullName", users.role AS users_role, users."referralCode" AS "users_referralCode", users.status AS users_status
FROM users
WHERE users."mobileNo" = ? OR users.email = ?
 LIMIT ? OFFSET ?
2022-02-04 17:43:37,691 INFO sqlalchemy.engine.Engine [cached since 9.304s ago] ('1234567890', 'johndoe@gmail.com', 1, 0)
(sqlite3.OperationalError) no such table: users
[SQL: SELECT users.id AS users_id, users."mobileNo" AS "users_mobileNo", users.email AS users_email, users."fullName" AS "users_fullName", users.role AS users_role, users."referralCode" AS "users_referralCode", users.status AS users_status
FROM users
WHERE users."mobileNo" = ? OR users.email = ?
 LIMIT ? OFFSET ?]
[parameters: ('1234567890', 'johndoe@gmail.com', 1, 0)]
(Background on this error at: https://sqlalche.me/e/14/e3q8)
2022-02-04 17:43:37,692 INFO sqlalchemy.engine.Engine ROLLBACK
------------------------------------------------------------------------------------------------------------ Captured log call -------------------------------------------------------------------------------------------------------------
INFO     sqlalchemy.engine.Engine:log.py:117 BEGIN (implicit)
INFO     sqlalchemy.engine.Engine:log.py:117 SELECT users.id AS users_id, users."mobileNo" AS "users_mobileNo", users.email AS users_email, users."fullName" AS "users_fullName", users.role AS users_role, users."referralCode" AS "users_referralCode", users.status AS users_status
FROM users
WHERE users."mobileNo" = ? OR users.email = ?
 LIMIT ? OFFSET ?
INFO     sqlalchemy.engine.Engine:log.py:117 [cached since 9.304s ago] ('1234567890', 'johndoe@gmail.com', 1, 0)
INFO     sqlalchemy.engine.Engine:log.py:117 ROLLBACK
============================================================================================================= warnings summary =============================================================================================================
app\testOptions\model.py:4
  C:\Users\shrid\OneDrive\Documents\backend\app\testOptions\model.py:4: PytestCollectionWarning: cannot collect test class 'TestOptions' because it has a __init__ constructor (from: app/test/test_db.py)
    class TestOptions(Base):
 
app\testResponse\model.py:9
  C:\Users\shrid\OneDrive\Documents\backend\app\testResponse\model.py:9: PytestCollectionWarning: cannot collect test class 'TestResult' because it has a __init__ constructor (from: app/test/test_db.py)
    class TestResult(Base):
 
app\testResponse\model.py:25
  C:\Users\shrid\OneDrive\Documents\backend\app\testResponse\model.py:25: PytestCollectionWarning: cannot collect test class 'TestQuestions' because it has a __init__ constructor (from: app/test/test_db.py)
    class TestQuestions(Base):
 
-- Docs: https://docs.pytest.org/en/stable/warnings.html
========================================================================================================= short test summary info ==========================================================================================================
FAILED app/test/test_db.py::test_create_user - AssertionError: {"detail":"Something went wrong!"}

編輯 2:用戶 Model:

class User(Base):
    __tablename__ = "users"

    id = Column(Integer, primary_key=True, index=True, autoincrement=True)
    mobileNo = Column(String, index=True, nullable=False, default="")
    email = Column(String, index=True, nullable=False, default="")
    fullName = Column(String, nullable=False, default="")
    role = Column(String, default='user')
    referralCode = Column(String, default='1234567890')
    status = Column(String, default='active')

除非我看到您設置 ORM 模型的整個模塊,否則我無法給您一個“確定”的答案,但是閱讀您所寫的內容,我認為如果您從模型的模塊中導入Base (這與您在所有模塊中使用的相同)您的應用程序), Base將有一個稱為元數據( Base.metadata )的 object ,其中將包括您的所有模型,因此當您調用create_all()時,它將看到您定義的模型並創建它。 像這樣進行導入:
from my_app_path.models.main_module_that_has_all_models import Base
如果你的模型遍布整個應用程序結構,你應該有一個模塊來導入它們,因為如果你把它們分散在各處,處理 ORM 模型會很痛苦。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM