Use of @IsTest versus testMethod and location of test methods in classes

From http://www.salesforce.com/us/developer/docs/apexcode/Content/apex_qs_test.htm?SearchType=Stem

This class is defined using the @isTest annotation. Classes defined as such can only contain test methods. One advantage to creating a separate class for testing as opposed to adding test methods to an existing class is that classes defined with isTest don't count against your organization limit of 3 MB for all Apex code.

The advantage to using separate test classes is that they do not count against the limit of the total amount of apex in your org (although this is a soft limit and thus not a overly compelling reason).

You can also include non-test utility methods in classes marked as @isTest and (this is the compelling part) they do not need to be covered by tests themselves, and can only be called from inside of test methods! Very useful for data generation methods that are not needed in production code.


I always use @isTest at the class level for the reasons stated in @ca_peterson's answer.

For individual test methods, I prefer @isTest, on the line above the method declaration, like so:

@isTest
static void TestSomething() { ... }

//instead of this:
static void testMethod TestSomething() { ... }

Why? If I need to disable a test, I can just comment out the @isTest line like so:

//@isTest
static void TestSomething() { ... }

And suddenly, the method isn't a test method anymore, it's just a "helper", and won't run as part of the test suite. This is handy if you're trying to isolate a problem in a particular test and want to temporarily disable a slow test, or tests that generate lots of log output. If needed, a quick seach/replace changes all test methods to non-test methods, and I can uncomment just the test I'm working on.


One reason you might co-locate the unit tests with the apex code itself is if you need access to private properties. This is something I run up against from time to time with Visualforce controllers, in that I want to inject some values into the private properties in order get the controller into the correct state to execute the test.

As stated above, this does count against the apex character limit, but I find its a trade off between that and writing code whose only purpose is to allow values to be stored in a private property when executing in the test context.