![](/img/trans.png)
[英]Optimization and testability at the same time - how to break up code into smaller units
[英]How do I factor code to ease testability?
我正在學習單元測試,並想知道如何編寫可測試的代碼。 但是,我不確定如何在不使其復雜的情況下編寫可測試代碼。 我將采用着名的汽車和發動機問題來描述問題。
class Car
{
private:
Engine m_engine;
public:
Car();
// Rest of the car
}
我提出了以下解決方案,以使上述代碼可測試。
更改Car的構造函數以將Engine作為參數。 然后模擬引擎並進行測試。 但是,如果我沒有不同類型的引擎,那么參數化構造函數似乎是不合適的,只是為了使它可測試。
使用setter然后將模擬引擎傳遞給setter。 與上述相同的流程。
首先測試引擎,然后使用經過驗證的引擎(或使用存根引擎)測試汽車。
我必須在代碼上測試哪些替代方案? 每種方法的優點和缺點是什么?
從不同的(測試驅動開發)觀點來看:易於測試的代碼易於使用。 編寫單元測試實際上是在測試代碼的“公共接口”。 如果它很難測試,那是因為你在那里有一些依賴,這使得它很難。 你真的需要一個遏制關系,還是一個聯想關系會更有意義?
在你的情況下,我個人認為在構造函數中傳遞Engine會更容易測試,所以我會像你的建議#1那樣重構構造函數。 您可以在一個測試套件中測試引擎,並提供一個模擬引擎來測試另一個測試套件中的Car。 現在測試它很簡單,這意味着界面易於使用。 這是好事。
現在考慮如何在實際項目中使用該實現。 您將創建一個CarFactory類,工廠將創建一個引擎並將其放入Car中,然后再將其交付給您。 (還要注意這最終如何更接近地模擬汽車,發動機和工廠的真實世界,但我離題了。)
因此,TDD的答案是重構代碼以在構造函數上獲取Engine指針。
如果您只有一個引擎類型,為什么要嘗試將其作為新對象? 如果您不打算交換引擎,請不要創建另一個抽象層。 只需將發動機作為汽車的一部分。
您可能正在分解以降低復雜性,而不是重用組件。 好決定。 在這種情況下,我會說3是你最好的選擇 - 驗證你的低級組件,然后使用調用較低級別對象的更高級代碼。
實際上,Engine更像是數據庫。 並且您將需要更改構造函數以使用不同的數據庫(出於測試原因或其他原因),但您可以暫時擱置該謊言。
正如其名稱所暗示的,單元測試是關於測試單元以確認它們按照規定工作。 這意味着,您應該單獨測試引擎。
系統測試或集成測試是關於測試它們是否正確“粘合”在一起。
當然,它比這更復雜,但它應該指向正確的方向。
選項1通常是正確的方式。
通過完全控制您給汽車的發動機,您可以很好地測試汽車。
您可以使用引擎為汽車提供的所有不同輸出,更輕松地測試汽車的行為方式。 您還可以確保汽車對發動機進行適當的調用。
在構造函數中使用它可以清楚地表明Car依賴於引擎來工作。 將它與依賴注入框架一起使用,構造函數問題根本不是問題。
真正的問題是,有哪些要求? 如果目標是簡單地實現“汽車”對象,那么它甚至不需要引擎。
測試應始終與要求相關。 任何對象模型都將是對現實的一些概括,因此問題在於需要表示哪些方面。
一旦你的需求下降,那么你應該在通用的高級別上編寫測試。 然后,OO設計應該以這樣的方式完成,即可以實現這些測試。
C ++的一個可能性是使用友誼:
class Car
{
private: //for unit testing
friend class TestCar; //this class is the unit test suite for the Car class
Car(Engine* mockEngine); //this constructor is only used by the TestCar class
private:
Engine* m_engine;
public:
Car();
// Rest of the car
};
第二種可能性是構造函數的實現使用全局/靜態方法,例如如下所示,您可以通過一些配置文件或通過鏈接(可能是動態鏈接)到此不同版本來更改此方法的實現方法:
Car::Car()
{
m_engine = Engine::create();
}
我主張允許(通過構造函數或屬性)將Engine的實現添加到Car(最好是IEngine)。
汽車測試實際上並不關心引擎的作用,只要它能夠正確響應調用引擎的結果。 然后,使用假引擎進行測試,以便您可以控制發送到汽車的信號,您應該好好去。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.