上次跟妳講的幾個問題,我把總結成文檔了,妳有空思考一下。
庫底層 api 的實現決定了庫的使用方法。
testcase 需要模擬用戶使用。
若干因素會影響到使用者
- 同步/異步編程模型。
已實現同步,現有所有代碼基於同步編程模型開發,不需要註冊回調函數。異步方式的測試代碼其實和同步的大體相同,只不過調用、使用方式有所區別。沒必要寫兩份差不多的代碼。
妳思考一下,如何通過採用統一的 testcase,測試async/sync的api
若干因素會影響到 testcase
- 測試邏輯
比如如下是針對 get 的單元測試,如果它通過,說明 get 命令確實可用(關於 get: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。