2009-09-18 38 views
1

我是一個控件開發人員和單元測試的相對新手。幾乎每天,我都會對由於UI交互而無法測試控件的態度進行抗爭。我正在製作一個演示控件,以表明如果控件設計爲可測試的,可以顯着減少手動測試。目前我有50%的邏輯覆蓋率,但是如果我能找到一種方法來測試一些更復雜的部分,我認爲我可以將其提高到75%或更高。你如何測試產生複雜對象圖的方法?

例如,我有一個具有描述控件狀態的屬性的類以及一個生成由多個段組成的WPF對象的方法。實施看起來是這樣的:

internal PathGeometry CreateOuterGeometry() 
{ 
    double arcRadius = OuterCoordinates.Radius; 
    double sweepAngle = OuterCoordinates.SweepAngle; 
    ArcSegment outerArc = new ArcSegment(...); 

    LineSegment arcEndToCenter = new LineSegment(...); 

    PathFigure fig = new PathFigure(); 
    // configure figure and add segments... 

    PathGeometry outerGeometry = new PathGeometry(); 
    outerGeometry.Figures.Add(fig); 
    return outerGeometry; 
} 

我有一些其他的方法,像這樣的佔未覆蓋的代碼幾百塊,一個額外的25%的覆蓋率。我原本打算測試這些方法,但拒絕了這個概念。我仍然是一個單元測試的新手,我能想到的唯一的方法來測試代碼將是幾種方法是這樣的:

void CreateOuterGeometry_AngleIsSmall_ArcSegmentIsCorrect() 
{ 
    ClassUnderTest classUnderTest = new ClassUnderTest(); 
    // configure the class under test... 
    ArcSegment expectedArc = // generate expected Arc... 

    PathGeometry geometry = classUnderTest.CreateOuterGeometry() 
    ArcSegment arc = geometry.Figures.Segments[0]; 

    Assert.AreEqual(expectedArc, arc) 
} 

測試本身看起來不錯;我會爲每個預期的分段寫一個。但我有一些問題:

  • 我需要測試來驗證「是否第一段ArcSegment?理論上測試測試這個,但不應該每個測試只測試一件事情?這聽起來像兩件事。
  • 該控件至少有六個計算案例和四個邊緣案例;這意味着對於每種方法我至少需要十次測試。
  • 在開發過程中,我改變了多次生成各種幾何圖形的方式。這會導致我不得不重寫所有的測試。

第一個問題讓我停頓了一下,因爲它好像可能會誇大測試的次數。我想我可能不得不測試像「有x個分段嗎?」和「段n是正確的類型?」,但現在我已經想得更多了,我發現方法中沒有分支邏輯,所以我只需要做一次這些測試。第二個問題讓我更加確信測試會有很多努力。這似乎是不可避免的。第三個問題複合了前兩個問題。每次我改變計算幾何圖形的方式時,我都必須編輯大約40次測試,以使它們尊重新的邏輯。這也包括添加或刪除測試,如果段添加或刪除。

由於這三個問題,我選擇編寫一個應用程序和手動測試計劃,將控件置於所有有趣的狀態,並要求用戶驗證它看起來是一種特定的方式。這是錯的嗎?我是否高估了編寫單元測試的努力?有沒有其他方法來測試這可能更容易? (我目前正在學習模擬和存根;好像需要對設計進行一些重構,並最終付出大致的努力)。

+0

究竟是什麼問題?這看起來更像是對單元測試的個人挫折的冗長討論。 – 2009-09-18 15:09:15

+0

問題是帶有問號的部分:「?是這個錯誤我是高估參與編寫單元測試的工作是否有測試此的另一種方式,可能是更容易?」 – OwenP 2009-09-18 15:11:00

回答

2

使用依賴注入和模擬。

爲ArcSegmentFactory,LineSegmentFactory等創建接口,並將模擬工廠傳遞給您的類。這樣,你將隔離特定於該對象的邏輯(這應該使測試更容易),並且不會取決於其他對象的邏輯。

關於測試的內容:你應該測試什麼是重要的。你可能有一個你想完成任務的時間表,你可能無法測試每一件事情。 確定需要測試的東西的優先級,並按優先級順序測試(考慮測試需要多少時間)。此外,當你已經做了一些測試,它變得更容易爲其他的東西新的考驗,我實在不明白的問題創造了同一個類中的多個測試...

關於修改,這就是測試的目的:允許你改變,並且不會真的擔心你的改變會給世界帶來混亂。

-1

教科書的方法來做到這將是移動所有的業務邏輯,其通過在GUI中的1線的方法稱爲庫或控制器。這樣你可以單元測試控制器或庫而不用處理GUI。

+0

這就是我已經在做的事情。這個問題是關於測試提取邏輯的一個特定部分。 – OwenP 2009-09-18 15:42:57

+0

我看到,這方面的問題很不明確。 至於如何測試複雜的東西。隨機生成是一種方法。另一種方法是研究這個問題,並用特定的邊緣案例編寫好的測試用例。測試很難,這就是爲什麼業界有龐大的質量保證團隊。 – tster 2009-09-18 15:48:06

0

您可能會嘗試編寫一個控件生成工具來生成隨機控制圖並對其進行測試。這可能會產生一些你可能沒有想到的數據點。

0

在我們的項目中,我們使用JUnit來執行不嚴格地說是單元測試的測試。例如,我們發現,掛鉤一個空白數據庫並將Hibernate生成的自動模式(一種對象關係映射工具)與我們的測試數據庫的實際模式進行比較是有幫助的;這有助於我們用錯誤的數據庫映射捕捉很多問題。但總的來說......你只應該在一個給定的測試方法上測試一種方法。這並不意味着你不能對它進行多重斷言來檢查對象的各種屬性。

0

我的方法是將圖轉換爲一個字符串(每行一個段)並將此字符串與預期結果進行比較。

如果你改變你的代碼的東西,測試將開始失敗,但所有你需要做的是檢查故障是在正確的地方。您的IDE應爲此提供並排差異。

當您確信新輸出正確時,只需將其複製到舊的預期結果上即可。這將確保不會忽視錯誤(至少不會被忽略),測試仍然很簡單,而且很快就會修復。

接下來,如果你有共同的路徑部分,那麼你可以把它們放到單獨的字符串,並建立從這些部件測試的預期結果。這可以讓你避免重複自己(如果公共部分發生變化,你只需要爲所有測試更新一個地方)。

0

如果我正確理解你的例子,你試圖找到一種方法來測試一大堆繪製操作是否產生給定的結果。您可以生成一組預期圖像(已驗證的「良好」圖像的快照),並創建單元測試,這些單元測試使用繪製操作創建相同的一組圖像,並將結果與圖像比較。這將允許您自動執行圖形操作的測試,這正是我理解您的問題所在。

+0

這幾乎是我所說的一些事情。它具有分辨率問題,偶爾會有小的細節逃脫圖像分析。我們仍然會進行手動驗證,但是我認爲測試我將正確的數字傳遞給繪製事物的代碼會有很大的幫助。如果那個部分搞砸了,那是不可控的。 – OwenP 2009-09-18 15:46:10