When Salesforce is life!

Tag: Apex Test

How to create an Apex reusable Data Factory Library using Forceea Templates

Today’s post has been written by Nikos Mitrakis, the creator of Forceea, an amazing Data Factory Framework for Salesforce.

Some facts about Nikos:

– Salesforce Developer at Johnson & Johnson EMEA Development Centre (EDC)
– Started his Salesforce journey in 2014
– Has passed 10 certifications, including Certified Application Architect
– Holds a Physics degree
– Leader of Limerick, Ireland Developer Group
– Married since 1994, has a daughter
– Loves watching sci-fi movies and good comedies
– Lives in Limerick, Ireland


Introduction to a familiar situation

Let’s face it with honesty and courage: writing test methods for our Apex code is (very often) boring and time-consuming, usually because of the difficulty regarding the creation of test data. In most implementations we can see a mediocre result, which could be described as a class (e.g. DataFactory) including static methods that generate and insert SObject records. The following code describes this inefficient pattern:

public class DataFactory {
    public static List<Account> createAccounts(Integer numRecords) {
        List<Account> results = new List<Account>();
        for (Integer counter = 1; counter <= numRecords; counter++) {
            Account record = new Account();
            // define fields
            record.Name = ...
            ...
            results.add(record);
        }
        return results;
    }
    // other methods
}

Using this logic, we can execute our Data Factory method with:

List<Account> accounts = DataFactory.createAccounts(100);
insert accounts;

to create and insert 100 accounts. As you can see, one issue here is how we generate data for other fields in our test method. But things get worse when we create related SObjects, for example contacts with accounts. Let’s examine a new method createContacts, based on the previous pattern:

public static List<Contact> createContacts(Integer numRecords) {
    List<Account> accounts = createAccounts(10);
    // optionally process accounts and manually add/modify Account fields
    insert accounts;
    List<Contact> results = new List<Contact>();
    for (Integer counter = 1; counter <= numRecords; counter++) {
        Contact record = new Contact();
        // define fields
        record.LastName = ...
        record.AccountId = ... // get the ID from accounts list
        ...
        results.add(record);
    }
    return results;
}

When we call the above method from our test method, e.g. with

List<Contact> contacts = DataFactory.createContacts(100);
//  optionally process contacts and manually add/modify Contact fields
insert contacts;

we certainly insert 10 accounts and 100 contacts related to these accounts. But what if we need to modify the generated accounts or we need to insert additional Account fields? This pattern doesn’t allow to do this. In more complex scenarios, we may have to insert many more SObjects. The final result is a Data Factory class with methods that create test data BUT without the ability to easily modify the created records.

I can finally hear your question: Do you propose a better approach? Is there a more flexible and easier way to do it? And the answer is YES!

Making a Data Factory Library with Forceea Templates

Forceea Data Factory framework is an open source GitHub project, with the following capabilities:

  • creates records for standard or custom objects, for any standard or custom field
  • automatically definines the required fields
  • creates static or random data for fields of any data type: Integer, Currency, Double, Date, Datetime, Time, Boolean, String, TextArea, Percent, Reference, Email, Phone, URL, Base64 (BLOB), Picklist and MultiPicklist
  • creates real random first and last names
  • creates real random addresses with street, zip code, city, region/state and country
  • creates serial data for date, datetime, integer, decimal, currency and percent
  • can copy data from another field of the same record or a lookup record
  • can create the same random data, using a pseudo-random number generator
  • handles record types and field dependencies (dependent picklists)
  • supports record groups for inserting and deleting records
  • validates the definitions based on the field data type
  • provides many methods to get/insert the created records, add/delete field definitions, get the errors, configure the amount of information returned during run-time (debug log) and more
  • includes an extended error messaging system

and will be our main tool to build a powerful and flexible DataFactory class (our Data Factory Library). This class will include static methods, our Templates, which actually will not insert any data at all! What these Templates do is to instruct Forceea how to generate the data.

Let’s meet our first Template:

