36

Is there any advantage to using the older testMethod keyword to identify test methods or is it better to use the @IsTest annotation?

Does the location of these test methods have any significance? E.g. Either being included within the definition of the class being tested or defined in a separate class.

0

8 Answers 8

32

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.

3
  • 6
    Just noting here that individual methods annotated with isTest, outside of an isTest annotated class, do count towards the org apex limit. Aug 22, 2012 at 3:09
  • 4
    It is worth noting that with Summer `13 (28.0) you won't be able to include test methods in the class body. They need to be in a dedicated test class. See Apex Test Code Segregation. Also, the article indicates there are performance benefits to keeping the test cases in separate classes. Apr 23, 2013 at 20:26
  • 1
    @DanielBallinger Thank you for sharing that blog post! I hadn't known about these changes, and the article does a great job explaining things. Thank you!! May 11, 2013 at 1:37
19

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.

1
  • Certainly a good reason. With testMethod I do a find and replace from 'testMethod' to '/*testMethod*/' and vice versa. One day they will hopefully let us run single test methods. Jan 28, 2014 at 23:18
13

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.

4
  • I hadn't thought of this and had definitely struggled with this in the past. In the end, I opted for lower test coverage as I didn't want to arbitrarily change my code just to make it "testable". I've never heard a convincing argument for occasional use of test methods inside of normal classes until this.
    – pchittum
    Oct 26, 2012 at 8:12
  • 1
    Quick note - Summer 13 now lets you access Private variables in test with a new annotation... Jun 20, 2013 at 21:37
  • Yes, they have solved this problem now, hence you can't colocate tests with your code from the Summer 13 of the API onwards. Jun 21, 2013 at 10:35
  • Now you can use the @TestVisible annotation to access private properties.
    – Eduard
    Jul 24, 2018 at 13:17
7

I tend to agree with @ca_peterson in the use of @istest at the class level.

Using testmethod or @istest on the method level (within a test class) is interchangeable. You'll probably find yourself using @isttest more often, as that lets you specify the oninstall and seealldata attributes as needed (overriding the defaults).

But, if you have a bunch of test classes using the testmethod syntax, there's no reason to waste time changing them over.

7

As noted in the Apex Developer Guide on IsTest Annotation:

The testMethod keyword is now deprecated. Use the @isTest annotation on classes and methods instead.

So to answer your first question, there is now an advantage to using @IsTest rather than testmethod, namely that the former is still supported.

3

One benefit we've had from keeping the tests in a separate class is that you can have one engineer actively working on the class, while another is working on the tests. In an organization where development and unit testing are done by separate people, it makes coordinating your work (including using Git to manage your codebase) a lot easier.

I'll typically email my testing counterpart with my planned changes, and he can work on the unit tests while I'm working on the class. Either one of us can finish first, check code into Git, and wait on the other to finish before testing.

4
  • This seems like it would make it incredibly hard to use a Test Driven Development model. Aug 31, 2012 at 17:30
  • @PeterKnolle: does keeping test methods inside of the class make it easier? I'm not sure I understand your comment. If you want TDD, write the tests first and then code to them. Or, write the class interface (methods with dummy returns), write the tests, and then complete the class.
    – tomlogic
    Aug 31, 2012 at 17:37
  • Usually when I use TDD I write the failing test case and then write the code to make it pass and refactor as such. I guess I've never really thought about having someone else write the test, me code to pass, then me and them refactor together? I wasn't referring to the location of the test method as much as the two separate people. I wasn't as familiar with that approach. Aug 31, 2012 at 17:39
  • 1
    In our company, someone else writes unit tests to ensure that the original developer isn't overlooking anything. If you're not thinking of a potential boundary case as you write the original code, there's a good chance you'll miss it when writing the test as well.
    – tomlogic
    Aug 31, 2012 at 17:41
3

As per developer Guide:

The testMethod keyword is now deprecated. Use the @isTest annotation on classes and methods instead. The @isTest annotation on methods is equivalent to the testMethod keyword

Note: testMethod doesn't have any impact on the count of apex character limit like it's mentioned in the other post the only thing here is that testMethod is now deprecated and @isTest the new one which we all should prefer going forward. I've tested this by removing testmethod code and there was no change in the character count of apex.

0

As @ca_peterson says @isTest doesnt count towards organization's total Apex code limit.

Here is the link for testing best practices. Just in case you need..

https://developer.salesforce.com/page/File:Apex_code_testing_webinar.pdf

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .