+ Start a Discussion
Kenji775Kenji775 

How do you organize your testing classes?

This is more of a best practice type question. For a long time, I had a seperate testing class for every trigger/component/class. This got to be kinda bulky, and I found I was repeating a lot of code (lots of triggers revolved around creating the same types of objects, so many of my testing classes where essentially the same thing, save a few asserts). So I thought it would make sense to combine all my testing classes into one massive test class. Easier to maintain (from my point of view), and made it so I just created my test objects, ran my various asserts and coudl easily test all my code.

 

Now of course, that idea is failing. I have to create too many objects, and run too many different tests for them all to be contained in one file. But the fact that there is a lot of shared code is still true. So now I'm thinking about breaking it into testing classes by the object they test. I'm really fairly new to OOP, so I know there is a more eloquent way of doing it, probably creating some basic classes, and extend them for the various objects I need to test or something. Before I do another rewrite though I just wanted to see how the community does it. Thanks for any insight.

rungerrunger

No, you're on the right track.  There's no hard and fast rule for how to categorize your tests into different test classes.  You can certainly factor out common initialization code into static methods that you call from multiple tests.  There's nothing in Apex akin to the TestCase base class in JUnit, with its setup/teardown methods (that's something I'd like to add at some point).

 

Basically, I think you're already going in the right direction.

 

Rich

Kenji775Kenji775

So you are thinking basically one testing class for each kind of object makes sense then?

My issue right now is that I'm running into governer limits on my big test class, so I need to break it down. By object probably makes the most sense right?

rungerrunger

Which governor limit?  Just the size of the class?

 

By object is one common approach, yes.  It really kind of depends on what your app looks like.

Kenji775Kenji775

In this, case it's too many SoQl queries (101). There is just so much querying going on while testing all the triggers it explodes. Just happened today after I tried to add one more test case.

Jeremy.NottinghJeremy.Nottingh

I'm a little confused. You have one big class for testing each object, but you still have lots of individual testmethods inside that class, right? It seems like you shouldn't run into governor issues, since each testmethod runs within its own context. 

 

If your one big class is also one big testmethod, that will definitely cause problems.

 

Jeremy

AlexPHPAlexPHP

The essence of test classes is that you break down each test method to only test a single unit of your code logic... hence the term "unit test".

 

You can try to combine your test setups into a single class.  By that, I mean to put the code used to set up your test environment into a class that can be shared by many other test classes.

 

Then in your test class, you can call just the test setups that you need to test a particular unit of code.

 

Each test method of your test class should be testing a single unit of code logic.  By doing so, you will avoid needing to do excessive querying and going over the governor limits.

 

Hope this makes sense.

Kenji775Kenji775

Jeremy,

It's one big class, cause I suck at programming.

It is attached so you can see what I mean.

 

 

