【问题标题】:Applying TDD when the application is 100% CRUD当应用程序是 100% CRUD 时应用 TDD
【发布时间】:2009-05-09 01:39:14
【问题描述】:

我经常遇到这个问题,但我不知道如何克服这个障碍。我真的很想开始学习和应用测试驱动开发(或 BDD 或其他),但似乎我想要应用的每个应用程序几乎只是标准数据库 CRUD 的东西,我不确定如何去应用它。除了持久化到数据库之外,这些对象几乎什么都不做。没有需要测试的复杂逻辑。有一个网关,我最终需要测试第 3 方服务,但我想先完成应用的核心。

每当我尝试编写测试时,我最终只会测试我可能不应该首先测试的基本东西(例如 getter/setter),但看起来对象没有其他任何东西。我想我可以测试持久性,但这对我来说似乎永远不对,因为你不应该真正访问数据库,但是如果你模拟它,那么你真的没有测试任何东西,因为你控制了吐回的数据;就像我看过很多例子,其中有一个模拟存储库,它通过循环和创建已知值列表来模拟数据库,并且测试验证“存储库”可以拉回某个值......我是没有看到这样的测试的意义,因为“存储库”当然会返回那个值;它在课堂上是硬编码的!好吧,我从纯 TDD 的角度来看它(即,您需要进行测试,说明您的存储库需要 GetCustomerByName 方法或其他任何方法,然后才能编写方法本身),但这似乎无缘无故地遵循教条“方式”——除了证明方法的合理性之外,测试似乎没有做任何有用的事情。

我是不是想错了?

例如运行工厂联系人管理应用程序。我们有联系人,假设我们可以向联系人发送消息。因此,我们有两个实体:ContactMessage,每个都有共同的属性(例如,名字、姓氏、联系人的电子邮件以及消息的主题和正文和日期)。如果这些对象都没有任何实际行为或需要执行任何逻辑,那么在设计这样的应用程序时如何应用 TDD?该应用程序的唯一目的基本上是拉出联系人列表并将其显示在页面上,显示表单以发送消息等。我在这里没有看到任何有用的测试——我可以想到一些测试,但它们几乎是为了说“看,我有测试!”而进行的测试。而不是实际测试某种逻辑(虽然 Ruby on Rails 很好地利用了它,但我并不认为测试验证是一个“有用的”测试,因为它应该是框架为你处理的事情)

【问题讨论】:

  • 我只想说...我喜欢这个问题的标题。
  • 这是一个很好的问题。我相信大多数时候,当我们听到关于 TDD 成本合理性的争论时,他们确实是专门谈论类似 CRUD 的应用程序。
  • 这也是我注意到的。我想要使用 TDD(不一定是 TDD,而是测试),但是当应用程序只需要提取数据时,我永远无法想到要测试什么 - 不过,我在这里得到了一些很好的回复。

标签: tdd


【解决方案1】:

“该应用的唯一目的基本上是拉一个联系人列表”

好的。测试一下。 “拉”是什么意思?这听起来像是“逻辑”。

"在页面上显示它们"

好的。测试一下。显示正确的?那里的一切?

" 显示发送消息的表单,"

好的。测试一下。正确的领域?输入的验证都有效吗?

”之类的。”

好的。测试一下。查询是否有效?找到正确的数据?显示正确的数据?验证输入?为无效输入生成正确的错误消息?

【讨论】:

  • @S.Lott 您在这里描述的是在单元级别上的更多行为类型测试,而不是 TDD。我同意你提到的每个领域都是单元测试的主要候选人。
  • 如果他们以可测试的形式定义“拉”,那么测试驱动“拉”的设计。如果他们根据一些可测试的结果来定义“在页面上显示它们”,那么测试驱动“显示”的设计。这对我来说就像是 TDD。
  • 我同意这一点,只要测试驱动设计而不是测试行为。
  • @DavidYancey 当然,您正在测试行为。这就是正在设计的东西,一个对象(以及总体而言,一个对象系统)的行为方式。 TDD 通过指定所述行为的接口来使用对所需行为的测试来驱动设计。
  • 在谈到 TDD 时,他们说在编写测试之前永远不要写一行代码。那么我应该如何为 CRUD 应用程序编写测试呢?因为 MVC 框架只是从视图输入中填充模型。那么我应该如何测试呢?
【解决方案2】:

我现在正在开发一个纯 CRUD 应用程序 但是我看到了单元测试用例的很多好处(注意——我没有说 TDD)

我先编写代码,然后然后编写测试用例——但永远不要太分开——尽管如此

我还测试了 CRUD 操作 - 数据库的持久性。

当我完成持久性 - 并转到 UI 层 - 我将相当有信心我的服务\持久层是好的 - 然后我可以在那一刻独自专注于 UI。

所以恕我直言——TDD\单元测试总是有好处的(不管你怎么称呼它,这取决于你对它的感觉有多极端)——即使对于 CRUD 应用程序也是如此 您只需要为您的应用找到正确的策略

只要使用常识......你会没事的。