public class DataFactory {
    // returns definitions for: Accounts 
    public static FObject getDefAccounts() {
        FObject result = new FObject('Account');
        result.setDefinition('Name', 'static value(Company)');
        result.setDefinition('Name', 'serial type(number) from(1) step(1) scale(0)');
        result.setDefinition('Phone', 'random type(phone) format("(30) DDD dD-00-DD")');
        result.setDefinition('Industry', 'random type(picklist)');
        result.setDefinition('Site', 'random type(url)');
        return result;
    }
}

Obviously the method getDefAccounts returns an FObject – the class instance for generating data with Forceea. Reading the code you can see that we define accounts with random values for all required fields. So, these are our guidelines so far:

  • Create a DataFactory class
  • Create a master Template for each SObject, with the name getDef<SObjectApiName>s, e.g. getDefCases
  • Use the above pattern for each master Template, defining all common required fields (the fields required by any record type)
  • For the Template field definitions, use definitions which generate
    – random values for picklist fields
    – random values for fields with date/datetime, checkbox, email, phone, currency, percent, address, and text area data types
    – serial values for the Name field (notice how we did it in the getDefAccounts method)

Even though it’s not obvious from the above code, Forceea (by default) will find and insert field definitions for any required fields we haven’t defined, but it’s a best practice to define all these required fields in our master Template.

The setDefinition method sets the expected values for each field, using a descriptive data generation language called Dadela. For example, the definition random type(picklist) except(Hot) for the Rating field generates random values from the pisklist field’s values, excluding the value “Hot”.

Now, for every record type of each SObject create a new Template, for example:

// returns definitions for: Accounts with MediumAccount record type
public static FObject getDefMediumAccounts() {
    FObject result = getDefAccounts();
    result.setDefinition('RecordTypeId', 'static value(MediumAccount)');
    result.setDefinition('NumberOfEmployees', 'random type(number) from(10) to(100) scale(-1)');
    result.setDefinition('AnnualRevenue', 'random type(number) from(1000000) to(10000000) scale(3)');
    return result;
}

This new Template builds on the master Template getDefAccounts, defining only the record type and the additional fields which are related to this specific record type (NumberOfEmployees and AnnualRevenue). All other defined fields from the master Template are used as they are, so we don’t duplicate any field definitions. Our additional guideline:

  • Create a record type Template for each SObject’s record type, with the name getDef<RecordTypeDescription><SObjectApiName>s, e.g. getDefServiceCases

This is it! This is what we need to do for SObjects which don’t include a Lookup or Master-detail relationship. But how do we create templates for those SObjects that they do include a relationship? Let’s see how, with our second SObject:

// returns definitions for: Accounts - Contacts
public static Map<String, FObject> getDefContactsAndAccounts() {
    // initialize
    Map<String, FObject> fobjectsByName = new Map<String, FObject>();
    String objName = '';
    // Account
    objName = 'Account';
    FObject objAccount = getDefMediumAccounts(); 
    fobjectsByName.put(objName, objAccount);
    // Contact
    objName = 'Contact';
    FObject objContact = new FObject(objName);
    objContact.setDefinition('FirstName', 'random type(firstname) group(name)');
    objContact.setDefinition('LastName', 'random type(lastname) group(name)');
    objContact.setDefinition('AccountId', 'random lookup(Account) source(forceea)');
    objContact.setDefinition('LeadSource', 'random type(picklist)');
    objContact.setDefinition('Title', 'random type(list) value(Developer, CFO, Account Manager, CEO, Logistics Manager)');
    objContact.setDefinition('Email', 'random type(email)');
    fobjectsByName.put(objName, objContact);

    return fobjectsByName;
 }

I think you’ll agree that this Template is more interesting. Its first lines use the previously created record type Template getDefMediumAccounts to define the Account fields. We could also

  • insert one or more new field definitions using objAccount.setDefinition('FieldApiName', '<Field Definition>') before fobjectsByName.put(..) or
  • modify an existing field definition – for example to define a static value for the (existing) NumberOfEmployees field, we can use
    // delete previous field definitions
    objAccount.deleteFieldDefinitions('NumberOfEmployees');
    // add new definition
    objAccount.setDefinition('NumberOfEmployees', 'static value(100)');