@isTest
private class unitTests 
{
	static testMethod void testData()
	{
		
        //create a new date object so we can easily insert it
        DateTime dT = System.now();
        Date myDate = date.newinstance(dT.year(), dT.month(), dT.day());

        //make an account so we can attach a contact to it
        Account TestAccount = new Account(name='My Test Account', Tax_ID__c='99-9999999');	
               
        //Now make a contact, so we can attach him as a respondent a few times
        date birthdate = date.parse('03/21/1988');
        Contact ContactGuy1 = new Contact(Firstname='Frank', 
        									Lastname='Jones', 
        									AccountID=TestAccount.ID, 
        									of_PSA__c=0, 
        									of_No_shows__c =0, 
        									of_Cancellations__c =0, 
        									of_Disqualified__c =0, 
        									of_Participations__c =0, 
        									MailingCity='coon rapids', 
        									MailingCountry = 'us', 
        									MailingState='MN', 
        									MailingStreet='432423 nowhere street', 
        									MailingPostalCode='45543',
        									phone = '7625324246',
        									birthdate = birthdate);

        insert ContactGuy1;
 
        Contact ContactGuy2 = new Contact(Firstname='Bob', Lastname='Jones', AccountID=TestAccount.ID, of_PSA__c=0, of_No_shows__c =0, of_Cancellations__c =0, of_Disqualified__c =0, of_Participations__c =0, MailingCity='coon rapids', MailingCountry = 'us', MailingState='MN', MailingStreet='11021 bittersweet street', MailingPostalCode='55433');    

        insert ContactGuy2;
        
	    RecordType ParentRecordType = [select id from RecordType where name = 'FPI Parent Campaign'];
	    RecordType ChildRecordType = [select id from RecordType where name = 'FPI Child Campaign'];		
		RecordType UmbrellaRecordType = [select id from RecordType where name = 'FPI Umbrella Campaign'];

		Struct myStruct = new Struct('Hey','This is a struct');
		
        //Create the Umbrella Campaign
        Campaign UmbrellaCampaign = new Campaign(name='My Test Account Campaign Master', 
                        Incentive_Amount_Paid_for_Study__c=20.00, 
                        Time_Slot__c='MASTER', Status='Active', 
                        Recruits_Per_Time_Slot__c=1, 
                        IVR_Description__c = 'Test',
                        Respondent_timeout__c = myDate,
                        Project_Manager__c = ContactGuy1.id,                           
                        RecordTypeID=UmbrellaRecordType.id);
        
        insert UmbrellaCampaign;
        	
        //Create the Parent Campaign
        Campaign ParentCampaign = new Campaign(name='My Test Account Campaign Master', 
                        Incentive_Amount_Paid_for_Study__c=20.00, 
                        Time_Slot__c='MASTER', Status='Active', 
                        Recruits_Per_Time_Slot__c=1, 
                        IVR_Description__c = 'Test',
                        Parentid=UmbrellaCampaign.id,
                        Respondent_timeout__c = myDate,
                        isActive = true,                           
                        Criteria_1_Quota__c = 1, 
                        Criteria_2_Quota__c = 1, 
                        Criteria_3_Quota__c = 1, 
                        Criteria_4_Quota__c = 1, 
                        Criteria_5_Quota__c = 1, 
                        Criteria_6_Quota__c = 1, 
                        Criteria_7_Quota__c = 1, 
                        Criteria_8_Quota__c = 1, 
                        Criteria_9_Quota__c = 1,
                        Criteria_10_Quota__c = 1,
                        Update_Respondent_Status__c = true,
                        Update_Status_To__c = 'active',
                        Project_Manager__c = ContactGuy1.id,,
                        RecordTypeID=ParentRecordType.id);
        
        insert ParentCampaign;

		
		        
        //Create the Child Campaign
        Campaign ChildCampaign = new Campaign(Parentid=ParentCampaign.id,
        									  name='My Test Account Campaign', 
        									  Time_Slot__c='1pm', 
        									  Incentive_Amount_Paid_for_Study__c=20.00, 
        									  Status='Planned', Recruits_Per_Time_Slot__c=1, 
        									  IVR_Description__c = 'Test', 
        									  RecordTypeID=ChildRecordType.id,
        									  Project_Manager__c = ContactGuy1.id);
        
        insert ChildCampaign;
 


        //Create a link category
        Link_Category__c LinkCategory = new Link_Category__c(Name = 'About', 
                                                Link_Class__c = 'about',
                                                Label__c = 'about', 
                                                HTML_ID__c = 'about',
                                                CSS_Class__c = 'about');
        insert LinkCategory;
        
        //Create link item
        Link_Item__c LinkItem = new Link_Item__c(Name = 'home',
        										   Link_URL__c = 'http://www.google.com',
        										   Link_Category__c = LinkCategory.Id);
        insert LinkItem;										   
        										                                               
        
        
        
        //***************** TEST PreventDupeCases trigger ********************************
		//Try to create the same case twice. Second one should error.
		Case case1 = new case(contact = ContactGuy1, status = 'Open', Origin = 'Web', subject='This is a test case. Eat face');
		insert case1;
		
		
		Case case2 = new case(contact = ContactGuy1, status = 'Open', Origin = 'Web', subject='This is a test case. Eat face');
		try
		{
			insert case2;
		}
		catch(Exception e)
		{
			system.debug('Adding 2nd case failed. This is good');
		}
		//***************** TEST PopulateRespondentInfo Trigger ********************************
		//Those resondents we made above should have caused the FlagRespondentsAsRecentlyTested
		//trigger to fire. That means those contacts should have the  recently_tested__c flag to true
		
		//add two respondents to the parent campaign        
        
        Contact contact1details = [select recently_tested__c, pid__c, id from Contact  where id = :ContactGuy1.id];
        
        //Insert the first contact using a PID instead of inserting a contact ID. The trigger shoudl use the PID to look up the contact ID and fill it in.
        Respondent__c Respondent1 = new Respondent__c(Master_Campaign__c=ParentCampaign.id, Child_Campaign__c=ChildCampaign.id, Respondent_PID__c = contact1details.pid__c,      
                Criteria_1_Met__c = 'yes', Criteria_2_Met__c = 'yes', Criteria_3_Met__c = 'yes', Criteria_4_Met__c = 'yes', Criteria_5_Met__c = 'yes', Criteria_6_Met__c = 'yes', Criteria_7_Met__c = 'yes', Criteria_8_Met__c = 'yes', Criteria_9_Met__c = 'yes', Criteria_10_Met__c = 'yes');    
        insert Respondent1;
        
        //Insert the second contact using just a regular contact ID, so the other half of the trigger will fire, that should fill in the PID.
        Respondent__c Respondent2 = new Respondent__c(Master_Campaign__c=ParentCampaign.id, Child_Campaign__c=ChildCampaign.id, Respondent__c=ContactGuy2.Id, Respondent_PID__C = ContactGuy2.PID__c,
                Criteria_1_Met__c = 'no', Criteria_2_Met__c = 'no', Criteria_3_Met__c = 'no', Criteria_4_Met__c = 'no', Criteria_5_Met__c = 'no', Criteria_6_Met__c = 'no', Criteria_7_Met__c = 'no', Criteria_8_Met__c = 'no', Criteria_9_Met__c = 'no', Criteria_10_Met__c = 'no');    
        insert Respondent2;

        //Insert the second contact using just a regular contact ID, so the other half of the trigger will fire, that should fill in the PID.
        try
        {
	        Respondent__c Respondent3 = new Respondent__c(Master_Campaign__c=ParentCampaign.id, Child_Campaign__c=ChildCampaign.id, Respondent_PID__C = '123412',
	                Criteria_1_Met__c = 'no', Criteria_2_Met__c = 'no', Criteria_3_Met__c = 'no', Criteria_4_Met__c = 'no', Criteria_5_Met__c = 'no', Criteria_6_Met__c = 'no', Criteria_7_Met__c = 'no', Criteria_8_Met__c = 'no', Criteria_9_Met__c = 'no', Criteria_10_Met__c = 'no');    
	        insert Respondent3;   
        }
        catch(Exception e)
        {
        	System.debug('Inserting 3rd Respondent Failed. Caught be bad PID');	
        }    
             
        //***************** TEST Payment Duplicate Preventor ********************************
        Payments__c payment1 = new Payments__c(Contact__c = ContactGuy1.id, Respondent_Number__c = 5, status__c = 'tested', Study__c = ChildCampaign.id);
        Payments__c payment2 = new Payments__c(Contact__c = ContactGuy1.id, Respondent_Number__c = 5, status__c = 'tested', Study__c = ChildCampaign.id);
        insert payment1;
		try
		{
			insert payment2;
		}
		catch(Exception e)
		{
			system.debug('Adding 2nd payment failed. This is good');
		}        
        //***************** TEST Update Umbrella Counters ********************************
        //This just recalculates counters, so just run an udate statment on it.
        UpdateTopLevelCampaignCounters updateCounterController = new UpdateTopLevelCampaignCounters();
		boolean updateCampaignSuccess;
		updateCampaignSuccess = updateCounterController.updateCountersSchedule();
		
		boolean updateCampaignSuccess2 = UpdateTopLevelCampaignCounters.updateCountersTrigger();
  
  
        //***************** TEST UpdateNumberOfCHildrenInHousehold ********************************
        //This just recalculates counters, so just run an udate statment on it.
        
        /*
        updateNumberOfChildrenInHousehold  updateAccountCounterController = new updateNumberOfChildrenInHousehold ();
		boolean updateAccountCounterSuccess;
		updateAccountCounterSuccess = updateAccountCounterController.updateCountersTrigger();
		*/
		     
		//***************** TEST FlagRespondentsAsRecentlyTested ********************************
		//Those resondents we made above should have caused the FlagRespondentsAsRecentlyTested
		//trigger to fire. That means those contacts should have the  recently_tested__c flag to true
		
		//We already pull contactguy1 one details above, so we can just use an assert here to make sure it's right
		contact1details = [select recently_tested__c, pid__c, id from Contact  where id = :ContactGuy1.id];
		
		System.assertEquals(contact1details.recently_tested__C,true);


		//***************** TEST InactivateCampaignOnRecruitFill Trigger ********************************
		//Those resondents we made above should have caused the InactivateCampaignOnRecruitFIll
		//trigger to fire. That means the master campaign status should be 'Initial Recruitment Complete'	
		Campaign campaign = [select Status from campaign  where id = :ParentCampaign.id];
		
		//Update a respondent to test the cancel logic
		Respondent2.Respondent_Status__c = 'cancelled';
		update Respondent2;
		
		//Then delete them to test the counter logic
		delete Respondent2;
		//System.assertEquals(campaign.Status,'Initial Recruitment Complete');
								
		//***************** TEST AssignCallers trigger and assignCallers class ********************************
		//Modify a campaign to use the assign callers trigger
		
		//for whatever reason we need a lead for a campaign member, so we better make one
		Lead lead1 = new Lead(company = 'Big stupid butt store',  firstname='Daniel', lastname='llewellyn', status='open');
		insert lead1;
		
		//Create the proper campaign member status
		CampaignMemberStatus newstatus = new CampaignMemberStatus(HasResponded = true, isDefault = true, SortOrder = 20, CampaignId = ParentCampaign.id, label = 'Qualified-Callers');
		insert newstatus;
		
		//Create a campaign member so there is someone to assign a caller to
		CampaignMember member1 = new CampaignMember(leadid = lead1.id, status = 'Qualified-Callers', Contactid= ContactGuy1.id, Token__c = 'asfasdfasfas', Campaignid = ParentCampaign.id);
		insert member1;
		
		//update the parent campaign record so that the trigger fires
		ParentCampaign.Assign_Callers__c = true;
		update ParentCampaign;	
		
		
		//***************** TEST MakRespondentCheckGen trigger and MarkRespondentcheckGenClass **********
		//Insert a check and then check the associate respondent record to make sure the "check has been generated" flag is true
		
		//Insert the check record, with ContactGuy1 as the contact
		Check__c Check1 = new Check__c(contact__c = ContactGuy1.id, Master_campaign__c = ParentCampaign.id, Payment_Amount__c =15.00,Respondent__c=Respondent1.id,Session__c=ChildCampaign.id,Unique_Check_Record_ID__c='AAGDSFABADFAHADFADFAGASDFAFSDAF');
		insert Check1;
		Respondent__c respondentCheckTest = [select Check_Has_Been_Generated__c from Respondent__c  where id = :Respondent1.id];
		
		//System.assertEquals(respondentCheckTest.Check_Has_Been_Generated__c,true);

		String myRunResult;
		//***************** TEST queryToJSON class ********************************
		//send a query to the query to json component, get some data back
		
		
	    try
	    {
			PageReference pageRef1 = Page.queryToJson;
			pageRef1.getParameters().put('queryString','name from contact');
			Test.setCurrentPageReference(pageRef1);
			QueryToJSON jsonCtlr = new queryToJSON();
			jsonCtlr.getJson();
			myRunResult = jsonCtlr.getResult();
			//System.assert(jsonCtlr.getJson()=='expected value');
		    System.Debug('Query To JSON Returned'+myRunResult );
	    }
	    catch(Exception e)
	    {
	    	
	    }
		
		
		//***************** TEST getJsonEvents class ********************************
		//send a query to the query to json component, get some data back
		
		try
		{
			PageReference opsCalendar = Page.OpsCalendar;
			opsCalendar.getParameters().put('start','1262332800');
			opsCalendar.getParameters().put('end','1263178646');
			Test.setCurrentPageReference(opsCalendar);
			getJsonEvents eventsCtlr = new getJsonEvents();
			eventsCtlr.getEvents();
			eventsCtlr.getResult();
			
			myRunResult = eventsCtlr.getResult(); 
			
			//System.assert(jsonCtlr.getJson()=='expected value');
		    System.Debug('get JSON Events result'+myRunResult );		
	    }
	    catch(Exception e)
	    {
	    	
	    }
		
		
		//***************** TEST quotaCheck page and quotaTest class ********************************
		//send a query to the query to json component, get some data back
		
		try
		{		
			PageReference quotacheck = Page.quotaCheck;
			quotacheck.getParameters().put('CC',ChildCampaign.id);
			quotacheck.getParameters().put('MC',ParentCampaign.id);
			quotacheck.getParameters().put('R',ContactGuy1.id);
			Test.setCurrentPageReference(quotacheck);
			quotaTest quotaTestCtlr = new quotaTest();
			quotaTestCtlr.respondentCanSchedule();
			myRunResult = quotaTestCtlr.getResult(); 
			//System.assert(jsonCtlr.getJson()=='expected value');
			System.Debug('Quota Check Returned'+myRunResult);
	    }
	    catch(Exception e)
	    {
	    	
	    }			
		
		//***************** TEST index and website Menu ********************************
		//call the index page, which will load the websiteMenu class
		try
		{
			PageReference indexPage= Page.index;
			Test.setCurrentPageReference(indexPage);
			WebsiteMenu  websiteMenuCtlr = new WebsiteMenu();
			websiteMenuCtlr.getMenuItems();
			System.Debug('Website Menu Returned'+websiteMenuCtlr);
	    }
	    catch(Exception e)
	    {
	    	
	    }
		//***************** TEST LinkMenu Class ********************************
		try
		{
			List<Link_Category__c> myMenu = linkMenu.getLinks('about');			
		}
	    catch(Exception e)
	    {
	    	
	    }

		//***************** TEST findContactsForAngel Class ********************************
		
		//Working test
		try
		{
			PageReference findContacts = Page.AngelFindContacts;
			findContacts.getParameters().put('birthdate','03211988');
			findContacts.getParameters().put('phone','7632344306');
			findContacts.getParameters().put('postalCode','55447');
			Test.setCurrentPageReference(findContacts);
			findContactsForAngel findContactsCtlr = new findContactsForAngel();
			findContactsCtlr.findContacts();
			myRunResult = findContactsCtlr.getResult(); 
			//System.assert(jsonCtlr.getJson()=='expected value');	
		}
	    catch(Exception e)
	    {
	    	
	    }
	    //Failure test
		try
		{
			PageReference findContacts = Page.AngelFindContacts;
			findContacts.getParameters().put('birthdate','03211900');
			findContacts.getParameters().put('phone','7632344306');
			findContacts.getParameters().put('postalCode','55447');
			Test.setCurrentPageReference(findContacts);
			findContactsForAngel findContactsCtlr = new findContactsForAngel();
			findContactsCtlr.findContacts();
			myRunResult = findContactsCtlr.getResult(); 
			//System.assert(jsonCtlr.getJson()=='expected value');	
		}
	    catch(Exception e)
	    {
	    	
	    }		    		
		//***************** TEST returnPinandPidForAngel Class ********************************
		
		//Working test
		try
		{
			PageReference getPidAndPin = Page.AngelGetPinAndPID;
			getPidAndPin.getParameters().put('contactID',ContactGuy1.id);

			Test.setCurrentPageReference(getPidAndPin);
			returnPinandPidForAngel findPinAndPidCtlr = new returnPinandPidForAngel();
			findPinAndPidCtlr.findPinAndPid();
			myRunResult = findPinAndPidCtlr.getResult(); 
			//System.assert(jsonCtlr.getJson()=='expected value');	
		}
	    catch(Exception e)
	    {
	    	
	    }
	    
	    //failure test	
		try
		{
			PageReference getPidAndPin = Page.AngelGetPinAndPID;
			getPidAndPin.getParameters().put('contactID','423adfagasd');

			Test.setCurrentPageReference(getPidAndPin);
			returnPinandPidForAngel findPinAndPidCtlr = new returnPinandPidForAngel();
			findPinAndPidCtlr.findPinAndPid();
			myRunResult = findPinAndPidCtlr.getResult(); 
			//System.assert(jsonCtlr.getJson()=='expected value');	
		}
	    catch(Exception e)
	    {
	    	
	    }	
	    
		//***************** TEST getCaseInfo Class ********************************
		
		//Working test
		try
		{
			Case testCase = [select CaseNumber from case where id = :case1.id];
			PageReference getCaseInfo = Page.getCaseInfo;
			getCaseInfo.getParameters().put('caseNumber',testCase.CaseNumber);

			Test.setCurrentPageReference(getCaseInfo);
			getCaseInfoForAngel getInfoByCaseNumCtrl = new getCaseInfoForAngel ();
			getInfoByCaseNumCtrl.getInfoByCaseNum();
			myRunResult = getInfoByCaseNumCtrl.getResult(); 
		}
	    catch(Exception e)
	    {
	    	
	    }
	    
	    //failure test	
		try
		{
			PageReference getCaseInfo = Page.getCaseInfo;
			getCaseInfo.getParameters().put('caseNumber','000000');

			Test.setCurrentPageReference(getCaseInfo);
			getCaseInfoForAngel getInfoByCaseNumCtrl = new getCaseInfoForAngel ();
			getInfoByCaseNumCtrl.getInfoByCaseNum();
			myRunResult = getInfoByCaseNumCtrl.getResult(); 
		}
	    catch(Exception e)
	    {
	    	
	    }	    	    
	} 
}

 

 

