使用.NET 4.0代码合约执行TDD的最佳做法建议是什么?
我想具体来说,我的问题是,鉴于TDD的一个要点是允许代码自我记录并且合同现在提供文档的一部分,代码合同是否应该像其他代码一样进行测试?
答案 0 :(得分:11)
这取决于您使用合同的方式以及您正在开发的应用程序类型。
首先:您当然不希望测试断言和后置条件(Contract.Assert
,Contract.Assume
,Contract.Ensures
和Contract.EnsuresOnThrow
)。
我认为这样做没有实际价值 - 因为它们已经在运行时由重写器验证过,即使没有测试,你也会发现故障非常快。
但是,在经过良好测试的应用程序中,即使在无效输入上,也不会出现后置条件或断言失败。因此,如果所有测试(甚至是测试处理无效数据的测试!)在没有单个后置条件/断言失败的情况下通过,那么您的后置条件和断言可以被视为“已测试”。
为此,您可能希望在测试中使用“Assert.Fail”处理ContractFailed事件。
现在“有趣”的部分是先决条件:
你在开发图书馆吗?那么,如果你的时间/预算允许,你肯定应该测试它们(更糟糕的是不测试实际的逻辑)
特别是,如果您使用的是“Contract.Requires< E>”在合同失败时抛出特定异常的重载,你应该像使用“if-throw”-constructs那样测试它们,就像常规参数验证一样。
如果您不是在编写库,我不会说测试前置条件确实是必要的 - 它们不是真正的业务需求,而是调试的助手。
如果参数为ArgumentNullException
,方法应该抛出每null
个单位测试,这真的很无聊。
如果您在方法中忘记了此验证代码(意思是:特定的Contract.Requires),您可能也会忘记单元测试。因此,参数验证测试为您的(非库)代码带来的附加值对连接值来说非常低。
总结一下:不要测试后置条件和断言。测试前提条件 - 但仅限于库(以及代码中可能像库一样使用的部分)。
答案 1 :(得分:3)
我不同意这里的其他人。合同不是测试,它们是关于API的要求和承诺的断言。它们不会神奇地证明您的代码是正确的,它们只是在您违反合同时在运行时向您提供信息。我不了解你,但我讨厌发送代码,在某些情况下,这些代码未能遵守合同并因合同声明而崩溃!与任何其他行为一样,合同应进行单元测试。如果您没有执行合同(以及间接执行合同的代码路径),则您没有证明代码有效性的证据。代码合同和单元测试不是相互排斥的概念。
答案 2 :(得分:1)
好问题。简单回答是不。代码契约可以处理与系统行为无关的多余测试。如果您真的可以获得100%的代码覆盖率,则需要处理isnull检查等,这些检查不需要在您的测试套件中。额外的好处是,这些将在编译时检查,而不是等待测试执行。
希望这有帮助。
答案 3 :(得分:1)
与代码合同一起创建单元测试的有用工具是Pex。它会分析您的代码并为其生成基本的单元测试。最棒的是它识别并理解代码契约,因此适应它生成的测试代码。
如果你有MSDN订阅,那么你可以下载Pex / Moles作为powertool,否则你可以在http://research.microsoft.com/en-us/projects/pex/downloads.aspx下载它(不是最新的版本)。
答案 4 :(得分:0)
测试代码的行为符合预期
你不应该明确地写测试来行使合同断言。
然而,在TDD或更改代码时,运行单元测试可能会以导致合同失败的方式执行代码 - 当发生这种情况时,测试应该失败并且您希望能够找到合同快速轻松地失败,因此您可以更正代码。
所以不知怎的,如果只是为了做Asser.Fail("合同要求未得到满足")
,那么你想要了解一个缩略词。这可能更像是你所追求的 How to Log error while using Code Contracts