如何测试一种方法(白盒测试)

本文关键字:一种 方法 白盒测试 测试 何测试 | 更新日期: 2023-09-27 18:20:36

这是我想要测试的方法

    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

我想我只要看看一个例子就知道了。

如何测试一种方法(白盒测试)

我建议学习单元测试。阅读MSDN上的这篇文章,并在谷歌上搜索如何编写单元测试。它们是测试单个代码单元的好方法,因此应该非常适合您的情况。

我还建议分离出与UI相关的代码,例如对MessageBox、其他UI元素和Console的调用;从您想要测试的代码中。这将使测试代码的逻辑和执行更加容易。

我同意Samuel Slade的回答——理解单元测试以及依赖注入和控制反转的原理肯定会有助于测试这样的系统。

我举了一个快速的例子,它可能不是最佳的,但至少展示了如何针对代码编写测试(以及一些依赖注入),以及如何测试代码是否有效。

我不得不做一些假设,但希望这是有道理的。如果你还有其他问题,请告诉我,我会尽力澄清的。

我希望这能有所帮助。祝你好运

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();
    }
}

您可以使用Microsoft Moles来模拟Console类的行为。看看下面的例子。

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);
        }
    }
}

在这里,我们截取对Console的调用,以便评估结果。有关Moles框架的更多信息,请参阅http://research.microsoft.com/en-us/projects/moles/.

然而,我同意其他人的观点,你应该阅读更多关于单元测试的内容,隔离你的依赖关系。。。我们可以用Moles测试你的代码,但IMHO,这不是最好的方法。