2012-01-18 153 views
3

這是我想測試如何測試方法(白盒測試)

private static void selectTop20Tags(Dictionary<string, int> list) 
    { 

     //Outputs the top 20 most common hashtags in descending order 
     foreach (KeyValuePair<string, int> pair in list.OrderByDescending(key => key.Value).Take(20)) 
     { 
      Console.WriteLine("{0}, {1}", pair.Key, pair.Value); 
     } 

    } 

我不知道我怎麼會測試這個方法,我整天都在研究它,並嘗試不同的東西但不能讓它工作。

我想包括一些代碼,如

#if TEST 
      if ((length of list don't know how you would do it) <= 20) 
      { 
       StreamWriter log2; 
       // appends file 
       log2 = File.AppendText("logOfTests.txt"); 
       // Writes to the file 
       log2.WriteLine("PASS"); 
       log2.WriteLine(); 

       // Closes the stream 
       log2.Close(); 
      } 
#endif 

我想我只需要看到一個例子,我會知道的。

+5

你不趕的NRE。你阻止它。 – 2012-01-18 17:51:31

+3

你的方法本身很難測試,因爲它使用'Console'。你可以通過一個'TextWriter'來代替,也許有一個使用'Console.Out'的重載? – 2012-01-18 17:53:14

+0

@Anony Pegram O.k也不確定是否有異常處理。 – Elliot678 2012-01-18 17:55:25

回答

4

我會建議學習單元測試。閱讀MSDN上的this文章,並在Google上搜索如何編寫單元測試。它們是測試各個代碼單元的好方法,因此應該適合您的情況。

我還建議分離出與用戶界面相關的代碼,例如調用MessageBox,其他UI元素和Console;來自你想測試的代碼。這將使測試代碼的邏輯和執行變得更容易。

2

我同意塞繆爾·斯萊德的答案 - 理解單元測試,也依賴注入和控制反轉一定會與測試這些系統幫助的原則。

我放在一起簡單的例子,這可能不是最優的,但至少說明了如何編寫針對代碼的測試(連同一些依賴注入),你如何可以測試,看看你的代碼工作。

我不得不作出一些假設,但我希望這是有道理的。如果您還有其他問題,請告訴我,我會盡力澄清。

我希望這會有所幫助。祝你好運!

CodeUnderTest

namespace CodeUnderTest 
{ 
    public interface IMessageBox 
    { 
     DialogResult Show(string message, string title, MessageBoxButtons buttons, MessageBoxIcon icon); 
    } 

    public class MessageBoxService : IMessageBox 
    { 
     public DialogResult Show(string message, string title, MessageBoxButtons buttons, MessageBoxIcon icon) 
     { 
      return MessageBox.Show(message, title, buttons, icon); 
     } 
    } 

    public class MessageBoxFake : IMessageBox 
    { 
     public DialogResult Show(string message, string title, MessageBoxButtons buttons, MessageBoxIcon icon) 
     { 
      return DialogResult.OK; 
     } 
    } 


    public class Repository 
    { 
     private readonly TextWriter _console; 
     private readonly IMessageBox _messageBox; 

     public Repository(TextWriter console, IMessageBox msgBox) 
     { 
      _console = console; 
      _messageBox = msgBox; 
     } 

     public void WriteTop20Tags(Dictionary<string, int> list) 
     { 
      selectTop20Tags(list, _console, _messageBox); 
     } 

     private static void selectTop20Tags(Dictionary<string, int> list, TextWriter _console, IMessageBox _messageBox) 
     { 
      try 
      { 
       //Outputs the top 20 most common hashtags in descending order 
       foreach (KeyValuePair<string, int> pair in list.OrderByDescending(key => key.Value).Take(20)) 
       { 
        _console.WriteLine("{0}, {1}", pair.Key, pair.Value); 
       } 
      } 
      catch (NullReferenceException e) 
      { 
       _messageBox.Show(e.Message, "Error detected", MessageBoxButtons.OK, MessageBoxIcon.Error); 
      } 
     } 
    } 
} 

單元測試

class When_I_Pass_A_Valid_Dictionary_I_Should_See_My_List_Output_To_My_Writer 
{ 
    static void Main(string[] args) 
    { 
     //Arrange 
     //dummy data 
     var list = new Dictionary<string, int>() 
     { 
      {"a", 100}, 
      {"b", 200}, 
      {"c", 300}, 
      {"d", 400} 
     }; 

     using (StringWriter sw = new StringWriter()) 
     { 
      //Act 
      //var repo = new CodeUnderTest.Repository(Console.Out, new CodeUnderTest.MessageBoxFake()); 
      var repo = new CodeUnderTest.Repository(sw, new CodeUnderTest.MessageBoxFake()); 
      repo.WriteTop20Tags(list); 

      //Assert 
      //expect my writer has contents 
      if (sw.ToString().Length > 0) 
      { 
       Console.WriteLine("success"); 
      } 
      else 
      { 
       Console.WriteLine("failed -- string writer was empty!"); 
      } 
     } 

     Console.ReadLine(); 
    } 
} 
1

您可以使用Microsoft摩爾模擬控制檯類的行爲。看下面的例子。

namespace TestesGerais 
{ 
    public class MyClass 
    { 
     public static void selectTop20Tags(Dictionary<string, int> list) 
     { 
      //Outputs the top 20 most common hashtags in descending order 
      foreach (KeyValuePair<string, int> pair in list.OrderByDescending(key => key.Value).Take(20)) 
      { 
       Console.WriteLine("{0}, {1}", pair.Key, pair.Value); 
      } 
     } 
    } 

    [TestClass] 
    public class UnitTest6 
    { 
     [TestMethod] 
     [HostType("Moles")] 
     public void TestMethod1() 
     { 
      // Arrange 
      var actual = new List<string>(); 
      MConsole.WriteLineStringObjectObject = (s, o1, o2) => actual.Add(string.Format(s, o1, o2)); 
      var dic = new Dictionary<string, int>(); 
      for (int i = 1; i < 30; i++) 
       dic.Add(string.Format("String{0}", i), i); 
      var expected = new List<string>(); 
      expected.AddRange(new[] { "String29, 29", "String28, 28", "String27, 27", "String26, 26", "String25, 25", "String24, 24", "String23, 23", "String22, 22", "String21, 21", "String20, 20", "String19, 19", "String18, 18", "String17, 17", "String16, 16", "String15, 15", "String14, 14", "String13, 13", "String12, 12", "String11, 11", "String10, 10" }); 
      // Act 
      MyClass.selectTop20Tags(dic); 
      // Assert 
      CollectionAssert.AreEqual(expected, actual); 
     } 
    } 
} 

在這裏,我們攔截對控制檯所做的調用,以便我們可以評估結果。有關Moles框架的更多信息,請參閱http://research.microsoft.com/en-us/projects/moles/

但是,我同意其他人,你應該閱讀更多關於單元測試,隔離你的依賴......我們可以測試痣你的代碼,但恕我直言,這不是最好的辦法。

+0

+1 - 我聽說過痣,但從未使用它。看起來很有趣,但我同意你的看法 - 這可能不是最好的方法。但它對於一些棘手的遺留代碼看起來很有用。 – 2012-01-18 19:08:50