arkina
arkina

Reputation: 1029

Is there anything wrong with putting test methods in the same class you're testing?

Is there anything wrong with putting test methods in the 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#.

Upvotes: 8

Views: 432

Answers (10)

Rick
Rick

Reputation: 709

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

Upvotes: 1

Roy Dictus
Roy Dictus

Reputation: 33139

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!

Upvotes: 2

Cirdec
Cirdec

Reputation: 24156

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
{
    ...
}

Upvotes: 0

Ian Gilham
Ian Gilham

Reputation: 1954

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.

Upvotes: 2

Paul Alan Taylor
Paul Alan Taylor

Reputation: 10680

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.

Upvotes: 2

RQDQ
RQDQ

Reputation: 15569

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.

Upvotes: 8

JaredPar
JaredPar

Reputation: 754715

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

Upvotes: 21

Grant Thomas
Grant Thomas

Reputation: 45083

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.

Upvotes: 1

jgauffin
jgauffin

Reputation: 101150

Yes. It would be breaking Single Responsibility Principle. It will reduce the readability. You add a dependency to your testing framework.

Upvotes: 6

Dan Puzey
Dan Puzey

Reputation: 34198

Biggest downside: you have to ship your tests, and they potentially become part of your public API.

Upvotes: 4

Related Questions