+ Start a Discussion
Eager-2-LearnEager-2-Learn 

Intro to move my first class to production?

Hi,

 

I have been reading about rules around at least 75% of code must be tested successfully before it can be moved to production.  My problem is I am imagining the process and I am sure by experimenting I will figure it out; however, when dealing with a production environment I do not like the idea of experiementing.

 

QUESTIONS:

  1. When I move the class and the test class to production is it automically active code or do I have to activate it?
  2. Do I have to keep the Test Class code in production all the time with the associate class?
  3. If I have a class that has temporary variables in the class code just for testing so that I can get 100% code coverage then move it to production will I be able to comment those variables out in the test class and controller class after I move it to production? 

If the answer is no than I may need some help on how to test a class that I need to know the new record id.  The code below is a portion of the controller and the second code snippet is a portion of the test class that tests the controller.

 

CONTROLLER CLASS:

// This class clones an opportunity and all related partner records
public class OppCloneWithPartnerRecsController {
 
    //added an instance varaible for the standard controller
    private ApexPages.StandardController controller {get; set;}
     // add the instance for the variables being passed by id on the url
    private Opportunity opp {get;set;}
    
    // set the id of the record that is created -- ONLY USED BY THE TEST CLASS
    public ID newRecordId {get;set;}    
    // set the force error  
    public boolean forceError { get;set; }
    //-------------------------------------------- ONLY USED BY THE TEST CLASS

 
    // initialize the controller
    public OppCloneWithPartnerRecsController(ApexPages.StandardController controller) { 
        //initialize the stanrdard controller
        this.controller = controller;
        // load the current record
        opp = (Opportunity)controller.getRecord();       
    }
 

 

TEST CLASS:

...

        Test.startTest();

//        ext.forceError = false;

        
        // call the oppCloneWithPartners method
        PageReference ref = ext.oppCloneWithPartners();
        // create the matching page reference
        PageReference redir = new PageReference('/'+ext.newRecordId); 
 
        // make sure the user is sent to the correct url
        System.assertEquals(ref.getUrl(),redir.getUrl());
 
        // check that the new Opp was created successfully
       Opportunity newOpp = [select id from Opportunity where id = :ext.newRecordId];
        System.assertNotEquals(newOpp, null);
        // check that the line item was created
        List<Partner> newItems = [Select p.Id From Partner p where p.OpportunityId = :newOpp.id];
        System.assertEquals(newItems.size(),2);
 
        // Switch back to runtime context
        Test.stopTest(); 
    } 

...

 

 

Best Answer chosen by Admin (Salesforce Developers) 
kwukwu

Okay I examined the code you based your own controllers on. I think the code is fine. Personally I would have written a class called ClonePurchaseOrder which handles the cloning of the class for you but it's a pretty simple action. Look at this example first: http://www.salesforce.com/us/developer/docs/pages/Content/pages_controller_error_handling.htm

 

In your test class you want to first insert a new purchase order record.

 

PurchaseOrder po - new PurchaseOrder();

po.property = blah blah blah

.....

insert po

Okay DONE.

 

Now we want to set the current page we are testing. We also want to set the ID parameter for the page. Now instantiate a new controller and start the test.

 

The problem with the example you are using is that the action parameter in the <page> tag automatically starts the cloning process RIGHT when the page loads.

 

So all I can really assume you can test is whether or not you got re-directed properly.

 

At this point your current page *should* be the new page. So try this call:

 

ApexPages.currentPage();

Check and make sure you got re-directed properly. Grab the new record and assert that they are true clones.

All Answers

kwukwu
  1. When I move the class and the test class to production is it automically active code or do I have to activate it?
  2. When you move a class into production it is automatically active. Unlike triggers, classes cannot be deactivated. At least it doesn't look like they can be deactivated.
  3. Do I have to keep the Test Class code in production all the time with the associate class?
  4. Yes, when you deploy production classes your test code will also be deployed along with the production class.
  5. If I have a class that has temporary variables in the class code just for testing so that I can get 100% code coverage then move it to production will I be able to comment those variables out in the test class and controller class after I move it to production? 
  6. Test classes do not count against your code limit so they can be as long as you need them to be. Also, test classes do not change any data in your Org. Test classes run just like code runs in execute anonymous so nothing is saved to the database.



kwukwu

Also, is there some way your class can be written without certain properties that are required for the test class? For example, when you insert a new record into the database, the Id field is usually populated for you.

 

Account newAccount = new Account();

newAccount.Name = 'ABC Corp';

insert newAccount;

 

newAccount.Id <<<<< new Id of record.

 

Generally speaking I have never needed to add actual variables into my classes for testing purposes. Test classes should run without any need to modify production code. Otherwise it's like you are building something to make sure your test class works versus writing your test class to make sure your code works.

Eager-2-LearnEager-2-Learn

Thank you for answering my questions.  I just have one that I need clarity on.  If my controller class has a temporary variable and logic that helps me get my code coverage requirements met and I uncomment that variable and IF statement then try to move it to production; will the production environment see it as not meeting the code coverage limits?  Or once I moved the code to production can I then modify the controller class code and comment the variable out and IF statement out.

 

I just don't see any other way to test my controller without putting a tempory variable in it.  Did you see the snippets of the controller code and the test script?  I am new to all of this an create code by gather pieces of suggestions.  Tough but I am making progress thanks to others help.

kwukwu

The way code coverage works is that it looks at the total lines of code that are NOT commented out. Then it runs your test class (or methods) and checks which lines have been "touched". As long as a line has been touched by a test class, it is considered covered.

 

However, you should of course use System.assert methods to make sure you are getting what you expect.

 