rungerrunger

Ah, yes.  You should try and break that up into multiple testmethods.  Then it doesn't really matter if they're on one class or not (except that the total class size cannot exceed a certain size, but that will be obvious when you try to save).

 

You're also not doing much in the way of asserts.  Having asserts in your tests are how you know if the code behaves the way you expect it to.  I'm seeing a few instances of this anti-pattern:

 

try {

  insert a;

}

catch (Exception ex) {

  System.debug('it is good that this failed');

}

 

Now, if it didn't fail, you wouldn't see the debug msg, but the test method would continue running and you wouldn't see any sign of failure when the test is done.  What you want is something more like:

 

try {

  insert a;

  System.assert(false);

}

catch (Exception ex) {

  System.assert(ex.getMessage().contains('My Validation String')); // where 'My Validation String' is the reason for the insertion failure

}

 

This way, if it succeeds, or if it fails for the wrong reason, the test will fail.

Kenji775Kenji775

Ok, yeah I'll work on breaing it into multiple methods.

I know I need to do more asserts. I'm just so lazy, and overworked :P You know how it goes. The code works fine so I just try and deploy and get it out. I know they are important though, so when I refactor it into using more methods, I'll try and at least get a few asserts in there.

Jeremy.NottinghJeremy.Nottingh

It's always tedious to go back and write testmethods and asserts after the code is all finished. And of course, users are always in a hurry to get their functions working. However, developing a good habit of writing basic testmethods *at the same time* as writing the Apex code can really pay off. If you know in advance that you need to cover 100% of your code, you can be thinking about it and writing it almost simultaneously.

 

