Starting with the Summer ’13 release of the platform, Apex test methods need to be created in test classes.  (A “test class” is one marked with the @isTest annotation.)  Test methods will no longer be able to compile in the same class as your regular executable code.  This is a departure from the pattern we’ve used for the past six years, and I am sure many people are scratching their heads and asking why we are enforcing this new coding pattern.

To start, let me reassure you that your existing code does not need to change.  If you’ve created tests in executable classes, these will continue to compile in the Apex version in which they were created.  The new pattern needs to be followed for new classes written in v28.0 and above, and for any classes for which you change the version from an older version to v28.0 or later.  The check is done at compile time, so if you don’t need to change anything or recompile anything, you will not notice any difference.

There is a direct benefit to this change in our caching strategy, and this is the first part of some new enhancements to our testing framework you’ll see over the coming year.  But first, some background…

We’ve Come A Long Way

So, why the new pattern? This change is a part of our ongoing effort to support the growth of Apex.

Thanks to everybody out there reading this, Apex is growing like crazy.  We are running almost 6 billion Apex transactions a month.  This is more than double what we saw a year ago.  This kind of volume was way beyond the horizon when the language was initially created, when it was conceived as a database triggering mechanism.  Now that this volume is here, it is becoming necessary to modify some of the original assumptions and make changes like this one.

The development team spends a large amount supporting the growth in Apex transaction volume.  With every release, we verify that you still see equal or better performance to what you saw in the past.  In addition, we must be prepared for another doubling of transaction volume every several months.  We are committed to staying ahead of what you create – and you have proven time and again to be very creative and prolific.

Cache is King

One key aspect to language performance is the caching of your code for execution.  If we had to load every class for every transaction, things would not go so quickly.  Instead, we store an executable form of your class in memory to use when you next need it.  The cache is smaller than all code combined, so some percentage of requests miss the cache and have to load classes from deeper storage.

The smaller everyone’s cached classes are, the more stuff we can fit in the cache.  More stuff in the cache means fewer misses; fewer misses means faster performance for everyone.  Faster = Better, if the elementary school kids in those AT&T commercials are to be believed.

Test methods are rarely executed, relative to how often executable methods are run.  However, they are still compiled as part of the cached class, which means they are taking up valuable cache space.  Moving all test methods to test classes means they’ll only be in the cache when you are testing.  This segregation of infrequently-used code (test methods & supporting code) from frequently-used code (executable code) will help us scale to meet the growth you are driving.

Making Testing Easier

In addition to helping achieve better performance, this change is the first of several testing-related changes we are planning to make testing your Apex code more efficient.  By more efficient I mean more efficient to create tests AND more efficient to run tests.  Here are some of the planned improvements you should see in the coming year or so.

Please Note!  The following list is forward-looking and might not happen as quickly as you or I would like.  Crises occur and resources get redirected from time to time; our number one priority is service reliability.  As cool as these new features will be, they are second-fiddle to any major issues that arise.  Imagine giant safe harbor statement projected on the sky.

Test-to-Parent class linking – You will be able to have a test class explicitly related to regular class or trigger.  Currently, many of you have implicit connections by adding a suffix or prefix to a class name, but this doesn’t make managing or interacting with your codebase all that much easier.  The explicit linkage will allow us to do better UI treatments for related classes.  A direct mapping will also make the upcoming Fast Deploy feature much easier to utilize.

Shared Data Setup Methods – Rather than creating reference data for every individual test method, you will be able to specify a data setup method to be shared among all the test methods within a class.  Since an average of 70% of testing time is spent setting on database operations, this should make your testing run much faster without needing to reduce the reference data being used for individual tests.

Improved Data Creation – The Test.loadData method has probably saved many of you lots of code space in creating test data.  We will be iterating on this, offering relative date field values and generic object population.

All of these items will depend on having tests be independent of executable code, so they can be run in a different manner.  At some point, you may need to migrate some of your old tests to the new pattern to take advantage of these features.

Help Me Help You

Migrating your test methods and supporting test code to test classes will be beneficial for the platform, but it will also be beneficial to you.  As you streamline your code, you will see better cache hit rates and thus better performance for your org.  As everyone streamlines their code, everyone’s org will get a lift from increased efficiency.  You don’t need to migrate test methods immediately, but I encourage you to consider this new pattern when you are making changes to existing code.

With your help, we can continue our mission of providing a scalable execution environment that can support all of what you and your colleagues create.

Get the latest Salesforce Developer blog posts and podcast episodes via Slack or RSS.

Add to Slack Subscribe to RSS