Skip to content

[Question] Is the framework causing performance issues in large-scale tests with multiple test records? #13

@spyros-michailidis

Description

@spyros-michailidis

I've tried using the framework in a test class and indeed the code is cleaner and more readable.

However I noticed some delays in the test execution. Below you will see a test class with two methods.

In the first method, I'm using the framework and the Domain classes, which handle some tasks automatically (such as creating standard pricebook entries for new products).

In the second method, I'm inserting all records manually without the framework. Both methods include two loops that runs 50 times each to create new records.

public class DemandService_Test {
  @isTest
  public static void testWithDomainBuilder() {
    // Given
    Account_t acc = new Account_t();
    Opportunity_t oppo = new Opportunity_t(acc).add(new Contact_t());
    List<Product_t> products = new List<Product_t>();
    List<Schema.PicklistEntry> picklistEntries = Product2.Family.getDescribe().getPicklistValues();
    for(Integer i=0; i<50; i++) {
      products.add(
        new Product_t().name('Test Product ' + i).code('TESTP' + i).family(picklistEntries[Math.floor(Math.random() * ((19 - 0) + 1) + 0).intValue()].value)
      );
    }
    for(Product_t p : products) {
      new Demand(acc, p);
    }
    acc.persist();

    // When
    Test.startTest();
    for(Product_t p : products) {
      new OpportunityLineItem_t(oppo, p).quantity(new Random().integer(1,100));
    }
    Test.stopTest();

    // Then
    List<OpportunityLineItem> oppoItems = [SELECT Id, Product2Id, KS_AchievableDemand__c, KS_AchievableDemand__r.KS_Product__c FROM OpportunityLineItem];
    for(OpportunityLineItem oppoItem : oppoItems) {
      Assert.areEqual(oppoItem.Product2Id, oppoItem.KS_AchievableDemand__r.KS_Product__c);
    }

    
  }

  @isTest
  public static void testWithoutDomainBuilder() {
    // Given
    Account acc = new Account(Name = 'Test');
    insert acc;
    Opportunity oppo = new Opportunity(AccountId = acc.Id, Name = 'test', StageName = 'Qualification', closeDate = Date.today(), Pricebook2Id = Test.getStandardPricebookId());
    insert oppo;
    List<Product2> products = new List<Product2>();
    List<Schema.PicklistEntry> picklistEntries = Product2.Family.getDescribe().getPicklistValues();
    for(Integer i=0; i<50; i++) {
      products.add(
        new Product2(Name = 'Test Product ' + i, ProductCode = 'TESTP' + i, Family = picklistEntries[Math.floor(Math.random() * ((19 - 0) + 1) + 0).intValue()].value)
      );
    }
    insert products;
    AchievableDemand__c[] demands = new List<AchievableDemand__c>();
    for(Product2 p : products) {
      new AchievableDemand__c(Account__c = acc.Id, Product__c = p.Id);
    }
    insert demands;
    
    PricebookEntry[] entries = new List<PricebookEntry>();

    for(Product2 p : products) {
      entries.add(
        new PricebookEntry(
          Product2Id = p.Id,
          Pricebook2Id = Test.getStandardPricebookId(),
          UnitPrice = 10,
          IsActive = true
        )
      );
    }
    insert entries;

    // When
    Test.startTest();
    OpportunityLineItem[] oppoItems = new List<OpportunityLineItem>();
    for(Product2 p : products) {
      oppoItems.add(
        new OpportunityLineItem(
          OpportunityId = oppo.Id,
          Product2Id = p.Id,
          Quantity = 10,
          TotalPrice = 10
        )
      );
    }
    insert oppoItems;

    Test.stopTest();

    // Then
    oppoItems = [SELECT Id, Product2Id, AchievableDemand__c, AchievableDemand__r.Product__c FROM OpportunityLineItem];
    for(OpportunityLineItem oppoItem : oppoItems) {
      Assert.areEqual(oppoItem.Product2Id, oppoItem.AchievableDemand__r.Product__c);
    }

  }
}

As you can see in the below log analysis, the first test method, which utilizes the framework, took 8 times more time to run.
Screenshot 2024-09-06 at 12 06 22

I'm not sure if the loop is responsible for the delay, as I read this comment by @rsoesemann suggesting that the framework isn't designed for inserting many records. It just makes me wonder what will happen in a larger test class with multiple different scenarios to test, each one with a separated test method that needs test data. I'm concerned about the potential performance impact of using the framework in those cases.

I'm posting this as a question, in case anyone experienced performance issues with the framework, or can point out if I might be using it incorrectly.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions