自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

FastAPI 之自動(dòng)化測(cè)試數(shù)據(jù)庫(kù)接口

運(yùn)維 數(shù)據(jù)庫(kù)運(yùn)維 自動(dòng)化
今天的文章分享如下在 FastAPI 框架下,使用 pytest 來(lái)自動(dòng)化測(cè)試數(shù)據(jù)庫(kù)相關(guān)的接口,文章的最后給出全部代碼。

[[442950]]

今天的文章分享如下在 FastAPI 框架下,使用 pytest 來(lái)自動(dòng)化測(cè)試數(shù)據(jù)庫(kù)相關(guān)的接口,文章的最后給出全部代碼。

最近越來(lái)越喜歡使用 FastAPI 來(lái)寫(xiě)后端服務(wù)了,因?yàn)樗?Python 領(lǐng)域性能最好的 Web 框架,它專(zhuān)注于提供高性能的 Web API,其他方面并不限制你的手腳,可以隨意使用你喜歡的三方庫(kù),這點(diǎn)類(lèi)似于 Flask,可以量身定制你的后端架構(gòu),以滿(mǎn)足自己的需求。

需要說(shuō)明的是,后端服務(wù)基本是離不開(kāi)關(guān)系型數(shù)據(jù)庫(kù)的,我之前是使用 Django,Django 的 ORM 太優(yōu)秀了,以至于我從 Django 轉(zhuǎn) FastAPI 有點(diǎn)很不適應(yīng)。在 ORM 領(lǐng)域,可以說(shuō)除了 Django 的 ORM,就是 SQLAlchemy 了。所以不用 Django,就必須會(huì)用 SQLAlchemy,要快速了解,看看廖雪峰的官方網(wǎng)站的使用 SQLAlchemy[1] 來(lái)快速入門(mén)。

FastAPI 涉及數(shù)據(jù)庫(kù)的接口寫(xiě)起來(lái)并不難,跟著官方文檔sql_databases[2],5 分鐘,我們就可以生成關(guān)于數(shù)據(jù)庫(kù)的增刪改查的 Restful 風(fēng)格的 API,難的是如何自動(dòng)化的測(cè)試,

通常情況下,我們會(huì)使用 pytest 進(jìn)行自動(dòng)化單元測(cè)試,根據(jù)數(shù)據(jù)庫(kù)的記錄數(shù)來(lái)斷言,但是,每測(cè)試一次,數(shù)據(jù)庫(kù)中的記錄就保存了下來(lái),你下次測(cè)試時(shí)如果不手動(dòng)清理,那測(cè)試仍然可能失敗。

那怎么解決呢?

那就是利用數(shù)據(jù)庫(kù)的回滾功能,會(huì)改變數(shù)據(jù)庫(kù)記錄的接口測(cè)試完成后讓事務(wù)回滾,這樣每次測(cè)試完成后,數(shù)據(jù)庫(kù)的記錄數(shù)是不變的,每次運(yùn)行 pytest,數(shù)據(jù)庫(kù)的記錄數(shù)是不變的,這樣就可以進(jìn)行自動(dòng)化測(cè)試。

要想實(shí)現(xiàn)這一點(diǎn),我們需要借助于 pytest 的 fixture 功能。

pytest.fixture 是一個(gè)裝飾器,用于聲明函數(shù)是一個(gè) fixture。如果測(cè)試函數(shù)的參數(shù)列表中包含 fixture 名,那么 pytest 會(huì)檢測(cè)到,并在測(cè)試函數(shù)運(yùn)行之前執(zhí)行 fixture。

比如:

  1. import pytest 
  2.  
  3. @pytest.fixture() 
  4. def some_data(): 
  5.     return 42 
  6.  
  7. def test_some_data(some_data): 
  8.     assert some_data==42 

fixture 包含一個(gè) scope 的可選參數(shù),用于控制 fixture 執(zhí)行配置和銷(xiāo)毀邏輯的頻率:

  • scope='function' 函數(shù)級(jí)別的 fixture 每個(gè)測(cè)試函數(shù)只運(yùn)行一次。配置代碼在測(cè)試用例運(yùn)行之前運(yùn)行,銷(xiāo)毀代碼在測(cè)試用例運(yùn)行之后執(zhí)行。function 是 fixture 參數(shù)的默認(rèn)值。
  • scope='class' 類(lèi)級(jí)別的 fixture 每個(gè)測(cè)試類(lèi)只運(yùn)行一次,不管測(cè)試類(lèi)中有多少個(gè)類(lèi)方法都可以共享這個(gè) fixture
  • scope='module' 模塊級(jí)別的 fixture 每個(gè)模塊只運(yùn)行一次,不管模塊里有多少個(gè)測(cè)試函數(shù),類(lèi)方法或其他 fixture 都可以共享這個(gè)fixture
  • scope='session' 會(huì)話(huà)級(jí)別的 fixture 每次會(huì)話(huà)只運(yùn)行一次。一次 pytest 會(huì)話(huà)中的所有測(cè)試函數(shù)、方法都可以共享這個(gè) fixture

