每天的專案會同步到 github 上,可以前往 這個網址 如果對於專案有興趣或是想討論一些問題,歡迎留言 OR 來信討論,信箱為:nickchen1998@gmail.com
接下來兩天我們要來介紹兩種虛擬資料庫,虛擬的資料庫可以讓我們在測試的時候可以在不實際建立資料庫環境的前提下,進行資料庫 CRUD 的函式測試,接下來兩天會分別會針對 SQL & NoSQL 各介紹一種,而今天我們先介紹 SQL 陣營的虛擬資料庫 - In-memory SQLite
由於今天的專案會比較符合真正在撰寫測試的情境,因此檔案稍微多了一些,另外今天會使用到 sqlalchemy 這個操作關聯式資料庫的套件,有興趣的人可以到我之前寫的文章看看,今天就把重點放在測試的部份上,下方為本次的專案架構截圖
有使用過 sqlalchemy 或 sqlmodel 的人,想必對於下方的路徑會很熟悉,這個是用在將資料庫與 ORM 架構做連線時的資料庫位置
mysql+pymysql://<username>:<password>@<host>:<port>/<database_name>
而今天要介紹的虛擬關聯式資料庫,是使用 SQLite 所提供的 In-memory 的資料庫,使用的路徑非常簡單,如下所示
sqlite://
且由於 python 內自帶 sqlite 的套件,所以只要將上面的路徑放入資料庫連線的路徑,電腦就會動使用記憶體協助我們進行資料表的建立以及操作
這邊我們會先簡單介紹放在 models 的內容以及要被測試的 CRUD 的函式
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import String, Column, Integer, DATETIME
from datetime import datetime
Base = declarative_base()
class User(Base):
__tablename__ = "user"
id: int = Column(Integer, primary_key=True, autoincrement=True)
username: str = Column(String(64))
birthday: datetime = Column(DATETIME)
from sqlalchemy.orm import Session
from models import User
def create_user_in_sqlite(data: User, session: Session) -> User:
session.add(data)
session.commit()
session.refresh(data)
return data
接下來就是重點了,sqlalchemy 實際對資料庫進行操作的時後,需要一個 session 物件來協助我們進行操作,接下來我們就要利用 fixture 來替我們在測試前做建立資料表以及產生一個 session 的動作
程式解析:
import pytest
from sqlalchemy import create_engine
from sqlalchemy.orm import Session, sessionmaker
from models import Base
@pytest.fixture(name="sqlite_session")
def sqlite_session_fixture() -> Session:
# 建立 engine
engine_url = "sqlite://"
engine = create_engine(engine_url)
# 建立資料表
Base.metadata.create_all(engine)
# yield 出 Session
with sessionmaker(bind=engine)() as session:
yield session
# 刪除資料表
Base.metadata.drop_all(engine)
接下來就來就準備撰寫 test case 了,一樣附上程式碼並逐行解釋
程式解析:
from crud import create_user_in_sqlite
from models import User
from fixtures import sqlite_session_fixture
from sqlalchemy.orm import Session
from datetime import datetime
use_fixtures = [sqlite_session_fixture]
def test_create_user_in_sqlite(sqlite_session: Session):
data = User(username="test_user", birthday=datetime.now())
result: User = create_user_in_sqlite(data=data, session=sqlite_session)
print(result.__dict__)
assert result.username == data.username
接著我們就可以利用 pytest 對 test_demo.py 進行測試了,下方為測試結果截圖
今天我們介紹了虛擬的 SQLite 資料庫,這個資料庫基本上可以兼容大多數的關聯式資料庫,但還是有特例,例如:postgres 當中的 Array 欄位無法使用在 SQLite 當中,因此使用相關的功能時就會產生錯誤,這個時候可能就還是得利用 docker 建立一個測試用的資料庫才可以進行測試,不過原本就是使用 mysql 或式 sqlite 的朋友,就完全不用擔心這個問題了
明天我們會介紹無關連式資料庫 (NoSQL) 陣營的虛擬資料庫 - MongoMock
基於sqlalchemy.ext.declarative.declarative_base
現在會有提示警告,models.py
第一行可改為SQLAlchemy 2.0版以後可用的 from sqlalchemy.orm import declarative_base
MovedIn20Warning: The
declarative_base()
function is now available as sqlalchemy.orm.declarative_base(). (deprecated since: 2.0) (Background on SQLAlchemy 2.0 at: https://sqlalche.me/e/b8d9)
Base = declarative_base()
-- Docs: https://docs.pytest.org/en/stable/how-to/capture-warnings.html
謝謝您的分享
感謝補充