2011-05-30 90 views
1

我開始使用「(NUnit)」學習Unit testing。我知道這種類型的測試用於測試「類」,「功能」和「這些功能之間的相互作用」。Nunit和web應用程序

在我的情況下,我開發「asp.net web應用程序」。

  • 如何使用這個測試來測試我的 頁面(因爲它被認爲是一類 和使用的方法),並在其順序?我有三個層次:

    1. 接口層(每頁的.cs)。

    2. 數據訪問層(每個實體的類)(DAL)。

    3. 數據庫層(它包含與數據庫的連接,打開連接,關閉連接等)。

    4. 業務層(有時進行計算或一些單獨的邏輯)。

  • 如何測試連接數據庫的方法?

  • 如何確保我的測試不浪費時間?

回答

2

有單元和集成測試。單元測試正在測試單個組件/類/方法/函數以及它們之間的交互,但只有一個實際對象(被測系統SUT)和測試雙擊。測試雙打可以分爲殘根和嘲諷。存根提供準備好的測試數據給SUT。這樣你就可以將SUT與環境隔離開來。因此,您不必訪問數據庫,Web或wcf服務等,每次都有相同的輸入數據。 Mock用於驗證SUT是否按預期工作。 SUT調用模擬對象的方法,甚至不知道它不是真正的對象。然後你通過聲明模擬對象來驗證SUT的工作原理。你可以手工編寫存根和嘲諷,或使用許多嘲諷框架之一。其中之一是http://code.google.com/p/moq/

如果你想測試與集成測試的數據庫交互,並且通常比較困難。對於集成測試,您必須以衆所周知的狀態設置外部資源。

讓我們把你的圖層:

  1. 您將無法進行單元測試。 Page是緊密耦合到ASP.NET運行時。你應該儘量不要在代碼背後有太多的代碼。只需從後面的代碼中調用一些對象並測試這些對象即可。你可以看看MVC設計模式。如果您必須測試您的頁面您應該查看http://watin.org/。它自動化您的互聯網瀏覽器,點擊頁面上的按鈕並驗證該頁面顯示預期的結果。

  2. 這是集成測試。您將數據放入數據庫,然後將其讀回並比較結果。在測試之後或測試之前您必須將測試數據庫帶到衆所周知的狀態,以便測試是可重複的。我的建議是在測試運行之前設置數據庫,而不是在測試運行之後。這樣在測試失敗後,您將能夠檢查數據庫中的內容。

  3. 我真的不知道這與點號不同。 2.

  4. 而這是單元測試。在測試中創建對象,調用它的方法並驗證結果。

如何測試,使數據庫的連接在2點 被addresed如何不浪費時間的方法?這將帶有經驗。我沒有一般的建議,除此之外,不要測試沒有任何邏輯的屬性。

有關單元測試偉大的信息看這裏:

http://artofunittesting.com/

http://www.amazon.com/Test-Driven-Development-Kent-Beck/dp/0321146530

http://www.amazon.com/Growing-Object-Oriented-Software-Guided-Tests/dp/0321503627/ref=sr_1_2?ie=UTF8&s=books&qid=1306787051&sr=1-2

http://www.amazon.com/xUnit-Test-Patterns-Refactoring-Code/dp/0131495054/ref=sr_1_1?ie=UTF8&s=books&qid=1306787051&sr=1-1

編輯:

SUT,CUT - 正在測試的系統或類別。這就是你測試的。 測試雙打 - 來自特技雙打。他們在電影中做危險的場面,以至於真正的演員不需要。同樣在這裏。測試雙打替換測試中的真實對象,以便您可以在測試環境中隔離SUT/CUT。

讓我們看一下這個類


public class NotTestableParty 
{ 
    public bool ShouldStartPreparing() 
    { 
     if (DateTime.Now.Date == new DateTime(2011, 12, 31)) 
     { 
      Console.WriteLine("Prepare for party!"); 
      return true; 
     } 
     Console.WriteLine("Party is not today"); 
     return false; 
    } 
} 

你將如何測試這個類做的事情應該在除夕?你要做的是在新年前夕:)

現在看看修改黨的階級 短的例子:

public class Party 
    { 
     private IClock clock; 

     public Party(IClock clock) 
     { 
      this.clock = clock; 
     } 

     public bool ShouldStartPreparing() 
     { 
      if (clock.IsNewYearsEve()) 
      { 
       Console.WriteLine("Prepare for party!"); 
       return true; 
      } 
      Console.WriteLine("Party is not today"); 
      return false; 
     } 
    } 

    public interface IClock 
    { 
     bool IsNewYearsEve(); 
    } 

    public class AlwaysNewYearsEveClock : IClock 
    { 
     public bool IsNewYearsEve() 
     { 
      return true; 
     } 
    } 

現在測試您可以將假時鐘傳遞到黨的階級

 var party = new Party(new AlwaysNewYearsEveClock()); 
     Assert.That(party.ShouldStartPreparing(), Is.True); 

現在你知道你的派對班是否在除夕。 AlwaysNewYearsEveClock是一個存根。

現在看一下這個類:

public class UntestableCalculator 
    { 
     private Logger log = new Logger(); 

     public decimal Divide(decimal x, decimal y) 
     { 
      if (y == 0m) 
      { 
       log.Log("Don't divide by 0"); 
      } 

      return x/y; 
     } 
    } 

    public class Logger 
    { 
     public void Log(string message) 
     { 
      // .. do some logging 
     } 
    }

您將如何測試你的類記錄的消息。根據你在哪裏登錄它你必須檢查文件或數據庫或其他地方。這不是單元測試,而是集成測試。爲了單元測試你這樣做。

public class TestableCalculator 
    { 
     private ILogger log; 
     public TestableCalculator(ILogger logger) 
     { 
      log = logger; 
     } 
     public decimal Divide(decimal x, decimal y) 
     { 
      if (y == 0m) 
      { 
       log.Log("Don't divide by 0"); 
      } 
      return x/y; 
     } 
    } 

    public interface ILogger 
    { 
     void Log(string message); 
    } 
    public class FakeLogger : ILogger 
    { 
     public string LastLoggedMessage; 
     public void Log(string message) 
     { 
      LastLoggedMessage = message; 
     } 
    }

而且在測試您可以

var logger = new FakeLogger(); 
     var calculator = new TestableCalculator(logger); 
     try 
     { 
      calculator.Divide(10, 0); 
     } 
     catch (DivideByZeroException ex) 
     { 
      Assert.That(logger.LastLoggedMessage, Is.EqualTo("Don't divide by 0")); 
     }

這裏你斷定假冒記錄。假記錄器是模擬對象。

+0

非常感謝Peri,一些概念不清楚,你能解釋一下'Test doubles','stubs','mocks','SUT'是什麼意思..「我真的不知道它有什麼不同從第二點開始。「數據庫層直接使用數據庫,數據訪問層由每個實體的類(映射)組成,並使用數據庫層訪問數據並執行CRUD操作。 – 2011-05-30 21:30:01

+1

我編輯了我的asnwer。 – 2011-05-31 19:37:07

相關問題