您如何确定哪种测试最能代表您想要创建的功能?

时间:2010-02-18 18:59:49

标签: tdd

维基百科上的测试驱动开发说,首先开发一个因为该功能不存在而失败的测试。然后构建代码以通过测试。这个测试是什么样的?

如何确定哪种测试最能代表您想要创建的功能?

有人能举个例子吗?

如果我为Web应用程序创建一个注销按钮功能,那么测试是否会在页面上找到按钮?或者什么?

我听说测试驱动很适合回归测试,我只是不知道如何开始将它与我的工作集成。

6 个答案:

答案 0 :(得分:2)

很明显,有些领域比其他领域更适合TDD,而且运行前端开发是我发现难以进行TDD的领域之一。但是你可以。

您可以使用WATINWebAii进行此类测试。然后你可以:

  • 编写一个测试,检查页面上是否存在按钮...失败,然后实现,然后传递
  • 编写一个单击按钮的测试,检查前端要更改的内容,使其失败,实现功能并通过测试。

但通常你会测试你所做行动背后的逻辑。您将在您的身份验证服务上测试注销功能,该功能由您在webforms中的eventhandler调用,或者在MVC中调用控制器操作。

答案 1 :(得分:1)

这个测试是什么样的?

测试有3个部分。

  1. 它设置了一个上下文
  2. 执行操作
  3. 它断言行动做了它应该做的事情
  4. 您如何确定哪种测试最能代表您要创建的功能? 测试不是基于功能(除非您在谈论像cucumber这样的高级框架),它们基于代码的“单元”。通常,单元是一个函数,您将编写多个测试来断言该函数的所有可能行为都正常工作。

    有人可以举个例子吗? 它根据您使用的框架而有所不同。就个人而言,我最喜欢的是shoulda,它是ruby Test :: Unit框架的扩展

    以下是自述文件中的一个例子。对于像这样的BDD框架,上下文设置发生在它自己的块

    class UserTest < Test::Unit::TestCase
        context "A User instance" do
          setup do
            @user = User.find(:first)
          end
    
          should "return its full name" do
            assert_equal 'John Doe', @user.full_name
          end
    
          context "with a profile" do
            setup do
              @user.profile = Profile.find(:first)
            end
    
            should "return true when sent #has_profile?" do
              assert @user.has_profile?
            end
          end
        end
      end
    

    就像我为Web应用程序创建一个注销按钮功能一样,那么测试是否会在页面上找到按钮?或者什么?

    有三种主要类型的测试。

    首先你有单元测试(这是人们通常认为你在谈论TDD测试时所说的)。单元测试测试单个工作单元而不测试任何其他单元。这意味着如果您的方法通常访问数据库,则确保在测试期间它实际上没有访问该数据库(使用称为“mocking”的技术)。

    接下来,您进行了集成测试。集成测试通常涉及与基础架构的交互,并且是更“完整堆栈”测试。因此,从您的顶级API,如果您有一个insert方法,您将完成整个插入,然后在数据库中测试结果数据。因为在这些类型的测试中有更多的设置,所以它们不应该真正从开发者机器运行(最好在构建服务器上自动化这些)

    最后,您进行了UI测试。这是最不可靠的,并且需要像Selenium或Waitr这样的UI脚本框架来自动点击您的UI。不要因为这种测试而疯狂,因为这些测试非常脆弱(一个小小的改变可能会破坏它们),并且它们无论如何都不会捕捉到整类问题(比如样式)。

答案 2 :(得分:0)

单元测试将调用注销函数并验证预期结果是否已发生(例如,用户登录记录已结束)

单击注销按钮更像是验收测试 - 这也是一件好事,而且(在我看来)完全在TDD的范围内,但它测试了两个功能:按钮,以及由此产生的动作

答案 3 :(得分:0)

测试将确保在执行注销功能时,用户已成功注销。通常会使用单元测试框架,例如NUnit或MSTest(用于.Net的东西)。

由于在Web服务器上执行服务器代码通常需要的所有上下文信息,因此Web应用程序难以进行单元测试。但是,一个典型示例将模拟该信息并调用注销逻辑,然后验证是否返回了正确的结果。一个松散的例子是使用NUnit和Moq的MVC类型测试:

[Test]
public void LogoutActionShouldLogTheUserOut()
{
    var mockController = new Mock<HomeController>() { CallBase = true };
    var result = mockController.Object.Logout() as ViewResult;

    Assert.That(result.ViewName == "LogoutSuccess", 
                "Logout function did not return logout view!");
}

这是一个松散的例子,因为它只是测试返回了“LogoutSuccess”视图,而不是执行了任何注销逻辑。在一个真正的测试中,我会模拟一个HttpContext并确保会话被清除或者其他什么,但我只是复制了它;)

单元测试不会测试UI元素是否正确连接到事件处理程序。如果你想确保整个应用程序从上到下工作,这将被称为集成测试,你会使用除了单元测试之外的东西。诸如Selenium之类的工具通常用于Web集成测试,而宏录制程序通常用于桌面应用程序。

答案 4 :(得分:0)

这取决于您使用的平台,以了解测试的显示方式。 ASP.NET WebForms中的TDD比ASP.NET MVC要困难得多,因为在WebForms中模拟HTTP环境以获得Session,Application,ViewState等预期状态而非ASP.NET MVC非常困难。

典型的测试是围绕Arrange Act Assert构建的。

// Arrange
... setup needed elements for this atomic test

// Act
... set values and/or call methods

// Assert
... test a single expected outcome

除非您告诉我们您计划编写的平台,否则很难给出更深入的示例。请提供更多信息。

答案 5 :(得分:0)

假设我想创建一个将一个函数添加到一个数字的函数(非常简单的例子)。

首先,写一个说f(10) == 11的测试,然后做一个说f(10) != 10的测试。然后编写一个通过这些测试的函数。如果您意识到该功能需要更多功能,请添加更多测试。