Some will even tell you to write your testmethods before the actual code, so you sort of save the fun part for last. I'm not that patient. My own pattern is to code, save to server, write tests, save to server, write asserts, run tests. Repeat.

 

Jeremy

Kenji775Kenji775

Thats a solid plan, and I really need to start doing it. I just gotta push back a little and say that projects are going to take just a tad longer so I can make sure I am writting my asserts and real meanigful tests. Thanks for your help.

Kenji775Kenji775

So I've broken my code into classes. Is there an easy way to share data between the classes without having to do a ton of passing around. So say I create one account, and lots of classes are going to want access to that account, whats the easiest way to do that.

 

Basically I just created a bunch of classes that create the testing data, and then other classes that actually use that data. I figured it would be much more efficient if I could call the class that creates the data once, and share that around, instead of every class that needs that data having to get it's own copy of it. Would marking the classes that create the data as public static work?

SivarajanSivarajan

Use Test.startTest() and Test.stopTest() system methods in your test methods. You can use only once in every test method. 

All of the code before the Test.startTest() method should be used to initialize variables, populate data structures, and so on, allowing you to set up everything you need in order to run your test. After you call this method, the governor limits that get applied are based on either the first DML statement (like INSERT, DELETE, and so on) or the first Web service invocation.

garybgaryb

