如何使用代码契约进行单元测试

发布于 2024-11-04 09:14:19 字数 123 浏览 0 评论 0原文

使用 .NET 4.0 代码契约进行 TDD 的最佳实践建议是什么?

我想具体来说,我的问题是,鉴于 TDD 的一点是允许代码自我记录,并且合约现在提供了文档的一部分,代码合约是否应该以与其他代码相同的方式进行测试?

What is the best practice recommendation for doing TDD with .NET 4.0 Code Contracts?

I suppose specifically, my question is that given that one point of TDD is to allow the code to be self documenting and the contract now provides a part of the documentation, should code contracts be tested in the same way as other code?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

不必你懂 2024-11-11 09:14:19

这取决于您如何使用合约以及您正在开发什么类型的应用程序。

首先:您当然不想测试断言和后置条件(Contract.AssertContract.AssumeContract.Ensures 和 <代码>Contract.EnsuresOnThrow)分别。
我认为这样做没有实际价值 - 因为它们已经在运行时由重写器验证,即使没有测试,您也会很快发现失败。
然而,在经过良好测试的应用程序中,任何后置条件或断言都不应失败 - 即使输入无效。因此,如果您的所有测试(甚至是测试无效数据处理的测试!)在没有单个后置条件/断言失败的情况下通过,则您的后置条件和断言可以被视为“已测试”。
为此,您可能希望在测试中使用“Assert.Fail”来处理 ContractFailed 事件。

现在“有趣”的部分是前提条件:
您正在开发图书馆吗?然后,如果您的时间/预算允许的话,您绝对应该测试它们(不测试实际逻辑更糟糕)。
特别是,如果您使用“Contract.Requires”重载会在合约失败时引发特定异常,您应该使用“if-throw”结构像常规参数验证一样测试它们。

如果您不编写库,我不会说测试先决条件确实有必要 - 它们不是真正的业务需求,而是调试的助手。
如果参数为 null,则为方法应抛出的每个 ArgumentNullException 编写单元测试可能会非常无聊。
如果您忘记了方法中的验证代码(即:特定的 Contract.Requires),您可能也会忘记单元测试。因此,参数验证测试为您的(非库)代码带来的附加值相对于连接值来说非常低。

总结一下:不要测试后置条件和断言。测试先决条件 - 但仅限于库(可能还有像库一样使用的部分代码)。

This depends on how you are using contracts and what kind of application you are developing.

First of all: You certainly don't want to test assertions and postconditions (Contract.Assert, Contract.Assume, Contract.Ensures and Contract.EnsuresOnThrow) separetly.
I see no practical value in doing so - as they are already verified during runtime by the rewriter, you will find failures very fast even without tests.
However, in a well tested application, no postcondition or assert should fail - even on invalid inputs. Thus, if all your tests (even the ones testing handling of invalid data!) pass without a single postcondition/assertion-fail, your postconditions and assertions can be seen as "tested".
For this, you might want to handle the ContractFailed event using an "Assert.Fail" within your tests.

Now the "interesting" part are the preconditions:
Are you developing a library? Then, you should definitely test them if your time/budget allows this (it's worse not testing the actual logic).
Especially, if you are using the "Contract.Requires<E>" overload which will throw a specific exception on contract failures, you should test them like regular parameter validation using "if-throw"-constructs.

If you are not writing a library, I wouldn't say that testing preconditions is really necessary - they are no real business requirement but rather a helper for debugging.
And it can get really boring to write a unittest for every ArgumentNullException a method should throw if a parameter is null.
If you forget this validation code (meaning: The specific Contract.Requires) inside your method, you will probably forget the unit-test, too. Therefore, the additional value a parameter-validation-test brings to your (non-library-)code is very low to the connected value.

To sum it up: Don't test postconditions and asserts. Do test preconditions - but only on libraries (and maybe parts of your code which are used like libraries).

浅笑轻吟梦一曲 2024-11-11 09:14:19

我不同意这里其他一些人的观点。合约不是测试,它们是关于 API 的要求和承诺的断言。它们不会神奇地证明您的代码是正确的,它们只是在您违反合同时在运行时为您提供信息。我不了解你的情况,但我不想发布在某些极端情况下未能遵守合同并因合同断言而崩溃的代码!与任何其他行为一样,合约应该经过单元测试。如果您不行使合同(以及间接行使合同的代码路径),您就没有代码有效性的证据。代码契约和单元测试并不是相互排斥的概念。

I'm going to disagree with some other folks here. Contracts are NOT tests, they are assertions about the API's requirements and promises. They don't magically prove your code to be correct, they just provide you information at runtime when you violate the contract. I don't know about you but I'd hate to ship code that in some corner case failed to comply with the contracts and crashed with a contract assertion! Like any other behavior, the contracts should be unit tested. If you don't excercise the contracts (and code paths that indirectly excercise the contracts) you have no evidence of the codes validity. Code contracts and unit tests are not mutually exclusive concepts.

知你几分 2024-11-11 09:14:19

很好的问题。简单的答案是否定的。代码契约可以处理与系统行为无关的多余测试。如果您确实可以达到 100% 的代码覆盖率,您将需要处理 isnull 检查等。这些检查不需要位于您的测试套件中。额外的好处是,这些将在编译时进行检查,而不是等待测试执行。

希望这有帮助。

Great question. The simple answer is no. code contracts can take care of the superfluous tests that are not about the behavior of the system. If you really can get to 100% code coverage, you will need to take care of the isnull checks, etc. these checks don't need to be in your test suite. the added benefit is that these will be checked at compile time instead of waiting for tests to execute.

Hope this helps.

随遇而安 2024-11-11 09:14:19

Pex 是结合代码契约创建单元测试的有用工具。它分析您的代码并为其生成基本的单元测试。最棒的是它可以识别和理解代码契约,因此可以调整它生成的测试代码。

如果您有 MSDN 订阅,则可以下载 Pex/Moles 作为强力工具,否则您可以在 http://research.microsoft.com/en-us/projects/pex/downloads.aspx

A useful tool to create unit tests in combination with Code Contracts is Pex. It analyses your code and generates basic unit tests for it. The great thing is that it recognizes and understands Code Contracts, and so adapts the testing code it generates.

If you have an MSDN Subscription then you can download Pex/Moles as a powertool, otherwise you can download it (not the most recent version) at http://research.microsoft.com/en-us/projects/pex/downloads.aspx.

笑,眼淚并存 2024-11-11 09:14:19

测试是为了测试代码的行为是否符合预期

。您不应该明确编写测试来执行合同断言。

然而,在 TDD 中或在进行代码更改时,运行单元测试可能会以导致合约失败的方式执行代码 - 当发生这种情况时,测试应该失败,并且您希望能够快速找到失败的合约并很容易,这样您就可以更正代码。

因此,您想以某种方式捕获contractException,然后执行 Asser.Fail("Contract request not met")

这可能更符合您的要求
如何在使用代码合约时记录错误

Tests are there to test code behaves as expected

You should NOT explictly write tests to exercise contract assertions.

However in TDD or when making a code change, running a unit-test may exercise code in a way that causes a contract fails - when this happens the test should fail and you want need to be able to then find the contract that failed quickly and easily, so you can correct the code.

So somehow you want to catch a contractexception if only to then do a Asser.Fail("Contract requirement not met")

This may be more what you are after
How to Log error while using Code Contracts

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文