[英]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.