2009-12-02 52 views
2

如果這個標題沒有意義(我期待=))這裏是我問:斷言與自己的單元測試功能輸出?

我有一個函數稱爲ParseFile()。它將一個字符串作爲參數,並將一個DataTable作爲返回值。

我想單元測試這個功能。首先編寫函數,運行它,獲取輸出,將其序列化爲XML,將其保存爲預期輸出,然後編寫單元測試以調用函數並針對反序列化的數據斷言,這是錯誤的嗎?

我意識到這有助於我走下坡路,如果我們得到新的輸入,我們可能以前沒有見過,並且必須更改解析函數來處理它 - 運行我的測試現在會斷言我沒有打破任何當前工作文件。真棒...

..但在這種情況下,格式將永遠不會改變,並且是標準的。那麼,我所說的完全沒用?如果是,那麼如何測試這個功能呢?

而且哎呀,如果我說的仍然是一個好主意 - 你怎麼會連做真正的TDD風格和編寫測試第一?沒有沉悶地爲文件中的每個預期字段編寫Assert調用()?我並不完全處於TDD'模式' - 但是我試圖到達那裏......而且這種情況我有時會想知道如何在第一次測試時對它進行測試,當預期輸出是一個數據集例如...

感謝

回答

4

這沒有錯,但它不是TDD。

話雖這麼說,我想提醒你有關主張對XML字符串:當出現錯誤時,XML尺寸足夠大,你最終手動比較兩個XML字符串中,犯錯不錯,在視覺上。

在那裏,做到了。我記得在這種情況下,將XML複製到兩個文件中,將其修改爲每行具有一個屬性並將兩個文件與diff進行比較。我說過我會嘗試下次使用XPath和/或XQuery來聲明XML。

另外,是不是你的函數做了太多事情:解析字符串生成XML?你可能想考慮把它分開。

你會怎麼做到真正的TDD 風格並先寫測試?

如果你真的想使用TDD並保留一個函數,那麼你可以從一個測試開始:你的XML輸出應該是什麼樣的空字符串?這是你的第一個考驗。一旦它通過,用一個簡單元素的字符串重新啓動,編寫測試,使其通過,並採取更復雜的字符串。泡沫,沖洗,重複。

2

這取決於你爲什麼要編寫測試。

從測試驅動開發的角度來看,您描述的過程是錯誤的。從質量保證的角度來看,它具有很大的意義,因爲它爲您提供了一個迴歸測試套件,可以在您前進時充當安全網。

使用TDD開發此類方法的關鍵是將它們分成更小的塊(單元)並單獨測試每個塊。如果你可以設法把它分成許多小塊,那麼它通常會產生一個更加靈活和可重用的API,而不是具有一些輸入和輸出的單一方法。

你如何分割這種方法?

開始思考如何將其組織到私人幫手方法中。然後考慮一下這些輔助方法中的一些(或全部)方法是否可以用一個對象來表示。設計模式如策略抽象工廠在這個意義上可以是非常有用的。

而不是粗粒度的API與很多內部邏輯,你會得到一個細粒度的API與許多公共,但可組合的邏輯。

1

您不應該將您的對象的序列化形式作爲測試進行比較。這太具體實現了。你只應該測試界面。

您應該測試DataTable對象的特定屬性,例如它有四行,五列,並且該單元[1,2]包含字符串「Fish」。

2

通常我會盡量遠離那些「寬泛」的測試功能。我更喜歡測試更細粒度的功能。我假設你的ParseFile()方法使用了幾個實用方法,它們本身使用其他實用程序方法。這些是我嘗試測試的方法。通常,像這樣的任何輸入都是由幾個不同的數據組成的。與其試圖測試整個文件是否被正確解析,你能否瀏覽一下ParseFile()方法和正在解析的數據,並將它分解成幾個較小的測試,這些測試在它們的聚合中給予你相同的信心?

我個人更喜歡這種方法的理由是,如果我需要修改任何解析代碼並且測試失敗,那麼我有更快的路徑來找到失敗的原因,而不是「ParseFile()沒有返回預期的結果「。 :)

3

這似乎更像是黑盒測試比單元測試。但是如果您確定生成的數據集是正確的,那麼我不會看到您執行此操作的問題。你是確保數據集不改變未來,我認爲這是一個很好的測試,但也許不一定是單元測試

3

我已經在過去使用的測試這樣的 - 他們往往是非常有用的。

他們完全不是TDD。我發現我編寫這樣的測試時,我有更好的沒有TDD的代碼:Glue Code。你尤其可以看到數據提取(也就是「查詢數據庫中的這個(現有)數據,以這種方式格式化併發送給客戶端。」)你可以使用TDD字段格式化器或其他實用程序對象,但最終所有的事情對於這種類型的代碼,如果您爲給定(大)輸入產生給定(大)輸出。將代碼翻出來引入測試接縫是不值得的麻煩。

你得到一個單元測試套件中最重要的美德了這種測試的:如果你改變的基本功能共享的一塊,它打破了功能,你的測試將變爲紅色。

有人會說,這不是一個單元測試,因爲它不是孤立的。我不在乎。這種區別對我毫無幫助。這個測試爲我提供了保證系統正常工作。這讓我無需擔心就可以對代碼庫進行更改。