【问题标题】:How do I get started with Unit Testing? Total n00b question, thoughts? [duplicate]如何开始使用单元测试?总 n00b 问题,想法? [复制]
【发布时间】:2009-11-15 21:21:52
【问题描述】:

所以我开始编写一个包含我多年来编写和学习的有用方法的类库,我将从两个代码示例开始,然后提出我的具体问题:

我还想说明这不是其他一些问题的重复,“我从哪里开始单元测试问题。”

检查网络连接(不是互联网,只是网络)

    public static Boolean IsNetworkConnected()
    {
        Boolean ret = false;
        try
        {
            String HostName = System.Net.Dns.GetHostName();
            System.Net.IPHostEntry thisHost = System.Net.Dns.GetHostEntry(HostName);
            String thisIpAddr = thisHost.AddressList[0].ToString();

            ret = thisIpAddr != System.Net.IPAddress.Parse("127.0.0.1").ToString();
        }
        catch (Exception)
        {
            return false;
        }
        return ret;
    }

还有我的 IsValiEmail 方法(注意,我没有写正则表达式)

   public const String MatchEmailPattern = @"^(([\w-]+\.)+[\w-]+|([a-zA-Z]{1}|[\w-]{2,}))@"
         + @"((([0-1]?[0-9]{1,2}|25[0-5]|2[0-4][0-9])\.([0-1]?[0-9]{1,2}|25[0-5]|2[0-4][0-9])\."
         + @"([0-1]?[0-9]{1,2}|25[0-5]|2[0-4][0-9])\.([0-1]?[0-9]{1,2}|25[0-5]|2[0-4][0-9])){1}|"
         + @"([a-zA-Z]+[\w-]+\.)+[a-zA-Z]{2,4})$";


    public static bool IsValidEmail(string email)
    {
        if (email != null && email != string.Empty) 
            return Regex.IsMatch(email, MatchEmailPattern);
        else 
            return false;
    }

所以,我的问题是如何测试这些方法是否真正有效,显然我想开始对我的代码进行更多单元测试,这比这些快速示例更复杂。

如果可能,我想避免安装额外的工具/框架,但我愿意接受你的想法。

更新

应该这个新的单元测试代码(通过已经发布的链接)在哪里?在同一个程序集中?单独组装?