Finally, we insert the FObject for the Account into the fobjectsByName map and we proceed to the field definitions for contacts.

If you noticed the definition objContact.setDefinition('AccountId', 'random lookup(Account) source(forceea)' and asked yourself what is source(forceea), this is a way to request that the framework will get the related account IDs from the previously inserted accounts. There are a lot of lookup field definitions that will certainly need your attention if you start developing with the framework, but for the moment let’s not go any deeper.

In many implementations we have a set of dependent SObjects. Let’s say that in order to create records for the Case, we have to create records for Account and Contact (and perhaps records for 4 more other SObjects) using a Template like getDefCasesAndAccountsContacts. This is a kind of quite complex data factory process, which can be handled by Forceea very smoothly – you just add the following pattern for each requird SObject:

objName = '<SObjectApiName>';
FObject objMySObject = new FObject(objName);
objMySObject.setDefinition('<FieldApiName>', '<Field Definition>');
// other required field definitions
fobjectsByName.put(objName, objMySObject);

Our last guidelines:

  • Document the SObjects that are returned by any Template, with the correct order, e.g. // returns definitions for: Accounts - Contacts - Cases
  • Use the format getDef<SObjectName>And<RelatedSObjects> for Templates with related SObjects, e.g. getDefCasesAndAccountsContacts

Finally, insert the following method in your DataFactory class:

public static void insertRecords(Map<String, Fobject> fobjects) {
    for (FObject obj: fobjects.values()) {
      obj.insertRecords(true);
    }
}

The test method

After you have created your Templates, let’s see how you can take full advantage of them. We’ll use getDefContactsAndAccounts as an example. In your test method, the first step is to define a map:

Map<String, FObject> fObjects = DataFactory.getContactsAndAccounts();

The second step is to modify any SObject definitions, if it’s needed. For our example here, we’ll make things a little more difficult with the following requirements:

  • For the Account: we need to insert 10 records, with a) random values for the Description field and b) any picklist value except “Hot” for the Rating field.
  • For the Contact: we need to insert 100 records, with the random values from 1/1/1960 to 31/12/2000 for the Birthdate field.
  • All other fields will get the default definitions from the their Templates.
// initialize
Map<String, FObject> fobjectsByName = DataFactory.getDefContactsAndAccounts();
FObject objAccount = fobjectsByName.get('Account');
FObject objContact = fobjectsByName.get('Contact');
// define number of records
objAccount.records = 10;
objContact.records = 100;
// optionally modify an existing definition
objAccount.deleteFieldDefinitions('Rating');
//  optionally define new field definitions
objAccount.setDefinition('Description', 'random type(text) minlength(10) maxlength(40)');
objAccount.setDefinition('Rating', 'random type(picklist) except(Hot)');
objContact.setDefinition('Birthdate', 'random type(date) from(1960-1-1) to(2000-12-31)');
// insert records
DataFactory.insertRecords(fobjectsByName);

Using the above pattern, it’s easy for everyone to understand what changes have been made in comparison to the getDefContactsAndAccounts Template.

Did you say that we need the inserted contacts for our System.assert? No problem at all! Just use:

List<Contact> contacts = objContact.getInsertedRecords();
OR
List<Contact> contacts = FObject.getInsertedRecords('Contact');

Conclusion

Forceea Templates are easy to implement and they are powerful enough to help you write your Apex test methods faster. The most important is that

  • your test methods will be more understandable by any other developer, and
  • the new test methods will require less effort to develop

The best way to see if this solution is suitable for you is to start working with it and create a pilot version of your new DataFactory class. If you’re not satisfied with your existing Data Factory (or if you don’t have a Data Factory at all), why don’t you give it a try?

[Salesforce / Apex] Forceea data factory framework: a new approach to an old problem

