Is there anything wrong with putting test methods in the开发者_如何学C same class as the class you're testing?
So add the [TestFixture] attribute to every class and have [Test] method alongside the actual methods.
I like the idea. Keeps everything in one place.
But what, if any, are the downsides to this ?
/I use Nunit and c#.
Yes this is a pattern to be avoided. Tests should be a completely separate entity from your shipping code for at least the following reasons
- Having tests in a separate assembly help ensure you have a usable API as they can't cheat via
private
/protected
constructs. Instead they are forced to go through the public API points - Having tests in the same assembly means your production code also includes your test code. No reason to ship code to the customer they won't actually be using
- Causes production code to take dependencies on assemblies they don't need (Nunit, xunit, etc ...)
- Many testing frameworks require test methods to be public hence it pushes tests to the public surface of your API.
- Having them in the same assembly opens the door to production code accidentally calling into test code and hence fun asserts popping up in production environments
This approach grates my soul.
I think it makes a lot more sense to keep your test code separate from your production code. Many reasons:
- Theoretically, you should be testing at the interface of your code and not have access to things like the private members behind the scenes.
- Organization - having all of your tests in a separate project means your main application won't be cluttered with test code.
- This would bloat the size of your deliverables.
- Putting everything in one place makes it harder for a team to work on the codebase at the same time (one person on tests, one on the code, etc).
Most of all:
It just plains feels / smells wrong.
Yes. It would be breaking Single Responsibility Principle. It will reduce the readability. You add a dependency to your testing framework.
Biggest downside: you have to ship your tests, and they potentially become part of your public API.
Downsides?
Your classes will technically have more methods than they need for use in a production environment. You'll also have references to nUnit that you don't need in a production environment.
You're also breaking separation of duties here. Your class is supposed to do the job, your test is supposed to verify that your class can do its job.
One potential downside is that when you ship your code, you would also have to ship all the tests, making the deliverable binary larger, full of test methods that never get called.
A more philosophical downside is that, while you are indeed keeping everything together, you are failing to separate the concerns of the code itself (the business logic) from the concerns of quality assurance (making sure it works correctly). Try thinking about your code in terms of a single responsibility for each class/file and see where that takes you.
You don't want to take shortcuts.
You don't want to test private methods. You especially don't want to use private methods as helper methods for your unit tests (i.e., reuse them in your tests).
It is much nicer to group test classes in test projects. These then don't influence the code that is being tested, and it's much easier to keep an overview of what code you have.
In the same fashion, you don't mix UI and business logic code.
So please, please, pretty please, don't mix tests with their subjects under test!
The biggest problem I see with this off the top of my head is that you don't want to distribute your unit tests within your code-base as part of the final product (hence dependencies too).
And using trace constants to conditionally build them gets real ugly in this case. Fr example, one condition for the test fixture attribute and at least one for the method or group of methods.
There are so may aspects relating to why not to do this, as exemplified in the array of answers already flooding in - just don't do it.
To throw in my two cents:
I'll agree with most of the posts here, stating that creating test methods/functions for the sole purpose of testing is wasteful and potentially, structurally disorganized.
However, in general, when you develop "with testing in mind," you can design your implementation to also be tested. For instance, you may initially design a function/method to use a class variable. However, if you wanted to test that method's functionality, you may design it to have the value of the class variable "passed in" as a function parameter.
Now your method is functional and testable, i.e. functional testing.
So really, you can design your class to later be tested, while not suffering all the negatives of creating a method for the sole purpose of testing.
I hope this helps. This wiki gives a good overview of testing in programming, in general: http://en.wikipedia.org/wiki/Software_testing
Yes. First, it makes your classes bigger - every property or field used by your tests must be carried around in memory everywhere your class is used. Secondly, it adds a bunch of public methods and properties to the class, which would be visible to things like your factories.
If you want your tests to be right together with your class, just put them in the same file:
public class Foo : IFoo
{
...
}
[TestFixture]
public class Foo_Tests
{
...
}
精彩评论