【问题讨论】:

    标签: c# .net unit-testing


    【解决方案1】:

    看看这本书。 The art of unit testing。 wiki 页面有很多很棒的资源。

    【讨论】:

    • +1。这是一本很棒的入门书。
    • +1 同意,这也是一本好书,一旦你掌握了基础知识,但又想获得一个可维护的测试套件。
    • roy osherove 对单元测试所做的任何事情都是黄金!
    【解决方案2】:

    NUnit 可能是最适合您需求的单元测试框架。看看他们的quick start 教程。

    【讨论】:

      【解决方案3】:

      您当然可以在没有框架的情况下进行单元测试——只需制作一个带有“测试”按钮的应用程序来运行您的测试。但是,我发现使用现有框架要好得多——它们的设置允许您轻松添加测试、查看成功/失败并自动运行测试。 Nunit 很好,或者真的,任何事情都可以。 MSTest 是可以的,如果你有一个版本的 Visual Studio 附带它。

      IsValidEmail 应该易于测试:使用 null、“”、有效电子邮件和无效电子邮件进行测试。然后戴上黑帽子,试着把有害垃圾偷偷溜进去:你能把它弄坏吗?但是由于这个函数只对它的输入进行操作,所以很容易测试。

      IsNetworkConnected 更难测试。您调用 GetHostName 和 GetHostEntry,您无法控制它们返回的内容。这使得检查所有可能的模式变得困难。单元测试对您施加了很大的压力,要求您将逻辑与数据检索分开。这里的一种选择是传入 IPHostEntry。当然,这会使您的异常捕获变得不那么有用,并将其中的一部分推送给调用者。

      您可以构建一个函数来为您调用 GetHostName 和 GetHostEntry,然后将委托传递给您的应用中的真实委托和测试中的虚假委托。在某些时候,该策略的成本高于其提供的价值——您必须自己做出判断,并且不要将精力浪费在不会产生价值的工作上。

      *Mock Objects 技术的追随者会注意到,您不应该模拟 GetHostName 和 GetHostEntry,因为您不拥有它们。如果您有一个模拟框架并希望使用它,请随意;只是不要误用他们的工具来遵循他们的设计方法。

      【讨论】:

        【解决方案4】:

        测试 IsNetworkConnected

        Sean McMillan 的回答是正确的,即测试 IsNetworkConnected 方法没有太多好处。它没有封装太多逻辑,只封装了不值得抽象的依赖项。但是,让我们假设由于某种原因对该方法进行单元测试很重要。以下是我将采取的方式:

          public static Boolean IsNetworkConnected(IIPAddressProvider ipAddressProvider) 
            { 
                Boolean ret = false; 
                try 
                {
                    IPAddress thisIpAddr = ipAddressProvider.GetIPAddressOFLocalHost();
                    ret = thisIpAddr.ToString() != System.Net.IPAddress.Parse("127.0.0.1").ToString(); 
                } 
                catch (Exception) 
                { 
                    return false; 
                } 
                return ret; 
            }   
        

        之后我会编写以下单元测试:

        • 从 IIPAddressProvider 的模拟中抛出异常
        • 从 IIPAddressProvider 的 mock 中返回 Null IPAddress
        • 从 IIPAddressProvider 的 mock 中返回 127.0.0.1
        • 从 IIPAddressProvider 的 mock 中返回 127.0.0.1 以外的不同 IPAddress

        测试 IsValidEmail

        为这种方法编写单元测试有一定的价值。您需要尝试积极、消极和边界测试用例。单元测试也是白盒测试的一种形式。从您的方法中可以清楚地看出,在进行单元测试时,您需要在方法和正则表达式的前提条件下进行练习。这里重要的是练习正则表达式。方法中的代码路径不多。在我看来,您需要编写上述测试用例场景。此外,在将其用于生产代码之前,应先使用一些第三方工具进行正则表达式验证。

        测试代码应该放在哪里

        在我看来,它应该始终位于与生产代码不同的程序集中。这是最好的选择。

        【讨论】:

          【解决方案5】:

          对于第一段代码,您需要考虑引入依赖反转,以便您可以模拟这些依赖关系并控制该方法何时返回 true 以及何时返回 false。

          第二个我会创建一些 NUnit 测试,每个测试都通过有效或无效的电子邮件,并验证返回的结果是否正确。为此,您可以为每封要测试的电子邮件创建一个测试,或者创建一个测试作为行测试(这在 NUnit 2.5+ 中是可能的)。

          至于测试应该放在哪里......好吧,它们可以放在同一个程序集中或另一个程序集中......目前最佳实践似乎是将它们放在单独的程序集中。如果您有一个名为 MyProject 的项目,那么您可以为您的单元测试创​​建一个名为 MyProject.Tests 的项目......作为额外的额外内容,最好将您的集成测试放在另一个名为 MyProject.Integration.Tests 的程序集中。

          【讨论】:

            【解决方案6】:

            一些额外的单元测试框架可以在here找到。

            【讨论】:

              【解决方案7】:

              您可以从 Junit 开始,并且可以使用模拟框架(如 mockito)来模拟涉及使用框架的代码部分。但是要使用模拟框架,您需要将使用外部框架的部分代码隔离到单独的类或接口中,并使用模拟框架来模拟外部依赖。

              同样在您的代码中,您使用“==”运算符进行字符串比较。


              ret = thisIpAddr != System.Net.IPAddress.Parse("127.0.0.1").ToString();

              但是你应该使用 "equals" 方法来比较字符串。

              【讨论】:

              • 这是一个 C# 问题,不是 Java 问题。
              • 哎呀,正如你所指出的,我完全错过了这不是 Java 问题。感谢指正
              【解决方案8】:

              同意 Asaph,NUnit 是使用最广泛的框架。话虽如此,如果您不想使用其他框架,VStudio Professional 确实内置了单元测试工具。
              我建议将您的测试放在同一个解决方案中,放在一个单独的项目中,这样您就不必将您的测试与您的程序集一起发布。
              您的第一种情况实际上对单元测试来说并不是最明显的,因为您的类具有难以复制的外部依赖项:显然,如果该类测试机器已连接,则结果本身将取决于机器。换句话说,如果测试失败,你不知道是因为你的代码,还是因为你的代码无法控制的东西。这些情况通常通过 Mocking 来处理,但如果您是单元测试新手,这可能不是最容易开始的事情!
              第二种情况是一个更好的起点;本质上,您将必须创建有效和无效地址,并将它们传递给您的方法,并检查结果是否应该是。

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 2010-11-20
                • 1970-01-01
                • 1970-01-01
                • 2021-11-21
                • 1970-01-01
                • 1970-01-01
                • 2011-08-22
                • 1970-01-01
                相关资源
                最近更新 更多