/** * ═══════════════════════════════════════════════════════════════════════════════ * BULK INSERT 200+ RECORDS * For testing trigger and flow bulkification * ═══════════════════════════════════════════════════════════════════════════════ * * PURPOSE: * Test that triggers and flows handle bulk operations correctly. * Salesforce processes up to 200 records per transaction in normal contexts. * * WHY 251 RECORDS: * • 200 is the batch size for triggers (this tests the boundary) * • 250+ ensures multiple batches in batch Apex contexts * • 251 specifically crosses the 200 boundary * * WHAT TO VERIFY: * • No governor limit exceptions (SOQL, DML, CPU) * • All records processed correctly * • No N+1 query patterns * • Trigger/Flow logic executes correctly for all records * * ═══════════════════════════════════════════════════════════════════════════════ */ // ═══════════════════════════════════════════════════════════════════════════════ // CONFIGURATION // ═══════════════════════════════════════════════════════════════════════════════ Integer recordCount = 251; // Intentionally over 200 to test batch boundaries String namePrefix = 'BulkTest'; Boolean enableDebugLimits = true; // ═══════════════════════════════════════════════════════════════════════════════ // TRACKING COLLECTIONS (for cleanup) // ═══════════════════════════════════════════════════════════════════════════════ Set createdAccountIds = new Set(); Set createdContactIds = new Set(); Set createdOpportunityIds = new Set(); // ═══════════════════════════════════════════════════════════════════════════════ // CAPTURE INITIAL LIMITS // ═══════════════════════════════════════════════════════════════════════════════ Integer startQueries = Limits.getQueries(); Integer startDml = Limits.getDmlStatements(); Integer startCpu = Limits.getCpuTime(); Long startHeap = Limits.getHeapSize(); System.debug('═══════════════════════════════════════════════════════════════'); System.debug('Starting Bulk Insert Test: ' + recordCount + ' records'); System.debug('═══════════════════════════════════════════════════════════════'); // ═══════════════════════════════════════════════════════════════════════════════ // STEP 1: CREATE ACCOUNTS // ═══════════════════════════════════════════════════════════════════════════════ List accounts = new List(); List industries = new List{ 'Technology', 'Healthcare', 'Finance', 'Manufacturing', 'Retail', 'Education', 'Energy', 'Media' }; for (Integer i = 0; i < recordCount; i++) { accounts.add(new Account( Name = namePrefix + '_Account_' + String.valueOf(i).leftPad(5, '0'), Industry = industries[Math.mod(i, industries.size())], Type = Math.mod(i, 3) == 0 ? 'Customer' : 'Prospect', AnnualRevenue = 100000 + (i * 10000), NumberOfEmployees = 50 + (i * 5), BillingCity = 'San Francisco', BillingState = 'CA', BillingCountry = 'USA', Description = 'Bulk test account ' + i )); } try { insert accounts; for (Account acc : accounts) { createdAccountIds.add(acc.Id); } System.debug('✓ Created ' + accounts.size() + ' Accounts'); } catch (DmlException e) { System.debug('✗ Account creation failed: ' + e.getMessage()); throw e; } // ═══════════════════════════════════════════════════════════════════════════════ // STEP 2: CREATE CONTACTS (2 per Account = 502 Contacts) // ═══════════════════════════════════════════════════════════════════════════════ List contacts = new List(); Integer contactIndex = 0; for (Account acc : accounts) { for (Integer i = 0; i < 2; i++) { String idx = String.valueOf(contactIndex++).leftPad(5, '0'); contacts.add(new Contact( FirstName = namePrefix, LastName = 'Contact_' + idx, AccountId = acc.Id, Email = namePrefix.toLowerCase() + '.contact' + idx + '@bulktest.example.com', Phone = '(555) 100-' + String.valueOf(1000 + contactIndex), Title = Math.mod(contactIndex, 2) == 0 ? 'Manager' : 'Director' )); } } try { insert contacts; for (Contact con : contacts) { createdContactIds.add(con.Id); } System.debug('✓ Created ' + contacts.size() + ' Contacts'); } catch (DmlException e) { System.debug('✗ Contact creation failed: ' + e.getMessage()); throw e; } // ═══════════════════════════════════════════════════════════════════════════════ // STEP 3: CREATE OPPORTUNITIES (1 per Account = 251 Opportunities) // ═══════════════════════════════════════════════════════════════════════════════ List opportunities = new List(); List stages = new List{ 'Prospecting', 'Qualification', 'Needs Analysis', 'Proposal/Price Quote' }; Integer oppIndex = 0; for (Account acc : accounts) { String idx = String.valueOf(oppIndex++).leftPad(5, '0'); opportunities.add(new Opportunity( Name = namePrefix + '_Opportunity_' + idx, AccountId = acc.Id, StageName = stages[Math.mod(oppIndex, stages.size())], CloseDate = Date.today().addDays(30 + oppIndex), Amount = 10000 + (oppIndex * 1000), Type = 'New Customer', LeadSource = 'Web' )); } try { insert opportunities; for (Opportunity opp : opportunities) { createdOpportunityIds.add(opp.Id); } System.debug('✓ Created ' + opportunities.size() + ' Opportunities'); } catch (DmlException e) { System.debug('✗ Opportunity creation failed: ' + e.getMessage()); throw e; } // ═══════════════════════════════════════════════════════════════════════════════ // CAPTURE FINAL LIMITS // ═══════════════════════════════════════════════════════════════════════════════ Integer endQueries = Limits.getQueries(); Integer endDml = Limits.getDmlStatements(); Integer endCpu = Limits.getCpuTime(); Long endHeap = Limits.getHeapSize(); // ═══════════════════════════════════════════════════════════════════════════════ // REPORT RESULTS // ═══════════════════════════════════════════════════════════════════════════════ System.debug('═══════════════════════════════════════════════════════════════'); System.debug('BULK INSERT TEST COMPLETE'); System.debug('═══════════════════════════════════════════════════════════════'); System.debug(''); System.debug('📊 RECORDS CREATED:'); System.debug(' Accounts: ' + createdAccountIds.size()); System.debug(' Contacts: ' + createdContactIds.size()); System.debug(' Opportunities: ' + createdOpportunityIds.size()); System.debug(' TOTAL: ' + (createdAccountIds.size() + createdContactIds.size() + createdOpportunityIds.size())); System.debug(''); System.debug('📈 GOVERNOR LIMITS USED:'); System.debug(' SOQL Queries: ' + (endQueries - startQueries) + ' / 100'); System.debug(' DML Statements: ' + (endDml - startDml) + ' / 150'); System.debug(' CPU Time (ms): ' + (endCpu - startCpu) + ' / 10000'); System.debug(' Heap Size (bytes): ' + endHeap + ' / 6000000'); System.debug(''); System.debug('═══════════════════════════════════════════════════════════════'); // ═══════════════════════════════════════════════════════════════════════════════ // CLEANUP SCRIPT (Run separately after testing) // ═══════════════════════════════════════════════════════════════════════════════ /* CLEANUP - Copy and run this separately after testing: // Delete in correct order (children first) DELETE [SELECT Id FROM Opportunity WHERE Name LIKE 'BulkTest%']; DELETE [SELECT Id FROM Contact WHERE LastName LIKE 'Contact_%' AND Email LIKE '%bulktest.example.com']; DELETE [SELECT Id FROM Account WHERE Name LIKE 'BulkTest%']; System.debug('Cleanup complete'); */ // ═══════════════════════════════════════════════════════════════════════════════ // OUTPUT RECORD IDS FOR MANUAL CLEANUP // ═══════════════════════════════════════════════════════════════════════════════ System.debug(''); System.debug('Record IDs for cleanup (first 10 of each):'); System.debug('Account IDs: ' + new List(createdAccountIds).subList(0, Math.min(10, createdAccountIds.size()))); System.debug('Contact IDs: ' + new List(createdContactIds).subList(0, Math.min(10, createdContactIds.size()))); System.debug('Opportunity IDs: ' + new List(createdOpportunityIds).subList(0, Math.min(10, createdOpportunityIds.size())));