This week’s guest post is a cool technical post about Apex Tests by Nikos Mitrakis.

Apex Tests are perceived as the hated necessity by most Salesforce developers: they are really important to keep high code quality levels but they are not the most fun part of coding with Salesforce.

I casually discovered Nikos through his GitHub page: I had a read at this Forceea Apex Test Framework, and I asked him to write a post to describe this cool piece of Salesforce tech.

Nikos has started his Salesforce journey in 2014. He started with Salesforce as a hobby (which still remains) and his wife continously threatens him with divorce if he doesn’t stop playing with his various Orgs all the time.
He has a Physics degree, a Microsoft SQL Server BI certification and a few Salesforce certifications. He likes writing code and discoverig how huge the Salesforce ecosystem is. He adores talking about his personal projects, he likes good sci-fi films, he’s been working with a Mac for more than a year, and he started the Salesforce Developer Group in Greece in 2016 (admittedly without much success).
Nikos is working as a Salesforce Developer at the Johnson & Johnson EMEA Development Center in Ireland. If he wasn’t a Salesforce Developer, he’d like to be a Developer in Salesforce.


What is a Data Factory?

Generally speaking, a Data Factory is a set of tools that generate and insert data. It’s very important when you develop a test method in an Apex Test Class, since you usually have to insert records to complete the testing. Using a Data Factory you make your life easier and your work more productive!

A Data Factory is also required when you want to test a report, a trigger/class or another process under Large Data Volumes (e.g. how fast is our report when there are 1 million records?), for User Acceptance testing (UAT), and for training – when you don’t want to create a Full Sandbox or when you want to create data which don’t exist in the production system yet.

What is Forceea and how I can install it?

Forceea (forˈsēa) is a data factory framework for Salesforce and an open source project (https://github.com/nmitrakis/Forceea) in GitHub. It’s a framework, because it gives the programmatic tools for a developer (or administrator, why not?) to easily generate, insert and delete SObject records.

“Yet another data factory?” you may say. Well, not at all!

But first let’s see how you install it.

When you download the files, your installation depends on your preference: classic metadata or DX? For the first option, you may want use the Ant (the build files are included) or the CLI, for example with

sfdx force:mdapi:deploy -u <OrgAlias> -d <folder> -w 5).

For DX, I suggest the CLI, using the command

 sfdx force:source:push -u <OrgAlias>

How can I generate the data I want?

OK, you have installed the framework. Now what?

I think the better way to understand how it works is by example: suppose you want to insert 100 Opportunity records and in your Org the Opportunity object has the additional required custom field MyField__c (which is a lookup to the custom object MyObject__c). Of course the Opportunity has its own required fields (like Stage).

The first step is to create an FObject:

FObject myObj = new FObject(Opportunity, 100);

Next, you declare the field definitions. A field definition uses a descriptive “language” to define what kind of data you want to create for this particular field. This language is called SDDL (Sample Data Definition Language). Don’t be afraid! It’s not a new programming language and it’s very easy to learn.

Let’s start with the first field you want to define, which is the Record Type (API name: RecordTypeId). Do you want your records to have a specific record type (let’s say BigDeal)? Then give this field definition:

myObj.setDefinition('RecordTypeId', 'static value(BigDeal)');

static here is the command and value is the parameter. The static command creates (what else?) static values, that is values which are the same in every record you create.

Do you want a random record type? Then you need the following definition:

obj.setDefinition('RecordTypeId', 'random type(picklist)');

The random command does exactly what you understood, it’s a really powerful command and you can even decide that every time you get the same (but random) data!

But wait! I hear you saying that the Record Type field is not a picklist field, and of course you’re right (it’s a Lookup)! Forceea handles this “special” field as a picklist field, making things easier for you. Say “Thank you 4ca”..

So, we move to our next field, which is the Close Date (API name CloseDate). This has a Date type, and let’s suppose you want it to have random Date values from this year:

myObj.setDefinition('CloseDate', 'random type(date) from(2018-01-01) to(2018-12-31)');

