forceea data factory

Forceea: The Enterprise Data Factory We've Been Waiting For | Salesforce


Everybody needs testing records of SObjects:

  • Developers need testing data for their unit tests.
  • Testers need data for testing.
  • Administrators and architects need data for demos, stress testing, or User Acceptance Testing.

But how do you create data, manually or programmatically? You may wonder, what is the best way to automate the data creation of an enterprise (=complex) Salesforce implementation? With Forceea data factory of course! Let me explain why.

What is Forceea?

Forceea is an open-source data factory on GitHub I started in 2017. It's the effort of more than 1500h of development, with 30K lines of Apex code (with more than 97% test coverage).

You may read its extensive Success Guide for examples, training, and reference details.

Why Forceea is so powerful (spoiler: it's Dadela)?

Forceea is totally different from any data factory you may have used so far. The source of its magic is Dadela data generation language, a simple (yet very flexible and powerful) domain-specific programming language, that everyone can easily learn (yes, no coding skills are required!)

Let's see some Dadela examples to clarify things:

  • To get random values for the Account.Industry field, excluding the values "Services" and "Banking", we use random type(picklist) except(Services, Banking)
  • To get serial values like Opportunity-1, Opportunity-2, Opportunity-3, ... for the Opportunity.Name field, we use 2 definitions static value(Opportunity) and serial type(number) from(1) step(1) scale(0)
  • To get the Industry field value of the Account record related to the Contact.AccountId field we use copy field(AccountId) from(Account.Industry)
  • To create one record for each language of the custom picklist field Case.Language__c, for each Account (Case.AccountId field) that has previously been inserted by Forceea, we use 2 definitions
    for Language__c serial type(picklist) mode(permutation)
    for AccountId serial lookup(Account) mode(permutation) source(forceea)

This is a small sample of the Dadela field definitions. There are many more definitions to create static, random, and serial values for any standard or custom SObject (or Big Object) field, with lookup (or master-detail) fields, and functions (e.g. add a random number to a date value or convert a text to uppercase).

The last example used permutations, which is very useful for generating unique records by combining the values of one or more fields (a really powerful feature).

dont miss out iconDon't forget to check out: How to Get the Failed Records Through Database.Insert/Upsert | Salesforce Developer Guide

A complete data factory framework

Even though Dadela does all the magic behind the scenes, it's the Templates that help you construct a dynamic, re-usable Data Factory. A Template is nothing more than an Apex Map<String, FObject>.

The idea is simple: we create a new class called DataFactory and we configure methods (called templateX), e.g. templateContacts or templateCasesWithAccountsAndContacts.

Each Template returns a Map<String, FObject> with one or more items. Here we have the Template for Account:

public static Map<String, FObject> templateBigAccounts() {
    return new Map<String,FObject>{
        'Accounts' => new FObject(Account.SObjectType)
        .setVariable('recordType', RECORD_TYPE_BIG_ACCOUNTS)
        .setDefinition(Account.RecordTypeId, 'static value({@recordType})')
        .setDefinition(Account.Name, 'static value(Account-)')
        .setDefinition(Account.Name, 'serial type(number) from(1) step(1) scale(0)')
        .setDefinition(Account.Industry, 'random type(picklist)')
        // add definitions for any other required field

The Template defines a new FObject (Forceea Object) for Account, sets the number of records to 10, and defines 2 fields, the Name field with values like Account-1, Account-2, etc, and the Industry field with random picklist values.

A very interesting point is the definition of the variable recordType. A Forceea variable can make the scripts easier to read (and develop), for example, we assigned the constant RECORD_TYPE_BIG_ACCOUNTS to the variable, which was used in the definition of RecordTypeId field, using {@recordType}.

Now, let's say you want to insert accounts in a test method, with values for an additional field (e.g.AnnualRevenue). Using the existing Template, it's very easy:

Map<String, FObject> template = DataFactory.templateAccounts(); // get the template
template.get('Accounts') // get the FObject for Account
.setDefinition(Account.AnnualRevenue, // create a new field definition
'random type(number) from(100000) to(1000000) scale(2)');
insertRecordsFromTemplate(template, true); // allOrNone = true

This snippet gets the Template from DataFactory and adds a new definition for the AnnualRevenue field. The definition creates random numbers (with 2 decimals) between 100K and 1M.

You can create Templates that encapsulate other Templates, going from simple to more complex Templates. The Forceea Success Guide has an entire chapter with all the details for constructing a best-of-breed DataFactory class with your Templates. I recommend you have a look.

Important note: A Template doesn't insert, update or delete records, it just defines the "structure" of the records that will be created. That's why is so flexible to add a new definition or remove an existing definition to/from a Template.

The Result

Forceea has many more features and capabilities than you could ever require, but (believe me) they all make sense. Among others, it creates millions of records asynchronously and validates the definitions based on the field data type.

So, the question is this: why should you spend valuable time to develop a mediocre data factory, while you have the best data factory (for free)?

dont miss out iconCheck out an amazing Salesforce video tutorial here: Salesforce To Salesforce Integration Using REST API

Questions & Answers

Question: Can I see the process used by Forceea to generate records?

Answer: Yes! Use FObject.setGlobalVerbose('debug') to display all the details in the debug log.

Question: If I create random picklist values for 2 dependent fields, will Forceea create invalid combinations of restricted values?

Answer: No! Forceea knows the picklist dependencies and will respect them.

Question: Does Forceea allow multiple field definitions for all fields?

Answer: No! Some fields (e.g. lookup, picklist, number, date/datetime) should have only 1 definition, while others (e.g. text) may have multiple. Forceea will raise an error on invalid definitions.

Question: Does Forceea support fields that don't exist in Salesforce?

Answer: Yes! They are called Virtual Fields (e.g. $MyVirtualField) and they allow the creation of more complex data sets. They are very useful in specific scenarios.

Question: Forceea can insert records, but can it update or delete records?

Answer: Yes! Forceea can update existing records with setDefinitionForUpdate and can delete records as well.

Question: Is there any more powerful native open-source data factory for Salesforce today?

Answer: No!


Popular Salesforce Blogs