function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
jvolkovjvolkov 

Books on Testing APEX

I have went through the Apex Language Reference and the Force.com Cookbook but could not find any in depth explanation of how to test Apex code.
 
The only thing I understand from reading these two sources is that in order to deploy to Apex to production at least 75% of the code must be covered in the test.  Then they give a couple of examples of testing code.  But there doesn't appear to be any explanation as to why the test examples use the keywords and methods that they are using.
 
What other sources are there that can further explain in depth how to test Apex?
 
-Thanks
sfdcfoxsfdcfox
There's some information in the Apex Language Reference, but it's not specifically its own chapter or bookmark. Here's the idea in a nutshell:
 
1) Initialize any data that needs to be set up to effectively test the code (i.e. if you're processing an Account trigger, you need create some accounts to work with). Use a DML call if you need a pre-created record (i.e. if testing an "update" or "delete" call).
 
2) Use the Test.StartTest() to switch to "testing mode". This lets the environment know that you're testing something, and switches the context governor limits to that mode (i.e. triggers have lower limits than webservice methods).
 
3) Perform an action that will trigger the code. For triggers, use insert, update, delete, etc. For webservice methods or other methods, simply call the method. If you have error checking,  you should use a try/catch block to make sure your test passes.
 
4) Use the Test.StopTest() to switch back to the original context. You can use System.Assert or System.AssertEquals to validate the results of the test; you'll want this code to run outside the testing zone (after Test.StopTest()) so you don't give your test results invalid numbers or other possible errors.
 
There's a few key things you need to know:
 
- The keyword testMethod lets Salesforce know that it is a method for testing.
- The Test.StartTest() and Test.StopTest() should be used to ensure that you're not passing when you shouldn't (i.e. because of governor limits).

Other than those two requirements, it is up to you to determine how to test the method; this requires thinking about what your code does and purposefully trying to reach each and every line of code. For example, if you have an "if" statement, make two records or function calls, etc-- one that takes the true branch, and one that takes the false branch. You might need to make If you use try/catch blocks, use one set of records that won't cause the try/catch block to trap an exception, and one that will.
 
There's no one right way to test your code, but there are plenty of wrong ways. Your test methods should make sure of two things: That no unexpected errors occur, and the the logic works the way you expect.
jvolkovjvolkov

That was a very good explanation, thank you.  I now feel I understand the logic of what I am trying to accomplish much better. 

I will read up on the try/catch and assert keywords as I am still not familiar with the syntax of these.

One immediate question I have is do you want to use Test.StartTest() when testing a trigger and the testMethod when testing a class, both at the same time?  When writing something like public static testMethod void test1 () {  } in a trigger there is an error "Only top-level class methods can be declared static".

-Thanks

sfdcfoxsfdcfox
TestMethods have to be in a class, so you would first create a trigger, then create a class to test the trigger. Usually, you will place the testMethod in the class that contains the logic for the trigger, but that is not a requirement. As an example:
Code:
// trigger
trigger accountIndustryUpdate on Account (before insert, before update)
{ accountIndustryUpdateClass.UpdateAccounts(Trigger.new);
}

// class
public class accountIndustryUpdateClass {
  public static void UpdateAccounts(Account[] accounts)
  { for(Account acc:accounts)
    { if(acc.Industry==null)
      { acc.Industry='Unknown';
      }
    }
  }

  public static testMethod void testAccountIndustryUpdateClass()
  { Account[] accounts = new Account[0];
    accounts.add(new Account(Name='Acme'));
    accounts.add(new Account(Name='salesforce.com',Industry='CRM'));
    Test.startTest();
try {
Database.insert(accounts);
} catch(DMLException e)
{
} Test.stopTest(); accounts = [select id,name,industry from account where id in :accounts]; // Both accounts should have been created. System.assertEquals(2,accounts.size()); for(Account acc:accounts) { if(acc.Name=='Acme') { System.assertEquals('Unknown',acc.Industry); } if(acc.Name=='salesforce.com') { System.assertEquals('CRM',acc.Industry); } } } }

Now, of course, this is arbitrarily useless code (and may be syntaxically incorrect, as this is only an example), but it does provide an example of how a testMethod would work on a trigger. As you can see, I start by creating two accounts, one to test and make sure that industry would be updated, and one that makes sure that industry would NOT be updated (because it is not blank).
 
So the lesson here is that my code should have 100% coverage and pass all assertions. If it does, my code works well and is ready for production, otherwise I would need to debug my code and cycle back until have 100% coverage and no assertions. You should have as many assertions as necessary to test each possible branch or loop or anything that might go wrong. In my example, three assertions are required: 1) were all the accounts created, 2) did the one account have it's industry updated, and 3) did my other account NOT have it's industry updated. I use an empty catch statement because I do not care about the DML exceptions (there is an assertion later for that purpose) so that my test will run completely. Uncaught exceptions may result in incomplete code coverage.
 
I hope this helps out a bit in whatever it is you might be trying to do. If possible, you should consider writing your testMethod BEFORE you ever write a line of code. I read about this once somewhere. Ideally, if you can write unit tests before the code, you will better understand what the code needs to do. It should also shorten development time because any errors will be immediately obvious. Should you write the testMethod after the fact, you may not test your code as fully as you would beforehand, possibly because you might subconsiously "ignore" that error when you write the testMethod (you already wrote the code, and so you think it is already correct, and may leave out significant checks). I read about this in an article somewhere, although I can't recall offhand.
okaylah52okaylah52
I just ran into this posting. Here is the wiki site that explain Apex testing An Introduction to Apex Code Testing