The type parameter is the boss here – it defines what kind of data you get. Give type(Boolean) and you get random True/False values. Give type(phone) and you have random phone numbers, etc

The Amount is a currency, so you decide to take random values from 100,000 to 1,000,000 and round these values to the nearest thousand. Difficult? No, it’s very easy!

myObj.setDefinition('Amount', 'random type(number) from(100000) to(1000000) scale(-3)');

Every opportunity that respect’s itself should have an Account, so you decide that the AccountId field will take an ID from any random Account, but you’ll get accounts without two specific Industry values. You asked for it, you get it:

myObj.setDefinition('AccountId', 'random lookup(Account) field(Industry) except(Banking,Chemicals) source(forceea)

I think the above definition needs some clarifications. The lookup(Account) instructs the framework to fetch records from the Account object and the field(Industry) except(…) to get only records for which the Industry field has any value except “Banking” and “Chemicals”.

But what is source(forceea)? This parameter defines the “source” of the lookup object’s records:

  • If it’s source(salesforce), the framework will query the Salesforce database and get the lookup records.
  • If it’s source(forceea) and the lookup object has been previously created (in the same context/transaction), it gets the records from there (which of course is much faster).
  • If it’s source(forceea) and the lookup object hasn’t been created (or the records have been inserted and deleted), it inserts some records of this lookup object.

Now that you have the opportunity account, don’t forget the opportunity Name (API name Name). Let’ say you want it to have the format <AccountName> – Opportunity for <Random text (with words) from 15 to 30 chars>

So, what is our definition? Well, we don’t have one, but 3 definitions to deliver this:

myObj.setDefinition('Name', 'copy field(AccountId) from(Account.Name)');

This definition gets the Name of the related account.

myObj.setDefinition('Name', 'static value(" – Opportunity for ")');

As you see, this is just a simple text value.

myObj.setDefinition('Name', 'random type(text) minlength(15) maxlength(30)');

And finally, we get our random text with “Latinoid” random words, like “Partem inermis ius impedit eam”

Keep in mind that with the random type(text) definition, the first character of the text is always a capital and the same word is never repeated twice in a row.

Your next field is Lead Source (which is a picklist field with the API name LeadSource), and here you want to have any declared picklist value except from “Partner” and “Other”:

myObj.setDefinition('LeadSource', 'random type(picklist) except(Partner, Other)');

If you wanted these two values only, you could give the definition:

myObj.setDefinition('LeadSource', 'random type(list) value(Partner, Other)');

or if you needed just a specific picklist value:

myObj.setDefinition('LeadSource', 'static value(Partner)');

Now you’ve finished with your field definitions, but remember that we haven’t defined all required fields (like Stage or myField__c). Of course you don’t have to worry about that, because the framework automatically identifies and defines all required fields. There are specific rules for setting the suitable field definition, but (without going to many details) we could briefly say that the field definition for a required field depends on the field data type, the SObject and the field name. So, after defining your fields, Forceea will define all required fields you didn’t define, like Stage or myField__c.

If you need to make some changes in the created records (for example to update a field with some complex calculations), you can get the opportunities with:

List<Opportunity> myRecords = (List<Opportunity>) myObj.getRecords();

Then do your changes, e.g.

for (Opportunity objRecord : myRecords) {
 objRecord.Amount = … // your changes here
}

and just insert the amended records with

myObj.insertRecords(true);

Forceea has many other field definitions, to create random real first and last names (with male and female names), real postal addresses (address, city, postal code, state, country), URLs, email addresses, phone numbers, Boolean values and Datetime values. And don’t forget that it supports BLOBs (e.g. to create email attachments).

It also provides definitions with the serial command (e.g. serial type(number) from(1) step(1.5) scale(2)) to create serial integer, decimal, currency, percentage, date and datetime values.

As you understand, there are many methods to

  • get or delete field definitions
  • create records from a specific serial number (very useful when you insert records with the serial command in different transactions)
  • insert records in groups (a valuable tool for your test methods)
  • define the Verbose mode (how many debug logs you get)
  • get the errors (yes, there is a detailed error system)

The framework handles field dependencies (dependent picklists) and it protects you from doing errors like defining the wrong definition for a specific field data type or defining multiple definitions for a field (e.g. Date) which can have only one.

How can I see the framework’s messages?

Forceea doesn’t have a UI (for the moment). The framework uses Debug Log to post its messages, which show

  • The errors during the process
  • The process milestones completed
  • The data of the first created records

Here is a sample output, just to get an idea of what this looks like (please note that the field definitions in this sample are not the field definitions you used previously).Keep in mind that you have many options to reduce the quantity of logs, for example to get almost nothing on a production system (which by the way is accomplished using a Custom Metadata type).

What’s next?

When you use Forceea in a test method, you really don’t need to create many records, so the 10,000ms CPU limit isn’t an actual problem. Of course you can use the framework to insert records in a sandbox or developer Org when you execute an Apex script in the Anonymous Windows, which of course has the same 10,000ms limit. But when you want to populate a sandbox with 1,000,000 of Accounts, this is another story..

This story is a major part of the next upcoming release (v1.3). The functionality is called Async, it can insert or delete many objects in one transaction, and when you insert objects or delete 1 object it’s surprisingly fast! I have inserted 500,000 of a custom object (without any validation rules, triggers, processes, etc) in 40s! Of course its speed mainly depends on the triggers, etc you have in your actual Org, which may slow down the process significantly (that’s life..)

Anything else?

Yes! I invite everyone to have a look at the detailed User Guide (http://bit.ly/Forceea12_UserGuide) and try the framework.

And I’d like to say a big THANKS to Enrico for hosting this post.

[Salesforce / Apex Test] Code coverage and logical tests in Apex Test Classes

This article is actually a repost from a buddy I came across online.

I read his articles on LinkedIn by chance and I really appreciated the easy way he writes and how he delivers important Salesforce concepts.

I choose an article about Apex Test Coverage… but before going on the article…
…please take a moment to hail our beloved lord the deployment fish!

The guest blogger

Vladimir Egikyan is a SFDC developer since 2010. Most of his career he worked for technical services providing company in Israel. During that time he helped to implement business of various companies, among which are ZIM Integrated Shipping Services, Bank Leumi.
In the latest three years he works as in-house developer and sharpen his architect skills. Though he is officially certified only as Developer… yet 😉

Writing good Apex Tests is a key to successful developing. There is a huge list of best practices and recommendations, that you can find in Salesforce documentation. Following them all, is what every developer should aim to do. Over years of developing on Salesforce, I learnt that code coverage is not what really matters…

How can that be?

Well, your coverage will raise by itself if you mind checking what your class or trigger has to do and what results you expect. Having said that, the most important thing that your test class has to do is to use System.assert methods to prove that code behaves properly. This will keep you on the safe side from any unintentional mistakes, changes in business requirements and eventually will save time and money on development process.

Okay, let’s take a look at the example:

TVRemoteControl class describes remote controls that can increase and decrease volume in scale 0-50 and have simple menu text.

Corresponding test class would contain call for each of class’ function:

TVRemoteControlTest covers the TVRemoteControl by 86% which is more than allowed minimum of 75% and these classes will deploy to production.

First and obvious defect of the test class is that it does not test if code will properly handle changing the volume beyond limits. The most important is we have to test that we get expected results in any possible use case. Our applications are almost never finished: business requirements constantly change. Besides that, we are all human and we always can make mistakes and test class is a tool that can help us to correct possible mistakes in time and that happens quite a lot.

Let’s see the better version of the test class.

This version of test class contains checking for going out of boundaries and also in each test method implements different use case and uses System.assert methods to make sure that class is performing the expected logic.

The given example is simple, but do not underestimate the importance of using assertion methods. Business logic in real life is way more complex then tv remote control, keep using these methods and you will be surprised how much time it saves for future technical support.

Powered by WordPress & Theme by Anders Norén