2009-07-19 18 views
11

添加函數返回單元測試的對象的內部狀態,而不是使測試類成爲朋友更好嗎? - 尤其是,除了單元測試外,沒有其他功能的用處。在C++中使用朋友類與添加訪問器進行單元測試?

+0

可能重複[如何測試具有私有方法,字段或內部類的類?](https://stackoverflow.com/questions/34571/how-do-i-test-a-class-that -has-private-methods-fields-or-inner-classes) – Raedwald 2017-12-14 13:17:45

回答

12

單元測試應該95%的時間只測試一個類的公開暴露的表面。如果你正在測試一些東西,那就是測試實現細節,這本質上是脆弱的,因爲你應該能夠輕鬆地改變實現並且仍然能夠測試。它不僅脆弱,而且還可能被誘惑測試在計劃的使用場景中實際上不可能的事情,這是浪費時間。

如果您要添加的存取點是隻是爲了測試該功能是否取得了預期的效果,你的類的設計可能違反另一個原則,這是一個國家機器般類應始終清楚什麼如果這會影響人們與班級互動時發生的情況,請說明。在這種情況下,提供這些只讀訪問器是正確的。如果它不影響課程的行爲,請回到我之前關於實施細節的一點。

而且正如你所說的那樣,對於一個沒有使用過的東西的公共表面而言,也是出於其自身原因而不合要求的。

如果我訪問者和你的情況邀請好友之間挑選,我會選擇邀請好友,只是因爲擁有自己的測試,可以在緊要關頭改變它。您可能不會擁有使用您的額外訪問器的小丑的代碼,然後您會被卡住。

1

我推薦使用訪問者而不是通過公共成員或朋友類訪問。

我不認爲使用朋友課實際上會給你帶來任何好處,它有可能讓你的生活在路上走得更糟。如果你的代碼要長期呆在裏面,很可能會以你不希望的方式使用它。訪問函數可能只用於現在的測試,但誰知道未來會發生什麼?使用訪問器而不是直接訪問變量可爲您提供更多的靈活性,而且成本非常低。

另一個說法是使用訪問者而不是公共成員是一個好習慣。養成良好的習慣是程序員的重要技能。

+0

+1用於習慣開發。 – jkeys 2009-07-19 04:45:57

+0

爲了確保我能理解你,變量 的訪問者爲double time;我創建將創建: double time()const; – bias 2009-07-19 04:50:46

+2

是的,有兩個原因:1,它告訴其他程序員你希望他們能夠對數據做什麼; 2:編譯器通常可以優化不具有常量標識符的const函數。 – jkeys 2009-07-19 04:58:12

9

我不同意接受的答案,而是建議使用朋友類。

您正在測試的狀態的一部分可能是特定於您班級的實施;您正在測試其他代碼通常不知道或關心並且不應該依賴的細節。公共訪問器函數使這些實現細節成爲類接口的一部分。如果您正在測試的內部狀態不是預期接口的一部分,則不應通過公共功能顯示。從純粹的角度來看,你被困在兩個錯誤的答案之間,因爲朋友類在技術上也是公共接口的一部分。在我看來,問題就變成了,哪種選擇不太可能導致道路上的編碼選擇不佳?與一組實現相關的公共訪問函數一起使用會不經意地鼓勵類的實現依賴概念模型,導致依賴於實現的類的使用。一個適當命名和記錄的單個朋友類不太可能被濫用。

儘管一般情況下,我非常贊同優先訪問函數而不是直接訪問成員變量的建議,但我不同意這種最佳實踐適用於實現相關內部狀態的單元測試。一個合理的中間點是使用私有訪問器函數來處理單元測試將關心的那些狀態,並且要嚴格遵守單元測試中的訪問函數。只是我的觀點。

0

如何使內部狀態「保護」? 然後使用派生類進行單元測試。

+0

保護比朋友有最差的封裝保護。 **從你的班級繼承的任何**都有合法的訪問權限。而且因爲你把它們保護起來了,你說這確實得到了支持。至少,具有特定名稱「friend class MyObjectOnlyForTestingPurpose」的朋友類將限制對具有一個特定名稱的一個類的訪問。 。 。總而言之,就像將公寓的鑰匙交給一位朋友,不要將鑰匙交給家人中的每個人(包括您女兒的丈夫的半兄弟) – paercebal 2013-06-14 15:27:29

0

我認爲需要通過爲用戶提供訪問器(如果這樣做是有意義的)並提高可測試性來進行面向未來的驗證。我並不是僅僅爲了測試的唯一目的而與朋友結成友誼的粉絲,因爲這會在我不喜歡的地方引入緊密的耦合。

如果唯一使用訪問器是爲測試用例提供一種檢查類的內部狀態的方法,那麼公開地公開它們通常是沒有意義的。它還可以約束您稍後可能希望更改的實現細節,但之後發現不能,因爲其他人正在使用所述訪問器。

我的首選解決方案是提供受保護的訪問器函數,以清楚地向班級的用戶傳達這些不屬於公共接口的部分。然後,您的測試會創建一個包含父代函數的調用存根的最小派生類,但也會使訪問器處於公共狀態,以便您可以在測試用例中使用它們。

+0

不會派生類被視爲客戶/用戶類,就像公共接口的客戶/用戶一樣多?除非唯一派生類是單元測試存根,否則就會出現同樣的問題,如果您已將訪問器公開 - 派生類的作者無法分辨哪些受保護的函數可以調用,哪些只能用於測試目的。如果更改測試相關函數,則可能會中斷不知道不使用訪問器的派生類。 – Darryl 2013-04-29 18:27:40

3

使用朋友類進行單元測試是完全合法的,並允許您維護封裝。你不應該修改你的類的public接口,只是爲了讓這個類更加可測試。這樣想一想。如果您購買了第三方FTP庫,並且您正在嘗試使用它,並且它的公共接口混雜着一堆您不需要僅僅因爲單元測試就知道的方法!即使修改受保護的接口以補償單元測試也是不好的。如果我從某個班繼承,我不想擔心哪些方法對我有用,哪些只是因爲單元測試而存在!使用朋友類進行單元測試可以幫助您維護一個簡單易用的類接口;它有助於保持封裝和抽象!

我聽說過使用朋友類進行單元測試的觀點不好,因爲被測試的類不應該與其測試類「緊密耦合」,也不應該「知道」其測試類的任何內容。我不買這個。這是添加到課程頂部的單行:

friend class MyClassTest;

現在你可以用任何你想要的方式測試你的班級了!

現在我同意你不應該使用朋友類,除非有必要。如果你可以測試什麼需要測試而不需要成爲朋友,那麼一定要這樣做。但如果生活變得困難,並且使用朋友課程可以讓生活更輕鬆,那就用它吧!