Can you explain to me what your class is trying to do? If you are writing classes correctly, there should be no reason to have to write anything test related in any of your classes. The only situation I can really think of that you *might* need to do this is if your class makes a web callout to an outside service. Apex Tests cannot do callouts.

Eager-2-LearnEager-2-Learn

I have a controller class that clones an opportunity and related partner records and a VF page that uses the Opportunity and extention using my controller class.  The VF page is simply to show the cloned record once it is created by the my controller class code.  The following link helped me to produce my code.  The link shows how to clone a product and related line items.  I took this code and create my cloning opportunity and related partner records.  If you look at that code and test script link you can see why I am doing what I am doing.  Or I can add my code and test code to this discuss is that is better for you to help me.

 

I really appreciate your help.

Eager-2-LearnEager-2-Learn

At this point if I am understanding some of what you are saying the code portion below is what I think we should focus on and discuss.  How can I get the record ID from the record that is created in the TEST script into the Controller code?  I think that is why the temporary variable is used in the Controller class?  Again, I used this linke to help me create my code: http://blog.jeffdouglas.com/2009/11/19/apex-deep-clone-controller/

 

 

 

// Construct the standard controller
ApexPages.StandardController con = new ApexPages.StandardController(opp);

// create the controller
OppCloneWithPartnerRecsController ext = new OppCloneWithPartnerRecsController(con);

// Switch to test context
Test.startTest();

ext.forceError = false; \\ USED to test Exeption Logic so I get coverage for it!!!

// call the oppCloneWithPartners method
PageReference ref = ext.oppCloneWithPartners();
// create the matching page reference
PageReference redir = new PageReference('/'+ext.newRecordId);

kwukwu

The question is, what kind of exceptions will cause errors to occur? What scenarios are you checking for?

 

Imagine the class you are using to clone a record is like a black box. You have no idea what is going on in the class. All you know is what methods you have to access the class. Imagine if I wrote the class and I gave it to you to test and you were not allowed to change anything in my code.

 

Your test scenarios should test all the different cases where your logic handles errors.

 

How would you test it?

 

Every test should be able to run without any existing records in the database. Your test should be like this:

 

// Step 1: setup an existing account record

 

// Step 2: set the current page and clone the record we just created using the controller

 

// Step 3: check to see if the new cloned record is the same as the existing record using System.Assert.

Eager-2-LearnEager-2-Learn

I fully understand what your are suggesting and it makes sense; however, I have reached a road block on how to make it actually happen and that was why I pasted the code in hopes that you or someone can help me with the broken piece.  (That's all around your #2).

 

As far as testing the exception that is in the black box (my class) I only have a basic error routine that rolls back all changes if any error occurs.  However, to get that code to execute causes the test case to have a failure and I thought you could not deploy code and test scripts unless they are error free?

 

I appreciate your patience with me.

kwukwu

Okay I examined the code you based your own controllers on. I think the code is fine. Personally I would have written a class called ClonePurchaseOrder which handles the cloning of the class for you but it's a pretty simple action. Look at this example first: http://www.salesforce.com/us/developer/docs/pages/Content/pages_controller_error_handling.htm

 

In your test class you want to first insert a new purchase order record.

 

PurchaseOrder po - new PurchaseOrder();

po.property = blah blah blah

.....

insert po

Okay DONE.

 

Now we want to set the current page we are testing. We also want to set the ID parameter for the page. Now instantiate a new controller and start the test.

 

The problem with the example you are using is that the action parameter in the <page> tag automatically starts the cloning process RIGHT when the page loads.

 

So all I can really assume you can test is whether or not you got re-directed properly.

 

At this point your current page *should* be the new page. So try this call:

 

ApexPages.currentPage();

Check and make sure you got re-directed properly. Grab the new record and assert that they are true clones.

This was selected as the best answer
Eager-2-LearnEager-2-Learn

To be clear the code you are referening is not my code.  My code portions where pasted in this discussion stream.  I used that code to create my cloning of an opportunity and related partner records.  However, with your patience with me I was able to use your suggestions and make a test script that checks 90% of the code (passing to production).  I think it is good enough to get the code to production.  In addition to the required code scripts (75% or better code coverage) I have manually cloned records via the new custom clone button that calls the class and all is working as expected.

 

Thanks again.

kwukwu

I hope I was able to help you. Good luck.

Eager-2-LearnEager-2-Learn

You truly have helped me a great deal.  I am scheduled to take the DEV401 class in June in Matreo, CA so I hope that help me even get better as well.

 

If I would not be so pushy to ask how could I possibly validate the catch routine in my Controller class without causing the test to fail.  If I hit that part of the code wouldn't that be a failure and therefore cause the test script to not be valid to move to production? 

 

As previously stated, I am testing 90% of coverage now so it is not a concern to get my code to production but what about as I get more complicated Error Exceptions with many lines of code, that could potentially change my percentage of code coverage to a point that I would not luck out like I am now.

 

The code is this.... which is the 11% not being covered.

} catch (Exception e){ 
     
        Database.rollback(sp);
        ApexPages.addMessages(e);
        return null;
     }

 

 

kwukwu

The problem with the try catch is that you are trying to catch a very GENERAL exception (in fact, the highest level exception). I think it would be very hard to test this exception because it's so general. Instead, we should have multiple try/catch blocks to check different types of exceptions. In this case you will probalby want to test database exception types.

 

Once you know what kinds of exceptions you can expect, you can then try to re-create those scenarios in your test class. Otherwise it's too hard to know what we need to test. Of course the best test harness is the one that tests every possible case...but that would take a long time to code.

 

Take a look at this article: http://wiki.developerforce.com/index.php/How_to_Write_Good_Unit_Tests

 

DEV401 is a great class. I would highly recommend DEV501 as a follow-up to 401 because 501 has more coding related material. 401 is more admin related.