2014-09-05 76 views
0

最近我想通過開發一個真實的東西來學習TDD,所以我決定使用簡單的數據打包器/解包器。在紙上設計完成後,一切看起來不錯,但是當我嘗試編碼時,我意識到我不知道如何測試它,所以在TDD中 - 如何做任何事情。在TDD中測試兩路依賴類

我有兩個類:ArchiveReaderArchiveWriter。問題是,當我用ArchiveWriter保存某些東西時,如果沒有它,我不能正確測試它,我不得不逐一比較輸出字節,我認爲這不是個好主意 - 稍後可能會發生較小的不相關的更改。 ArchiveReader測試也需要閱讀,所以我必須使用ArchiveWriter來製作測試包。

TDD是否在這方面失敗?有沒有任何方法來測試這種情況?

+1

如果我正在測試讀取或寫出一些字節的東西,我想檢查它是字節爲字節的完美。 – 2014-09-08 13:26:11

回答

5

如果您已經有兩個類的代碼,那麼它不是真正TDD,因爲測試沒有驅動設計

您仍然可以測試您的代碼,具體取決於如何處理這些類的依賴關係。例如,如果ArchiveWriter類寫入流,則可以將其輸出到內存流而不是文件流,作者不應該關心它是什麼樣的流,而是可以讓您比較寫入方法。

同樣適用於ArchiveReader類,如果它從流中讀取,則它可以是存儲器流。

至於你關於ArchiveWriterArchiveReader的問題相互依賴於驗證對方,我不認爲這是一定的問題。儘管能夠獨立測試兩者是理想的,但是沒有規定單元測試只能測試一個類。

對於這些類,在生產中,它們可能總是相互使用,如果以後再讀不出來,那麼寫一個檔案是毫無意義的。

+0

即使沒有代碼,聽起來這些類的界面在編寫測試之前就已經確定了,所以仍然沒有足夠的空間來編寫測試來通知設計。如果你開始編寫一個測試來驗證讀取和寫入檔案的行爲,你最終會得到這兩個類還是一個不同的(可能更好的)接口? – Jonah 2014-09-05 21:02:36

+0

我還沒有做任何代碼。也許我錯過了一點,但我沒有看到檢查流內容和文件內容有什麼區別,在我看來困難是相同的 - 它仍然像逐字節操作。你是在暗示這條道路?那麼怎麼處理髮生在某些特定事件中的設計的少許更改,標題中的額外字段等等。爲了滿足要求,進行測試以滿足要求?我認爲在TDD中只是添加測試既不刪除也不執行它們。 – gecio 2014-09-06 19:59:24

+1

在測試中,您嘗試使用一個邏輯斷言(對於'ArchiveWriter'),測試可能是結果具有正確的標頭,另一個測試可能是正確的元數據,另一個測試可能是它具有正確的文件名另一個可能是檔案裏面有一個md5散列用於驗證等等。如果你能想出10個不同的東西需要對代碼進行斷言,那麼有10個或更多的測試並不是不合理的。事實上,您可能有更多測試非成功案例。進行具體的測試,並首先編寫退化案例。 – Matthew 2014-09-06 21:48:10

1

TDD幾乎約爲單元測試。單元測試是關於完全隔離的獨立工作單元的測試。簡而言之,就是測試某些公開方法的某些邏輯,並假定所有依賴和環境都是僞造的。

在你的例子中,它意味着如果你想單元測試ArchiveReader或者ArchiveWriter,首先你應該將它與真正的I/O隔離並且測試邏輯(C#/ java/...「你的代碼」)。

如果您以複雜的方式測試您的應用程序,那麼主要是關於集成測試。因此,您的斷言需要抵制ArchiveWriter產生的文件。

在進入TDD之前,我建議您閱讀至少一本關於單元測試的好書。羅伊·奧謝羅夫的書對我來說非常完美。

2

我開發了這種類型的代碼,它有兩個類或方法,必須使用TDD一直讀取和寫入相同的二進制格式。

你提到檢查輸出逐字節。我更喜歡輸入代碼的類似測試,因爲雖然我必須手工製作二進制輸入,但輸入代碼的行爲通常更容易檢查。它將委託給方法或創建對象,您可以按照通常的方式正確地檢查它。

我也有對稱性測試。這些代碼使用輸出代碼創建二進制表示,然後讓輸入代碼從該二進制表示中創建一組新的對象。測試檢查原始對象和新對象是否相同。這些測試很容易編寫,並在失敗時生成有用的duagnostics。

現在有些人會說哦,但是你沒有進行單元測試,因爲你的對稱測試測試了輸出代碼和輸入代碼;你正在做集成測試因此做錯了。這不應該擔心你。在進行集成測試之前,單元測試和集成測試之間存在精細劃分,並且所有內容都必須通過單元測試進行測試的想法是錯誤的。實際上,幾乎沒有代碼被完全隔離地測試;大多數測試代碼使用其他類,即使它們的基礎知識如StringHashMap。將測試視爲在完美單元測試和完美集成測試之間的連續體,更偏向於所有代碼在單元測試結束時進行測試,而不是在某些代碼不這樣做的時候過於擔心。