2009-09-04 30 views
3

考慮這兩個數據驗證場景:TDD能否成爲替代過度殺傷數據驗證的有效選擇?

檢查事事處處

確保每一個需要一個或多個參數實際檢查它們的方法,以確保它們是語法有效。

優點

  • 非常精細檢查粒度。
  • 如果正在編寫的代碼適用於某種類型的庫,那麼如果開發人員使用它的代碼不能提供有效的數據,我們一定要限制可以完成的損害。

缺點

  • 這是昂貴的,始終執行大部分的時間應該沒有必要的檢查。
  • 現在仍然可以忘記添加支票。
  • 更多代碼正在編寫中,因此需要維護。

。利用TDD善良的,當它進入只有

驗證數據從外部世界中你的代碼。 爲了確保內部數據總是在語法上正確,創建測試來檢查每個返回值的方法。爲確保有效數據輸入,有效數據將退出。

優點和缺點實際上與以前的方法切換。

截至目前我正在使用第一種方法,但由於我正在使用測試驅動開發,我認爲也許我可以與第二種方法一起使用。

優點很明顯,仍然,我不知道它是否像第一種方法一樣安全。

回答

0

優點很明顯,仍然不知道它是否與第一種方法一樣安全。

這完全取決於你測試它的程度。

這可能是一樣安全,如果下面的兩個條件都滿足:

  • 被完全驗證將數據添加到系統的每一個公開曝光裝置
  • 該轉換數據的每個內部方法完全和充分測試

但是,我質疑這會更容易或它需要更少的代碼。檢查每個公共入口點所需的代碼量將與驗證每種方法所需的代碼量非常相似。您將需要在入境點進行更多檢查,因爲他們必須檢查可能在內部檢查的內容。

0

對於第二種方法,您需要兩組好的測試。您不僅必須檢查

要確保如果有效數據 進入,有效數據將退出。

您還必須檢查如果無效數據進入,則會引發異常。我想你還是需要驗證數據,如果你有無效數據,就踢出去。如果您不希望在生產應用程序中出現令人討厭的ArgumentNullException或其他隱藏錯誤,這纔是真正的唯一方法。然而,TDD確實可以增強所有檢查的質量(尤其是Fuzz Testing)。

+0

這很有趣。儘管如此,如果我在運行時檢查中錯過了某些東西,我是不是還會遇到討厭的異常?這不就等於不好寫我的測試嗎?那麼我只會確保無效數據在入口點得到妥善處理,而不是完整的應用程序。 – RobSullivan 2009-09-04 17:19:35

2

聽起來像第一種方法是契約驅動的,其中一個方面就是您還需要驗證您從任何公共接口返回的內容是否符合合同。

但是,我認爲這兩種方法都是有效的,但非常不同。

TDD只是部分處理公共接口,因爲它應該檢查每個輸入是否被正確驗證,除非你已經在單獨的函數中進行了所有驗證,並且要進行充分的測試,否則很難確保這個函數3或4個參數正在進行正確的有效性測試。無論採用哪種方法,您必須編寫的測試數量都非常高。

如果您正在使用一個庫,那麼在每個可以從外部直接調用的函數中(外部在庫之外),那麼您將需要檢查每個輸入是否有效,並且該無效輸入是按照每個該合同要麼返回null,要麼拋出異常。但是,它必須與文檔一致。

一旦您驗證了它,那麼沒有理由強制對私有函數進行驗證,因爲只能從庫中調用這些驗證,並且您應該驗證您只處理有效數據。

很遺憾,無論如何,都需要進行大量測試。所有這些測試都是爲了確保您沒有任何意外問題,但這通常有助於證明寫作和維護成本的合理性。

至於你的問題,如果你的測試寫得很好,而且你確保所有的有效性檢查完全完成,那麼它應該是安全的,但風險是如果你認爲它是安全的,書面測試,那麼它實際上會比沒有測試更差,因爲有一個假設,你的測試寫得很好。

我會同時使用這兩種方法,直到你知道你的測試寫得很好,那麼就跟TDD一起去吧。

+0

同意。我通常擔心我的公共接口,並假設內部方法的參數是有效的(更多的是保持方法比其他任何方法都短)。我想這些方法可能會在重構/重用時冒泡給公衆,但是如果你總是測試你的公共接口...... – TrueWill 2009-09-04 17:53:22

+0

實際上,我將使用AspectJ來測試我的Java公共函數,以確保輸入參數和返回數據與文件一致。 – 2009-09-04 18:48:47

1

我的看法是,在第一種情況,你的兩個缺點的勝過一切:

  • 這是昂貴的,始終執行大部分的時間不應該 需要檢查 。
  • 正在編寫更多的代碼,因此需要維護的 。

此外,技術上TDD對此問題沒有影響,因爲它不是測試技術。越到後來...

爲了緩解缺點我強烈主張(因爲我認爲你說的)代碼分成外的:外面是,所有的驗證發生。希望這只是一個薄薄的包裝,以防止GIGO。一旦進入,數據就不需要再次驗證。

至於TDD,我會強烈主張(現在正在這樣做),將其用於開發您的代碼,並留下成爲迴歸測試套件的測試的附加益處。現在,您將自然地開發以外的代碼,以執行可靠的驗證,並且可以輕鬆添加您最初可能會忘記的任何檢查。你的裏面的代碼可以開發,假設它只處理有效數據,但TDD仍然會給你信心,它會起作用。我說我會用第二種方法,就像我所描述的那樣,不管我是用TDD開發還是不用(但TDD總是我的第一選擇)。

0

您的Pros and Cons列表中缺少一項,這對於使單元測試比瘋狂參數檢查更安全的方法足夠重要。

您只需考慮其中

對於單元測試時和其中有:

  • 時:在設計時
  • 其中:在一個專用源文件的應用程序代碼

的外對於矯枉過正的數據檢查他們是:

  • 時:在運行時
  • 其中:糾纏在應用程序源代碼,典型地使用斷言。

這是問題所在:通過單元測試覆蓋的代碼在設計時檢測到錯誤,當您運行測試,如果你是偏執和schizofrenic樣測試儀(最好成績)你寫的設計打破測試什麼可以檢查每個數據邊界和不正確的輸入。您還使用代碼覆蓋工具來確保每個備選方案的每個分支都經過測試。你沒有限制:測試在他們自己的文件中,不要混亂應用程序。如果您獲得比實際應用程序代碼多十倍的測試行,則無關緊要,不會造成運行時間損失,也不會導致可讀性受損。

另一方面集成的過度測試檢測到運行時出錯。在最糟糕的情況下,它會檢測用戶系統上的錯誤,在這裏你無能爲力(如果你曾經聽說過這個錯誤發生)。即使你是偏執型的,你也必須限制你的測試。斷言不能是應用程序代碼的90%。它提高了可讀性問題,維護,往往重性能的懲罰。你會在哪裏停止:只檢查外部輸入參數?檢查內部函數的每個可能或不可能的輸入?檢查每個循環不變?還測試流出數據(全局變量,系統文件等)時的行爲是否改變?您還必須意識到斷言代碼也可能包含一些錯誤。如果斷言的公式會發生分裂怎麼辦?您必須確保它不會由DIVIDE-BY-ZERO錯誤或類似錯誤導致?

另一個問題是,在很多情況下,你只是不知道斷言失敗時可以做什麼。如果你處於一個真正的入口點,你可以返回你的用戶或lib用戶可以理解的東西......當你檢查innner功能時

+0

明白我的答案有點諷刺,我對每種方法各自的優點和缺點進行了探索。但我相信基本點持有。 – kriss 2009-09-08 06:35:45

相關問題