Lots of good advice here already. A couple of points:

 

1. Unit tests should test units of code - sound advice, but what is a "Unit" exactly? This is an exercise in experience IMO, but I try and write test methods for each method I have. I usually end up with a test class for every class with multiple test methods. However, this approach has it's limitations (see 2!)

 

2.  How you test depends on what you are testing. Apex classes with public methods that maybe take a value and return a value based on the value passed in are very easy to test. Visualforce pages aren't necessarily as easy. Triggers... let's just say I dislike these the most, especially if you have a lot of objects to set up before you can insert/update/delete the object  the trigger is on.

 

3. Reusing parts of test methods. See this post by the every-excellent Jeff Douglas to see how you can use static blocks of code across tests in a test class. You can have testMethods within your test class that insert setup objects and return objects but they can't take arguments; you can have static methods in a test class that do take arguments but (I believe) this will require coverage. Finally, you can create a "normal" class with a bunch of static methods that set things up and are callable from other classes (unlike the other two options).

 

4. I tend to write code that covers a particular part of functionality and then write tests for it, before moving onto the next piece that needs coding. Over time, I try to curate the test methods so that I'm reusing as much as I can.

 

 

Kenji775Kenji775

good advice everyone, thank you. I think when I get my code all rewritten I might post here and see if anyone can point out and glaring errors or issues. I've been a procedural programmer for a long time, but still new to OOP concents and how to use them. Getting better though! Thanks again everyone.