unit-testing - 单元测试示例?

标签 unit-testing language-agnostic

关闭。这个问题不满足Stack Overflow guidelines .它目前不接受答案。












想改善这个问题吗?更新问题,使其成为 on-topic对于堆栈溢出。

4年前关闭。




Improve this question




我理解测试驱动开发背后的想法,首先编写测试,然后针对测试编写代码,直到成功。在我的工作流程中,它对我来说还没有走到一起。

你能给我一些例子,说明单元测试可以在前端或后端 Web 开发环境中使用吗?

最佳答案

你没有指定一种语言,所以我会尽量保持这种通用性。不过这会很难,因为用实际代码表达概念要容易得多。

单元测试一开始可能有点困惑。有时并不总是清楚如何测试某些东西,或者测试的目的是什么。

我喜欢将单元测试视为测试小段代码的一种方式。

我使用单元测试的第一个地方是验证某些方法是否像我期望的那样适用于所有情况。我最近刚刚为我的网站编写了一个电话号码验证方法。我接受来自 123-555-1212、(123) 555-1212 等的任何输入。我想确保我的验证方法适用于所有可能的格式。如果没有单元测试,我将被迫手动输入每种不同的格式,并检查表单是否正确发布。这是非常乏味且容易出错的。稍后,如果有人对电话验证代码进行了更改,如果我们可以轻松检查以确保没有其他问题,那就太好了。 (也许我们添加了对国家/地区代码的支持)。所以,这是一个简单的例子:

public class PhoneValidator
{
    public bool IsValid(string phone)
    {
          return UseSomeRegExToTestPhone(phone);
    }
}

我可以写一个这样的单元测试:

public void TestPhoneValidator()
{
     string goodPhone = "(123) 555-1212";
     string badPhone = "555 12"

     PhoneValidator validator = new PhoneValidator();

     Assert.IsTrue(validator.IsValid(goodPhone));
     Assert.IsFalse(validator.IsValid(badPhone));
}

这 2 行 Assert 将验证从 IsValid() 返回的值分别是真还是假。

在现实世界中,您可能会遇到很多好的和坏的电话号码示例。我有大约 30 个电话号码供我测试。以后只要运行这个单元测试就会告诉你你的手机验证逻辑是否有问题。

我们还可以使用单元测试来模拟我们无法控制的事情。

单元测试应该独立于任何外部资源运行。您的测试不应依赖于存在的数据库或可用的 Web 服务。因此,相反,我们模拟这些资源,以便我们可以控制它们返回的内容。例如,在我的应用程序中,我无法在注册时模拟被拒绝的信用卡。银行可能不希望我提交数千张不良信用卡只是为了确保我的错误处理代码正确无误。这是一些示例代码:

public class AccountServices
{
   private IBankWebService _webService = new BankWebService();

   public string RegisterUser(string username, string creditCard)
   {
        AddUserToDatabase(username);

        bool success = _webService.BillUser(creditCard);

        if (success == false)
           return "Your credit card was declined"
        else
           return "Success!"

    }
}

这是单元测试非常困惑且不明显的地方。这种方法的测试应该做什么?首先,如果我们可以检查是否计费失败,是否返回了相应的错误消息,那就太好了。事实证明,通过使用模拟,有一种方法。我们使用所谓的控制反转。现在,AccountServices() 负责创建 BankWebService 对象。让我们让这个类的调用者提供它:

public class AccountServices
{
   public AccountServices(IBankWebService webService)
   {
       _webService = webService;
   }

   private IBankWebService _webService;

   public string RegisterUser(string username, string creditCard)
   {
        AddUserToDatabase(username);

        bool success = _webService.BillUser(creditCard);

        if (success == false)
             return "Your credit card was declined"
        else
           return "Success!"

    }
}  

因为调用者负责创建 BankWebService 对象,所以我们的单元测试可以创建一个假的:

public class FakeBankWebService : IBankWebService
{
    public bool BillUser(string creditCard)
    {
        return false; // our fake object always says billing failed
    }
}

public void TestUserIsRemoved()
{
    IBankWebService fakeBank = FakeBankWebService();

    AccountServices services = new AccountServices(fakeBank);

    string registrationResult = services.RegisterUser("test_username");

    Assert.AreEqual("Your credit card was declined", registrationResult);
}

通过使用该假对象,无论何时调用我们银行的 BillUser(),我们的假对象将始终返回 false。我们的单元测试现在验证如果对银行的调用失败,RegisterUser() 将返回正确的错误消息。

假设有一天您进行了一些更改,并且出现了一个错误:

public string RegisterUser(string username, string creditCard)
{
    AddUserToDatabase(username);

    bool success = _webService.BillUser(creditCard);

    if (success) // IT'S BACKWARDS NOW
        return "Your credit card was declined"
    else
        return "Success!"

}

现在,当您的计费失败时,您的 RegisterUser() 方法将返回“成功!”。幸运的是,您已经编写了单元测试。该单元测试现在将失败,因为它不再返回“您的信用卡被拒绝”。

以这种方式找到错误比手动填写您的注册表单以错误的信用卡来检查错误消息要容易和快捷得多。

一旦您查看了不同的模拟框架,您就可以做更强大的事情。你可以验证你的假方法被调用了,你可以验证一个方法被调用的次数,你可以验证调用方法的参数等等。

我想一旦你理解了这 2 个想法,你就会明白为你的项目编写大量的单元测试已经足够了。

如果您告诉我们您使用的语言,我们可以更好地指导您。

我希望这有帮助。如果其中有些令人困惑,我深表歉意。如果有什么不合理的,我会清理它。

关于unit-testing - 单元测试示例?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4910138/

相关文章:

unit-testing - 运行单个Grails单元/集成测试将在Intellij上运行所有测试

c++ - C++ 中的单元测试和模拟小型类值类

r - 如何在 R 中编写包测试以查看是否正确抛出警告?

language-agnostic - 检测 rtf 标记中的多字节和汉字

algorithm - 生成填字游戏的高效算法(纽约时报的风格)

algorithm - 使用哈希查找 float 数组的模式

javascript - 让 Jasmine 等待异步函数完成

ios - 如何从 UI 测试中的标签检索变量数据

language-agnostic - 您是否曾经限制自己只使用语言功能的子集?

language-agnostic - Nagle 算法和延迟 ACK 是否影响 TCP 连接设置?