.net 你用单元测试测试什么?

.net 你用单元测试测试什么?,.net,asp.net-mvc,unit-testing,tdd,.net,Asp.net Mvc,Unit Testing,Tdd,TDD这几天似乎是每个人都在谈论的东西,我自己也尝试过一些,但我不认为我有这个想法。我已经掌握了如何编写单元测试,但我不太清楚我的单元测试应该测试什么 如果我有一个返回数据列表的操作方法,我应该验证什么?只有视图名称是正确的,或者我也应该验证数据吗 如果我也要测试数据,我不是要写两次相同的代码吗?如果我使用相同的方法检索比较的数据,那么测试数据有什么用 我是否也应该测试添加/编辑数据的方法?如何验证记录是否已以正确的方式添加/编辑/删除 我知道这是相当多的大问题,但我并没有因为在互联网上阅读文章

TDD这几天似乎是每个人都在谈论的东西,我自己也尝试过一些,但我不认为我有这个想法。我已经掌握了如何编写单元测试,但我不太清楚我的单元测试应该测试什么

  • 如果我有一个返回数据列表的操作方法,我应该验证什么?只有视图名称是正确的,或者我也应该验证数据吗
  • 如果我也要测试数据,我不是要写两次相同的代码吗?如果我使用相同的方法检索比较的数据,那么测试数据有什么用
  • 我是否也应该测试添加/编辑数据的方法?如何验证记录是否已以正确的方式添加/编辑/删除
  • 我知道这是相当多的大问题,但我并没有因为在互联网上阅读文章而变得更聪明,因为他们似乎都关心如何测试,而不是什么

    举个例子——我有(或者,我将要写)一个GuestbookController,它具有查看、添加、编辑和删除帖子的方法。我需要测试什么?我该怎么做

  • 对于给定的输入或状态,您应该测试方法的返回值是否如您所期望的那样。如果您的方法返回大量类型的数据,您应该验证它们是否都正确
  • 在测试用例中使用一小部分样本数据。不要从磁盘或数据库加载任何内容。在测试中传入字符串或构造测试对象。考虑到这一小部分数据,您希望从您的方法中得到一个非常具体的结果,并将其与您的实际结果进行比较。您希望避免在测试中为您计算值的大量代码,因为这样您就必须为您的测试编写测试,以确保它们正常工作
  • 测试您编写的每一段代码。要添加记录(如果您的测试连接到测试数据库),只需查询最后插入的记录,或者比较前后记录的总数,并确保它增加1。如果您有一个mocking/stubing框架,那么您可以跳过数据库并断言将内容保存到数据库的方法已被调用。要测试编辑,只需再次从数据库中检索已编辑的记录,并断言该值已从其旧值更改。或者,如果是mock/stubing,则表示更改属性值的方法已正确调用

  • 但实际上,要为即将编写的代码编写一个测试。看着它失败。然后编写足够的代码使其通过。现在编写另一个测试并重复。

    我认为通过测试驱动开发/测试优先开发,您可以从单元测试中获得最大的好处。您应该首先编写测试,然后编写通过测试的代码。你应该先测试什么

    我发现从用户故事中编写测试非常有用。大多数时候,我从用户故事开始编写自上而下的风格测试。例如,我们的用户故事不包含这样的任务:

  • 用户保存订单时,视图应显示信息消息
  • 我通常从演示/控制器层为这个故事编写测试

      [Test]
        public void When_User_Save_Order_View_Should_Display_Information_Message()
        {
            using (mockRepository.Record())
            {
                repository.Save(order);
                view.Message= "Order saved successfully";
            }
    
            using (mockRepository.Playback())
            {
                presenter = new OrderSavePresenter(view, orderRepository);
                presenter.Save();
            }
        }
    

    然后我继续为我模仿或需要的每一个类编写测试。

    我不需要测试简单的东西,比如getter或setter。您不需要测试编译器本身,因此在调用setter时检查是否分配了值是没有用的

    一般来说,我尝试为具有实际代码的类的每个方法编写一个单元测试。这样,如果有人以后破坏了某个方法,它就会被捕获

    例如,有人更改了一个类似“addElements(String[]elements)”的方法。他们试图使用“for(inti=0;iunittesting(UT)!=测试驱动设计(TDD)” 这种混淆似乎相当普遍。UT完全是关于代码覆盖率。TDD关注的是特性。它们不是同一件事[对不起,Joel!]

    使用UT,您可以编写您想要的任何代码,然后返回并测试每个函数(即使是一些微不足道的函数)

    使用TDD,您可以选择下一个功能并首先为该功能编写测试。只为该功能编写测试,测试覆盖率与此无关。您首先编写测试以强制提前做出接口决策。然后编写代码以通过测试(请记住“可能工作的最简单的事情”)。然后根据所学内容重构代码。然后继续下一个功能(可能是在签入并重新运行所有单元测试之后)

    如果需要,使用TDD进行开发,然后返回并使用UT工具完成覆盖。如果您正在创建一个类库或其他API供开发人员使用,测试覆盖率越高越好;-)


    如果你只是编写一个应用程序来做五件特定的事情,仅TDD就足够了。

    测试你正在测试的模块接口的合同:

    • 如果客户机在使用您的类时希望有特定的行为,请对其进行测试
    • 如果您的类应该阻止客户机的某些行为(如其契约中所定义的),请测试它
    客户机是指使用您的类的代码。
    我所说的预期行为是指方法对返回值和对象状态的预期结果


    并将测试重点放在逻辑上(if、for、while等),因为像属性这样的简单东西在正常使用应用程序时失败的几率较小。

    这些是我发现对单元测试有用的通用准则:

    1) 识别边界对象(Win/WebForms、CustomControls等)

    2) 识别控制对象(业务层对象)

    3) 确保至少为边界对象调用的控件对象和公共方法编写单元测试


    通过这种方式,您可以确保您涵盖了应用程序的主要功能方面(功能),并且不会承担微测试的风险(除非您愿意)。

    在TDD中,您编写了应用程序的规范