C# 你应该对简单的属性进行单元测试吗?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/18967697/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Should you Unit Test simple properties?
提问by Sam
Should you Unit Test simple properties of a class, asserting that a value is set and retrieved? Or is that really just unit testing the language?
您是否应该对类的简单属性进行单元测试,断言已设置和检索值?或者那真的只是对语言进行单元测试?
Example
例子
public string ConnectionString { get; set; }
Test
测试
public void TestConnectionString()
{
var c = new MyClass();
c.ConnectionString = "value";
Assert.Equal(c.ConnectionString, "value");
}
I guess I don't see the value in that.
我想我没有看到其中的价值。
采纳答案by Stephen Byrne
I would suggest that you absolutely should.
我建议你绝对应该。
What is an auto-property today may end up having a backing field put against it tomorrow, and not by you...
The argument that "you're just testing the compiler or the framework" is a bit of a strawman imho; what you're doing when you test an auto-property is, from the perspective of the caller, testing the public "interface" of your class. The caller has no idea if this is an auto property with a framework-generated backing store, or if there is a million lines of complex code in the getter/setter. Therefore the caller is testing the contract implied by the property- that if you put X into the box, you can get X back later on.
Therefore it behooves us to include a test since we are testing the behaviour of our own code and not the behaviour of the compiler.
A test like this takes maybe a minute to write, so it's not exactly burdensome; and you can easily enough create a T4 template that will auto-generate these tests for you with a bit of reflection. I'm actually working on such a tool at the moment to save our team some drudgery
If you're doing pure TDD then it forces you to stop for a moment and consider if having an auto public property is even the best thing to do (hint: it's often not!)
Wouldn't you rather have an up-front regression test so that when the FNG does something like this:
今天的汽车财产可能最终会在明天有一个支持领域,而不是你......
“你只是在测试编译器或框架”的论点有点像稻草人,恕我直言;当您测试自动属性时,从调用者的角度来看,您正在做的是测试您班级的公共“接口”。调用者不知道这是否是具有框架生成的后备存储的自动属性,或者 getter/setter 中是否有一百万行复杂代码。因此,调用者正在测试该属性所隐含的合同- 如果您将 X 放入框中,您可以稍后取回 X。
因此,我们应该包含一个测试,因为我们正在测试我们自己代码的行为,而不是编译器的行为。
像这样的测试可能需要一分钟的时间来编写,所以它并不是很繁重;并且您可以轻松地创建一个 T4 模板,该模板将通过一些反思为您自动生成这些测试。我现在实际上正在开发这样一个工具来为我们的团队节省一些苦差事
如果你正在做纯 TDD,那么它会迫使你停下来考虑一下拥有汽车公共财产是否是最好的事情(提示:通常不是!)
您是否更愿意进行前期回归测试,以便当 FNG 执行以下操作时:
//24-SEP-2013::FNG - put backing field for ConnectionString as we're now doing constructor injection of it
public string ConnectionString
{
{get { return _connectionString; } }
{set {_connectionString="foo"; } }//FNG: I'll change this later on, I'm in a hurry
}
///snip
public MyDBClass(string connectionString)
{
ConnectionString=connectionString;
}
You instantlyknow that they broke something?
你马上就知道他们弄坏了什么东西?
If the above seems contrived for a simple string property I have personally seen a situation where an auto-property was refactored by someone who thought they were being oh so clever and wanted to change it from an instance member to a wrapper around a static class member (representing a database connection as it happens, the resons for the change are not important).
如果上面的内容似乎是为一个简单的字符串属性而设计的,我个人已经看到这样一种情况,即有人认为自动属性被重构了,他们认为自己太聪明了,并想将其从实例成员更改为静态类成员的包装器(代表发生的数据库连接,更改的原因并不重要)。
Of course that same very clever person completely forgotto tell anyone else that they needed to call a magic function to initialise this static member.
当然,这个非常聪明的人完全忘记告诉其他人他们需要调用一个魔法函数来初始化这个静态成员。
This caused the application to compile and ship to a customer whereupon it promptly failed. Not a huge deal, but it cost several hours of support's time==money.... That muppet was me, by the way!
这导致应用程序编译并发送给客户,因此它立即失败。没什么大不了的,但它花费了几个小时的支持时间==金钱......顺便说一下,那个布偶就是我!
EDIT: as per various conversations on this thread, I wanted to point out that a test for a read-write property is ridiculously simple:
编辑:根据此线程上的各种对话,我想指出读写属性的测试非常简单:
[TestMethod]
public void PropertyFoo_StoresCorrectly()
{
var sut = new MyClass();
sut.Foo = "hello";
Assert.AreEqual("hello", sut.Foo, "Oops...");
}
edit: And you can even do it in one line as per Mark Seeman's Autofixture
编辑:您甚至可以按照 Mark Seeman 的Autofixture在一行中完成
I would submit that if you find you have such a large number of public properties as to make writing 3 lines like the above a chore for each one, then you should be questioning your design; If you rely on another test to indicate a problem with this property then either
我认为,如果你发现你有如此多的公共属性,以至于每一行都写上 3 行这样的苦差事,那么你应该质疑你的设计;如果您依靠另一项测试来表明此属性存在问题,则要么
- The test is actually testing this property, or
- You will spend more time verifying that this other test is failing because the property is incorrect (via debugger, etc) than you would have spent typing in the above code
- If some other test allows you to instantly tell that the property is at fault, it's not a unit test!
- 测试实际上是在测试这个属性,或者
- 您将花费更多的时间来验证其他测试是否失败,因为该属性不正确(通过调试器等),而不是您输入上述代码所花费的时间
- 如果其他测试允许您立即判断该属性有问题,那么这不是单元测试!
edit (again!): As pointed out in the comments, and rightly so, things like generated DTO models and the like are probably exceptions to the above because they are just dumb old buckets for shifting data somewhere else, plus since a tool created them, it's generally pointless to test them.
编辑(再次!):正如评论中指出的那样,生成的 DTO 模型之类的东西可能是上述情况的例外,因为它们只是用于将数据转移到其他地方的愚蠢的旧桶,而且由于工具创建了它们,测试它们通常毫无意义。
/EDIT
/编辑
Ultimately "It depends" is probably the real answer, with the caveat that the best "default" disposition to be the "always do it" approach, with exceptions to that taken on an informed, case by case basis.
最终,“这取决于”可能是真正的答案,但需要注意的是,最好的“默认”配置是“始终这样做”的方法,但在知情的情况下逐案采取的例外。
回答by Mike Perrenoud
I would have to say no. If that doesn't work, you have bigger problems. I know I don't. Now some will argue that having the code alone would make sure the test failed if the property was removed, for example. But I'd put money on the fact that if the property were removed, the unit test code would get removed in the refactor, so it wouldn't matter.
我不得不说不。如果这不起作用,那么您将遇到更大的问题。我知道我没有。现在有些人会争辩说,例如,如果属性被删除,单独使用代码可以确保测试失败。但我愿意花钱,如果属性被删除,单元测试代码将在重构中被删除,所以这无关紧要。
回答by BenM
Generally, no. A unit test should be used to test for the functionality of a unit. You should unit test methods on a class, not individual, automatic properties (unless you are overriding the getter or setter with custom behaviour).
一般来说,没有。应该使用单元测试来测试单元的功能。您应该对类而不是单个自动属性进行单元测试(除非您使用自定义行为覆盖 getter 或 setter)。
You know that assigning a string value to an automatic string property will work if you get the syntax and setter value correct as that is a part of the language specification. If you do not do this then you will get a runtime error to point out your flaw.
您知道,如果语法和 setter 值正确,则将字符串值分配给自动字符串属性将起作用,因为这是语言规范的一部分。如果你不这样做,那么你会得到一个运行时错误来指出你的缺陷。
Unit tests should be designed to test for logical errors in code rather than something the compiler would catch anyway.
单元测试应该旨在测试代码中的逻辑错误,而不是编译器无论如何都会捕获的东西。
EDIT: As per my conversation with the author of the accepted answer for this question I would like to add the following.
编辑:根据我与此问题已接受答案的作者的对话,我想添加以下内容。
I can appreciate that TDD purists would say you need to test automatic properties. But, as a business applications developer I need to weigh up, reasonably the amount of time I could spend writing and performing tests for 'trivial' code such as automatic properties compared to how long it would reasonably take to fix an issue that could arise from not testing. In personal experience most bugs that arise from changing trivial code are trivial to fix 99% of the time. For that reason I would say the positives of only unit testing non-language specification functionality outweigh the negatives.
我可以理解 TDD 纯粹主义者会说您需要测试自动属性。但是,作为一名业务应用程序开发人员,我需要权衡合理的时间,我可以花费多少时间来为“琐碎”代码(例如自动属性)编写和执行测试,与修复可能出现的问题所需的合理时间相比不测试。根据个人经验,大多数由更改琐碎代码引起的错误在 99% 的情况下都是微不足道的。出于这个原因,我会说仅对非语言规范功能进行单元测试的好处大于坏处。
If you work in a fast paced, business environment which uses a TDD approach then part of the workflow for that team should be to only test code that needs testing, basically any custom code. Should someone go into your class and change the behavior of an automatic property, it is their responsibility to set up a unit test for it at that point.
如果您在使用 TDD 方法的快节奏业务环境中工作,那么该团队的部分工作流程应该是仅测试需要测试的代码,基本上是任何自定义代码。如果有人进入您的类并更改自动属性的行为,则他们有责任在那时为其设置单元测试。
回答by Ciaran Gallagher
Unless the properties perform any other sort of logic, then no.
除非属性执行任何其他类型的逻辑,否则不会。
Yes, it is like unit testing the language. It would be completely pointless to test simple auto-implemented properties otherwise.
是的,这就像对语言进行单元测试。否则测试简单的自动实现的属性将完全没有意义。
回答by Preston Guillot
Are you adhering to strict TDD practices or not?
您是否遵守严格的 TDD 实践?
If yes then you absolutelyshould write tests on public getters and setters, otherwise how will you know if you've implemented them correctly?
如果是,那么你绝对应该对公共 getter 和 setter 编写测试,否则你怎么知道你是否正确实现了它们?
If no, you still probably should write the tests. Though the implementation is trivial today, it is not guaranteed to remain so, and without a test covering the functionality of a simple get/set operation, when a future change to implementation breaks an invariant of "setting property Foo with a value Bar results in the getter for property Foo returning value Bar" the unit tests will continue to pass. The test itself is alsotrivially implemented, yet guards against future change.
如果不是,您可能仍然应该编写测试。尽管今天的实现是微不足道的,但不能保证保持如此,如果没有覆盖简单 get/set 操作功能的测试,当未来对实现的更改破坏了“将属性 Foo 设置为值 Bar 导致的不变量”时属性 Foo 的 getter 返回值 Bar”,单元测试将继续通过。测试本身也很简单,但可以防止将来发生变化。
回答by aqwert
The way I see is that how much unit testing (or testing in general) is down to how confident are you that the code works as designed and what are the chances of it breaking in the future.
我的看法是,有多少单元测试(或一般测试)取决于您对代码按设计工作的信心以及它在未来崩溃的可能性有多大。
If you have a lower confidence of the code breaking (maybe due to the code being out sourced and the cost of checking line by line is high) then perhaps unit testing properties is appropriate.
如果您对代码破坏的信心较低(可能是由于代码被外包并且逐行检查的成本很高),那么也许单元测试属性是合适的。
Once thing you can do is write a helper class that can go over all get/set properties of a class to test that they still behave as designed.
您可以做的事情是编写一个辅助类,该类可以检查类的所有 get/set 属性,以测试它们是否仍按设计运行。
回答by Alireza
According to the book The Art of Unit Testing With Examples in .NET, a unit test covers not any type of code, it focuses on logical code. So, what is logical code?
根据The Art of Unit Testing With Examples in .NET一书,单元测试不涵盖任何类型的代码,它侧重于逻辑代码。那么,什么是逻辑代码?
Logical code is any piece of code that has some sort of logic in it, small as it may be. It's logical code if it has one or more of the following: an IF statement, a loop, switch or case statements, calculations, or any other type of decision-making code.
逻辑代码是任何包含某种逻辑的代码,尽管它可能很小。如果它具有以下一项或多项,则它是逻辑代码:IF 语句、循环、switch 或 case 语句、计算或任何其他类型的决策代码。
Does a simple getter/setter wrap an any logic? The answer is:
一个简单的 getter/setter 是否包含任何逻辑?答案是:
Properties (getters/setters in Java) are good examples of code that usually doesn't contain any logic, and so doesn't require testing. But watch out: once you add any check inside the property, you'll want to make sure that logic is being tested.
属性(Java 中的 getter/setter)是很好的代码示例,它们通常不包含任何逻辑,因此不需要测试。但请注意:一旦您在属性中添加任何检查,您将需要确保正在测试逻辑。
回答by SayusiAndo
My answer which is from former test manager viewpoint and currently a development manager ( responsible for software delivery in time and quality) viewpoint. I see people are mentioning pragmatism. Pragmatism is not a good adviser because it may pair up with laziness and/or time pressure. It may led you on the wrong way. If you mention pragmatism you have to be careful to keep your intentions on the track of professionalism and common sense. It requires humility to accept the answers because they might not that you want to hear.
我的回答是从前测试经理的观点和目前的开发经理(负责软件的时间和质量交付)的观点来看的。我看到人们在提到实用主义。实用主义不是一个好的顾问,因为它可能伴随着懒惰和/或时间压力。它可能会让你走上错误的道路。如果你提到实用主义,你必须小心地将你的意图保持在专业和常识的轨道上。接受答案需要谦虚,因为它们可能不是您想听到的。
From my viewpoint what is important are the next:
在我看来,重要的是接下来:
- you should find the defect as early as possible. Doing so you have to apply proper testing strategy. If it is testing properties then you have to test properties. If not, then don't do it. Both comes with a price.
- your testing should be easy and fast. The bigger part (unit, integration, etc.) of the code tested in build time is the better.
- you should do root cause analysis to answer the questions below and make your organization protected from the current type of error. Don't worry, another type of defect will come up and there will be always lessons to be learned.
- what the root cause is?
- how to avoid it next time?
- another aspect is the cost of creating/maintaining tests. Not testing properties because they are boring to maintain and/or you have hundreds of properties is ridiculous. You should create/apply tools which makes the woodcutting job instead of human. In general, you always have to enhance your environment in order to be more efficient.
- what other says are not good adviser - doesn't matter whether it was said by Martin Fowler or Seeman - the environment they are I'm pretty sure not the same as you are in. You have to use your knowledge and experience to setup what is good for your project and how to make it better. If you apply things because they were said by people you are respect without even thinking it through you will find yourself in deep trouble. I do not say that you don't need advises and/or other people help or opinion, you have to apply common sense to apply them.
- TDD does not answer two important question, however, BDD does give you answers for the questions below. But, if you follow only one, you won't have delivery in time and quality. So doesn't matter whether you are purist TDD guy or not.
- what must be tested? ( it says everything must be tested - wrong answer in my opinion )
- when testing must be finished?
- 你应该尽早发现缺陷。这样做你必须应用适当的测试策略。如果是测试属性,那么你必须测试属性。如果没有,那就不要做。两者都是有代价的。
- 您的测试应该简单快捷。在构建时测试的代码的部分(单元、集成等)越大越好。
- 您应该进行根本原因分析来回答以下问题,并使您的组织免受当前类型错误的影响。别担心,另一种类型的缺陷会出现,并且总会有教训可以吸取。
- 根本原因是什么?
- 下次如何避免?
- 另一方面是创建/维护测试的成本。不测试属性因为它们维护起来很无聊和/或你有数百个属性是荒谬的。您应该创建/应用使木刻工作而不是人类工作的工具。一般来说,您总是必须改善您的环境以提高效率。
- 其他人说的不是好顾问——不管是 Martin Fowler 还是 Seeman 说的——他们所处的环境我很确定和你所处的环境不一样。你必须利用你的知识和经验来设置什么对您的项目以及如何使其变得更好有好处。如果你把事情是因为他们是你所尊重的人说的,甚至都没有仔细考虑过,你会发现自己陷入了深深的麻烦。我并不是说您不需要建议和/或其他人的帮助或意见,您必须运用常识来应用它们。
- TDD 没有回答两个重要的问题,但是,BDD 确实为您提供了以下问题的答案。但是,如果您只关注一个,您将无法按时交付质量。所以不管你是不是纯粹的 TDD 人。
- 必须测试什么?(它说一切都必须经过测试 - 在我看来是错误的答案)
- 什么时候必须完成测试?
All in all, there is no good answer. Just other questions you have to answer to get that temporary point where you are able to decide whether it is needed or not.
总而言之,没有好的答案。只是您必须回答的其他问题才能获得临时点,您可以决定是否需要它。