【讨论】:

    【解决方案3】:

    我觉得我们将 TDD 与单元测试混淆了。

    单元测试是测试行为单元的特定测试。这些测试通常包含在集成构建中。 S.Lott 为这些类型的测试描述了一些优秀的候选者。

    TDD 用于设计。我经常发现我在使用 TDD 时编写的测试不会被丢弃或演变成单元测试。这背后的原因是,当我在做 TDD 时,我正在测试我的设计,而我正在设计我的应用程序、类、方法、域等......

    针对您的场景,我同意 S.Lott 的暗示,即您需要一套单元测试来测试应用程序中的特定行为。

    【讨论】:

      【解决方案4】:

      在我看来,TDD 一个简单的 CRUD 应用程序有点像在吉他上练习音阶 - 你可能会认为只是发现你的演奏有多大的进步是无聊和乏味的。在开发方面 - 您可能会编写耦合较少的代码 - 更可测试。此外,您更有可能从代码使用者的角度看待事物——您实际上会使用它。这可能会产生许多有趣的副作用,例如更直观的 API、更好的关注点分离等。当然,有脚手架生成器可以为您执行基本的 CRUD,并且它们确实有专门用于原型设计的地方,但是它们通常与框架相关联各种各样的。为什么不首先关注核心领域,推迟框架/UI/数据库决策,直到您更好地了解所需的核心功能 - TDD 也可以帮助您做到这一点。 在您的示例中:您希望消息成为队列还是分层树等? 您希望它们实时加载吗?排序/搜索呢?你需要支持 JSON 还是只支持 html?使用 BDD / TDD 更容易看到这类问题。如果你在做 TDD,你甚至可以在不使用框架的情况下测试你的核心逻辑(并等待它加载/运行)

      【讨论】:

        【解决方案5】:

        跳过它。一切都会好起来的。我确定你有一个截止日期。 (/讽刺)

        下个月,我们可以返回并根据用户反馈优化查询。并打破我们不知道我们不应该打破的东西。

        如果您认为该项目将持续 2 周然后永远不会重新打开,那么自动化测试可能是在浪费时间。否则,如果您在几个月内“拥有”此代码并且它处于活跃状态,那么就构建一些测试。使用您的判断来判断风险最大的地方。更糟糕的是,如果您计划在公司工作几年,并且让其他队友轮流研究系统的各个部分,并且一年后可能又轮到您,那么请进行一些测试。

        不要过度,而是要“在里面插几根针”,这样如果事情开始“移动”,你就会有一些警报来提醒你注意事情。

        我的大部分测试都是 JUnit 或批处理“差异”类型测试,以及我几年前编写的一个基本的屏幕刮板类型工具(编写一些正则表达式 + wget/curl 类型的东西)。我听说 Selenium 应该是 Web 应用程序 UI 测试的好工具,但还没有尝试过。任何人都有本地 GUI 应用程序的可用工具???

        【讨论】:

          【解决方案6】:

          只是一个想法……

          获取 CRUD 的要求,使用 watijwatirAutoIt 等工具创建测试用例。开始创建 UI 以通过测试用例。一旦你启动了 UI 并且可能只通过了一个测试,就开始为该测试编写逻辑层,然后是 db 层。

          对于大多数用户来说,用户界面就是系统。请记住为您正在构建的每个新层编写测试用例。所以与其从 db 到 app 到 ui 层开始,不如从相反的方向开始。

          最终,您可能已经积累了一组强大的回归测试集,让您有信心安全地进行重构。

          这只是一个想法……

          【讨论】:

          • 有趣...我会查找这些工具。谢谢你。我个人的选择是自下而上地开发应用程序。我来自企业应用程序背景-因此对服务层和数据库模型更加尊重-所以想先解决这个问题。但是你说的也有道理
          • 您可能也会对此感兴趣...fitnesse.org FitNesse 使客户、测试人员和程序员能够了解他们的软件应该做什么,并自动将其与实际执行的操作进行比较。它将客户的期望与实际结果进行比较。
          • 典型的BDD就是这样完成的,你可以把它想象成两个同心圆,外层是高层特征,内层是高层所依赖的底层实现。您从使用fitnesse 或cucumber 之类的高级工具开始,然后使用capybara 或selenium 将每个步骤定义为高级可执行测试,从那里您可以计算出中间层,最后是数据层。这种方法一次为您提供完整的垂直切片功能。
          【解决方案7】:

          我明白你在说什么,但最终你的模型将变得足够先进,以至于它们需要(或通过自动化测试大大增强)。如果不是,那么您实际上是在开发一个有人已经为您开发的电子表格。

          既然您提到了 Rails,我想说对每个属性进行标准的创建/读取/更新/删除测试是一个好主意,特别是因为您的测试应该注意权限(我认为这是巨大的)。这还可以确保您的迁移按预期工作。

          【讨论】:

          • 我没有使用 Rails,但我用它作为一个例子,因为它已经“融入”测试,这就是教程通常说你应该测试的内容。不过我明白你的意思。
          【解决方案8】:

          我现在正在开发一个 CRUD 应用程序。此时我正在做的是在我的 Repository 对象上编写单元测试并测试 CRUD 功能是否正常工作。我发现这本身也对实际的数据库代码进行了单元测试。通过这种方式,我们在数据库代码中发现了很多错误。所以我建议你继续前进并继续进行单元测试。我知道在 CRUD 应用程序上应用 TDD 并不像您在博客或杂志上看到的那样迷人,但它正在服务于它的目的,当您处理更复杂的应用程序时,您会变得更好。

          【讨论】:

            【解决方案9】:

            如今,除了 UI 之外,CRUD 应用程序不需要太多手写代码,因为有 101 个框架可以生成数据库和数据访问代码。

            所以我会考虑减少手写代码的数量,并自动化 UI 测试。然后我会使用需要手工编写的奇数位逻辑的 TDD。

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2020-05-06
              • 1970-01-01
              • 2010-10-12
              • 1970-01-01
              • 2011-03-02
              • 1970-01-01
              相关资源
              最近更新 更多