【问题标题】:Agile: ATDD Scenario For the Model [closed]敏捷:模型的 ATDD 场景 [关闭]
【发布时间】:2015-12-05 00:27:47
【问题描述】:

我是 TDD 和 ATDD 的新手,我正在寻求了解用户故事与其接受标准之间的联系。对于上下文,我正在用 C# 构建一个带有 MVC 前端的 3 层应用程序。

例如,假设我有以下用户故事:

为了确保正确输入容量数据 作为个人更新此数据 当输入的数据不符合我们的业务规则时,我想要反馈。

对我来说,分解并定义什么是“容量数据”以及管理它的业务规则是有意义的。

例如,它可能具有必须大于零的“机器数”属性。

我想要避免做的是测试框架——如果我正确地遵循,我想要做的是测试这个业务逻辑是否正确实现,即:

  1. 业务规则(“机器数必须大于零”等)已在代码库中正确实现。
  2. 如果违反了业务规则,则会提醒用户注意此错误。

我相信我可以通过验证控制器中的无效模型状态重定向到同一页面来测试规则 #2,例如——并且有很多这样的例子。

但是,这样做不需要在视图模型上添加装饰吗?最终这会从用户的角度实现业务规则吗? (因此满足#1?)

假设我有以下语句/单元测试:

[Test]
public void GivenCapacityModelWhenNumMachinesZeroOrLessThenModelShouldBeInvalid()
{
   // Given
   IValidatorThing validator = new ValidatorThing(); //What enforces the rule? Should this be a controller service? Or a decorator such as [Range(0.000001,1000000)]? Doesn't each require different testing methods?
   var invalidModel = new CapacityModel(); // Or the viewmodel?
   double zeroValue = 0.000001;
   invalidModel.NumMachines = zeroValue;

   // When
   var modelIsValid = ValidatorThing.validateModel(invalidModel); 

   // Then
   Assert.IsFalse(modelIsValid);
}

当然,上面的内容不会编译。为了简单起见,我暂时省略了任何特定的模拟或固定框架。所以,为了使这个测试至少可以编译(但仍然失败),我需要做出一些决定:

  1. CapacityModel 是否应该是视图模型?还是来自服务层的 DTO?还是 DAL 层中的元数据类?我可以实现其中任何一个并使测试通过...但我真正应该测试什么?
  2. “验证器”是否检查验证此模型属性的服务的行为?还是CapacityModel上的数据注释?同样,我应该在 3 层应用程序的上下文中真正测试什么?

需要考虑的一些事项: 我要知道的一件事是,数据库表将具有描述这些规则的约束——因此,这条规则的目的似乎实际上是为了将这些规则传达给使用该应用程序的任何人。在那种情况下,我是否可以安全地假设将规则出现在三个地方会违反 DRY:视图模型、数据实体和数据库表。

我们在数据库中设置这些规则的原因是,我们希望确保 DBA 需要处理记录时不会意外违反规则。但是,据我所知,没有一种很好的方法可以将这些 CONSTRAINT 规则转换为应用程序的 DAL ......所以我想他们需要在应用程序中至少重复一次,以便将它们传达给用户。

那么,如果我要编写一个单元测试来满足业务规则,我会不会只是为了确保规则反映数据库?另外,还要编写一个单元测试来确保向用户显示正确的消息?

您能提供的任何指导都会很棒。我想觉得我所做的决定是合理的,或者至少有一个更好地解决问题的替代方法的想法。

谢谢,

劳伦斯

编辑:

所以,最终我试图以集中方式管理应用程序中的验证,以便我可以分离关注点——即控制器只关心路由,视图模型只关心显示数据,验证器例如,只关心验证等...而不是在视图模型中进行验证。

我发现了一个非常有用的article,它帮助我掌握了如何使用现有的 MVC 基础架构来做到这一点。希望这将有助于其他人研究这些类型的场景。

【问题讨论】:

    标签: c# asp.net-mvc agile


    【解决方案1】:

    我怀疑您可能模糊了单元测试和验收测试之间的界限。

    验收测试非常关注业务用户。它将应用程序视为一个黑匣子,但会检查以确认应用程序的界面是否按照用户期望的方式运行。

    在您的示例中,我会看到验收测试类似于:

    对于简单的业务规则(机器数量必须大于零),确保在违反业务规则的情况下向用户提供正确的反馈。

    我会在这个阶段与产品负责人交谈,以了解他们认为什么是“正确的反馈”以及他们希望如何显示。

    这里重要的是,您不是在测试如何评估业务规则或处理错误的内部机制是什么。您完全专注于最终用户交互。

    当然,您还需要实施单元测试以确保您的技术解决方案是可靠的,这是您详细了解业务逻辑实施位置的地方。

    您如何处理业务逻辑在很大程度上是一个设计决策。就个人而言,如果我在数据库中有业务逻辑,我也会有一个包含规则描述的表,在违反规则的情况下将用作查找。应用程序的其他层对业务逻辑一无所知,但会知道如何传递错误消息。

    【讨论】:

    • 谢谢!这确实有助于确认我混淆了两个不同的概念。对于上下文,我正在阅读this。因此,确定“对于简单的业务规则(机器数量必须大于零),确保在违反业务规则的情况下向用户提供正确的反馈。”是验收测试,那么我会将其分解为多个单元测试吗?比如“X
    • 为了澄清您建议的解决方案,理论上我会在出现错误消息后调用数据库表(包含错误代码)吗?或者以某种方式捕捉 Oracle 抛出的错误? this thread 讨论了从 Oracle 中捕获错误,但这听起来在实践中并不可行。您能否就详细描述实现的资源提供建议? (很难搜索这些,似乎没有太多信息——也许你知道一些?)
    • 我希望您拨打电话以获取错误消息。如果您可以从原始的 Oracle 错误中触发它,那就太好了,但我从未使用过这样的实现。抱歉,但我没有任何资源可以描述这种实现。关于您的第一点:我希望接受测试来测试错误消息的机制,而不是所有可能的错误条件。但这取决于我对有效使用测试覆盖率的看法。如果你想让你的覆盖范围测试每一个条件,那就去吧!
    • 感谢您的反馈,巴纳比。我想如果我可以从 Oracle 触发错误会很好,但最终如果规则本身将在数据库中完成,那么在应用程序中再次测试它们几乎没有价值。我认为确保从用户的角度来看,如果需要,在 POST 之前(“字段是必需的”内容)和 POST 之后(可能使用 [HandleError("一些错误页面")] 用于异常。这样,数据库使用约束添加价值,应用程序使用用户消息添加价值。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-09-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多