[design draft] testcase for redis-cpp
上次跟妳講的幾個問題,我把總結成文件了,妳有空思考一下。
庫底層 api 的實現決定了庫的使用方法。
testcase 需要模擬使用者使用。
若干因素會影響到使用者
-
同步/非同步程式設計模型。
已實現同步,現有所有程式碼基於同步程式設計模型開發,不需要註冊回撥函式。非同步方式的測試程式碼其實和同步的大體相同,只不過呼叫、使用方式有所區別。沒必要寫兩份差不多的程式碼。
妳思考一下,如何通過採用統一的 testcase,測試async/sync的api
若干因素會影響到 testcase
-
測試邏輯
比如如下是針對 get 的單元測試,如果它通過,說明 get 命令確實可用(關於 get:ofollow,noindex">https://redis.io/commands/get )。
test("get"); { c.set(foo, bar); ASSERT_EQUAL(c.get(foo), bar); }
比如如下是針對 set 的單元測試,如果它通過,說明 set 命令確實可用(關於 set:https://redis.io/commands/set )。
test("set"); { c.set(foo, bar); ASSERT_EQUAL(c.get(foo), bar); }
但是,
get 的 UT 通過的前提條件是 “set 確實能設定一個 key 的值”(即 set 的 UT 通過)。
set 的 UT 通過的前提條件是 “get 確實能取得一個 key 的值”(即 get 的 UT 通過)。
由此可以看出,各個api的UT之間是存在依賴關係的,無法保證這些測試用例從邏輯上完全正確。
以上是實際的一種情況。
如下抽象一下:
logic dependency:
T(A) -> T(B) T(B) -> T(C)
testcase:
TestA(...); TestB(...); TestC(...);
如果
B 的 UT 通過的前提是 A 的 UT 通過。
C 的 UT 通過的前提是 B 的 UT 通過。
就可以通過測試函式的呼叫順序解決問題,A 放在 B 之前,如果 A 不通過,則直接退出,不會執行到 B,如此等等。。如果程式執行完,則說明 A, B, C 都通過了。
現在的程式碼有些是使用這種方法寫的,但是 api 之間的耦合多了,就沒法這麼寫了。
妳思考一下,怎麼保證 testcase 從邏輯上是完備的。
-
api太多
如果這些 testcase 全部都手動寫,確實可以實現測試需求,但是隨著 api 的變化,會導致 testcase 每次都需要改動。其實,testcase 是由api實現決定並由其預期的,所以理論上是能做到自動生成。這樣作為庫的開發者,只需要實現底層功能和生成 testcase 的程式碼即可,可做到“只改實現和預期,不改 testcase”。
妳思考一下,如何做到從預期出發,最終不需要寫 testcase,讓程式自己生成 testcase。