如何在 .NET 4.0 Code Contracts 中实践 TDD 最佳建议?
我认为具体来说,我的问题是,考虑到 TDD 的一个目的是让代码自我记录,并且合同现在提供了部分记录,那么代码合同是否应该像其他代码一样进行测试?
如何在 .NET 4.0 Code Contracts 中实践 TDD 最佳建议?
我认为具体来说,我的问题是,考虑到 TDD 的一个目的是让代码自我记录,并且合同现在提供了部分记录,那么代码合同是否应该像其他代码一样进行测试?
这取决于您如何使用合同以及您正在开发什么类型的应用程序。
首先:您肯定不希望单独测试断言和后置条件(Contract.Assert
,Contract.Assume
,Contract.Ensures
和Contract.EnsuresOnThrow
)。
我认为这样做没有实际价值-由于重写器已经在运行时验证它们,即使没有测试,您也会很快发现失败。
然而,在经过充分测试的应用程序中,没有后置条件或断言应该失败-即使是在无效输入的情况下。因此,如果所有测试(甚至是测试处理无效数据的测试!)都通过而没有一个后置条件/断言失败,则可以将其视为“已测试”的后置条件和断言。
为此,您可能需要使用“Assert.Fail”在测试中处理ContractFailed事件。
现在有趣的部分是前置条件:
您正在开发库吗?然后,如果您的时间/预算允许,您绝对应该测试它们(不测试实际逻辑更糟)。
特别是,如果您使用“Contract.Requires<E>”重载,在合同失败时会抛出特定异常,则应像常规参数验证一样使用“if-throw”构造来测试它们。
如果您不是编写库,则我不认为测试前置条件真的是必要的-它们不是真正的业务要求,而只是调试助手。
而且,为每个方法应该抛出ArgumentNullException
的参数进行单元测试可能会变得非常无聊。
如果您在方法中忘记此验证代码(即:特定的Contract.Requires),则您可能也会忘记单元测试。因此,参数验证测试为您的(非库)代码带来的附加价值与相关价值相比非常低。
总之:不要测试后置条件和断言。确实测试前置条件-但仅针对库(以及可能像库一样使用的代码部分)。
我不同意其他人的观点。合同并不是测试,它们是关于API需求和承诺的断言。它们并不能神奇地证明你的代码是正确的,只有在你违反合同时,它们才会在运行时提供信息。我不知道你们怎么想,但我不希望发布的代码在某些边角情况下未能遵守合同而崩溃!与任何其他行为一样,合同应该进行单元测试。如果你不执行合同(以及间接执行合同的代码路径),那么你就没有证据证明代码的有效性。代码合同和单元测试并不是互斥的概念。
好问题。简单的答案是否定的。代码合同可以处理与系统行为无关的多余测试。如果您真的可以达到100%的代码覆盖率,您需要处理isnull检查等。这些检查不需要在您的测试套件中。额外的好处是这些将在编译时进行检查,而不是等待测试执行。
希望这可以帮助您。
测试旨在测试代码是否按预期运行。
您不应明确编写测试以执行合同断言。
但是,在TDD或进行代码更改时,运行单元测试可能会以导致合同失败的方式运行代码 - 当发生这种情况时,测试应该失败,并且您需要能够快速轻松地找到失败的合同,以便您可以更正代码。
因此,您希望捕获ContractException,即使只是为了执行Asser.Fail(“未满足合同要求”)
这可能更符合您的需求 如何在使用代码合同时记录错误