比如說(shuō)讓數(shù)據(jù)庫(kù)回滾的,我們就可以寫(xiě)一個(gè)這樣的 fixture:

  1. @pytest.fixture(scope="function"
  2. def db(db_engine): 
  3.     connection = db_engine.connect() 
  4.     # begin a non-ORM transaction 
  5.     connection.begin() 
  6.     # bind an individual Session to the connection 
  7.     db = Session(bind=connection
  8.     # db = Session(db_engine) 
  9.     app.dependency_overrides[get_db] = lambda: db 
  10.     yield db 
  11.     db.rollback() 
  12.     connection.close() 

當(dāng)然還有很多 fixture,比如說(shuō)創(chuàng)建數(shù)據(jù)庫(kù)引擎:

  1. @pytest.fixture(scope="session"
  2. def db_engine(): 
  3.     engine = create_engine(SQLALCHEMY_DATABASE_URL) 
  4.     if not database_exists: 
  5.         create_database(engine.url) 
  6.  
  7.     Base.metadata.create_all(bind=engine) 
  8.     yield engine 

再比如,在測(cè)試前,數(shù)據(jù)庫(kù)中先插入 2 條數(shù)據(jù):

  1. @pytest.fixture 
  2. def items(db): 
  3.     create_item(db, schemas.ItemCreate(title="item 1")) 
  4.     create_item(db, schemas.ItemCreate(title="item 2")) 

把這些 fixture 函數(shù)放在文件名conftest.py 中,pytest 會(huì)自動(dòng)讀取并執(zhí)行。至于為什么放在 conftest.py中,請(qǐng)查閱 pytest 文檔,這里不展開(kāi),

接下來(lái),利用這些 fixture,編寫(xiě)單元測(cè)試用例,一個(gè)示例如下:

  1. from fastapi.testclient import TestClient 
  2. from . import crud 
  3. from .main import app 
  4.  
  5. def test_post_items(db): 
  6.     client = TestClient(app) 
  7.     client.post("/items/", json={"title""Item 1"}) 
  8.     client.post("/items/", json={"title""Item 2"}) 
  9.     client.post("/items/", json={"title""Item 3"}) 
  10.  
  11.     items = crud.get_items(db) 
  12.     assert len(items) == 3 
  13.  
  14.  
  15. def test_list_items(items, client): 
  16.     response = client.get("/items"
  17.     assert len(response.json()) == 2 

其中 test_post_items,測(cè)試的是提交了 3 個(gè)數(shù)據(jù),然后斷言數(shù)據(jù)庫(kù)中的記錄數(shù)為 3。test_list_items 有個(gè)參數(shù)是 items,會(huì)調(diào)用之前的 fixture,提前往數(shù)據(jù)庫(kù)插入了 2 條記錄,因此斷言記錄數(shù)為 2。

每個(gè)測(cè)試函數(shù)執(zhí)行時(shí)互不影響,執(zhí)行完成后,數(shù)據(jù)庫(kù)都會(huì)回滾,測(cè)試前 items 是空的,測(cè)試之后 表仍然是空的,這樣就可以自動(dòng)進(jìn)行數(shù)據(jù)庫(kù)的測(cè)試了。

完整代碼

不能選擇 sqlite 數(shù)據(jù)庫(kù)進(jìn)行測(cè)試,因?yàn)樗恢С植l(fā)訪問(wèn)。

 

代碼的數(shù)據(jù)庫(kù)配置為 mysql,用戶(hù)名、密碼、數(shù)據(jù)庫(kù)名請(qǐng)自行修改后執(zhí)行。

 

責(zé)任編輯:武曉燕 來(lái)源: Python七號(hào)
相關(guān)推薦

2013-06-07 19:04:15

測(cè)試

2018-05-11 13:39:05

PythonCSV接口測(cè)試

2018-05-11 08:29:10

Python自動(dòng)化測(cè)試數(shù)據(jù)驅(qū)動(dòng)

2023-05-18 14:01:00

前端自動(dòng)化測(cè)試

2017-01-17 15:14:49

MySQL數(shù)據(jù)庫(kù)自動(dòng)化

2011-04-01 15:07:29

數(shù)據(jù)庫(kù)自動(dòng)化

2023-09-13 11:40:12

2022-12-26 12:30:28

接口測(cè)試

2014-04-16 14:15:01

QCon2014

2010-12-21 13:13:10

BMC數(shù)據(jù)庫(kù)自動(dòng)化服務(wù)

2013-05-16 10:58:44

Android開(kāi)發(fā)自動(dòng)化測(cè)試

2022-02-17 10:37:16

自動(dòng)化開(kāi)發(fā)團(tuán)隊(duì)預(yù)測(cè)

2012-02-27 17:34:12

Facebook自動(dòng)化

2021-09-03 09:56:18

鴻蒙HarmonyOS應(yīng)用

2021-06-30 19:48:21

前端自動(dòng)化測(cè)試Vue 應(yīng)用

2012-12-24 22:54:31

2011-12-23 17:09:57

自動(dòng)化測(cè)試

2024-11-01 15:05:12

2022-08-14 16:11:23

Python自動(dòng)化測(cè)試數(shù)據(jù)

2011-01-20 10:17:25

ibmdwWeb
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)