Test Data Management & Isolation – Salesforce Platform Developer 1 Exam Guide
Why Test Data Management and Isolation Matters
In Salesforce development, automated testing is not optional — it is a platform requirement. Every production deployment demands at least 75% code coverage, and the integrity of those tests depends entirely on the data they use. If your tests rely on data that already exists in the org, they become fragile, unpredictable, and likely to fail when deployed to a different environment. Test data management and isolation is the discipline of ensuring that every test method creates, controls, and cleans up its own data, making tests reliable, repeatable, and environment-independent.
What Is Test Data Isolation?
By default, Apex test methods do not have access to the organization's existing data (with a few exceptions such as User, Profile, RecordType, and certain setup objects). This is governed by the test isolation framework built into the Salesforce platform. The framework ensures that:
• Test methods run in their own transaction context.
• Data created during a test is rolled back automatically after the test completes — nothing is permanently committed to the database.
• Tests cannot see standard or custom object records that already exist in the org, unless explicitly allowed.
This behavior was formalized starting with API version 24.0 and later. Tests written at API version 23.0 and earlier could see org data by default, but modern best practice (and the exam) focuses on the isolated model.
Key Concepts You Must Know
1. @isTest(SeeAllData=true) vs. @isTest(SeeAllData=false)
• @isTest(SeeAllData=false) — This is the default behavior. The test class or method cannot see any pre-existing org data (except certain setup objects). You must create all data the test needs.
• @isTest(SeeAllData=true) — This annotation explicitly allows the test to access all data in the org. This is strongly discouraged because it makes tests dependent on specific data existing, which can cause failures across environments.
The annotation can be applied at the class level or at the method level. If the class is marked SeeAllData=true, individual methods within it cannot override it to false. However, if the class is marked SeeAllData=false (or has no annotation, since false is the default), individual methods can be annotated with SeeAllData=true.
2. Test Data Factory / Utility Classes
A test data factory is a dedicated Apex class (annotated with @isTest) that contains reusable static methods for creating test records. For example:
@isTest
public class TestDataFactory {
public static Account createAccount(String name) {
Account a = new Account(Name = name);
insert a;
return a;
}
}
Benefits include:
• Centralised record creation logic — if a required field changes, you update one place.
• Consistency across all test classes.
• Reduced code duplication.
• The class annotated with @isTest does not count against the org's Apex code size limit.
3. @TestSetup Methods
The @TestSetup annotation designates a method that runs once before all test methods in the class. Data created in a @TestSetup method is available to every test method, but each test method gets its own copy of that data (a fresh rollback point). This means:
• Changes made by one test method do not affect another test method.
• You avoid redundant DML operations, improving test performance.
• Only one @TestSetup method is allowed per test class.
• @TestSetup cannot be used in a class that has @isTest(SeeAllData=true).
@TestSetup
static void setup() {
Account a = new Account(Name = 'Test Corp');
insert a;
Contact c = new Contact(LastName = 'Doe', AccountId = a.Id);
insert c;
}
4. Test.startTest() and Test.stopTest()
While not strictly about data isolation, these methods are critical for controlling governor limit context. Everything between Test.startTest() and Test.stopTest() gets a fresh set of governor limits. Additionally, Test.stopTest() forces all asynchronous operations (future methods, queueable jobs, batch Apex) to execute synchronously so you can assert their results immediately.
5. System.runAs()
The System.runAs(User u) method allows you to execute code in the context of a specific user. This is important for testing record sharing, profile-based access, and permission sets. Notably, User records are always visible in test context even without SeeAllData=true, so you can query existing users or create new ones.
6. Objects Always Visible in Tests
Even with SeeAllData=false, the following are accessible:
• User
• Profile
• Organization
• RecordType
• CronTrigger / AsyncApexJob (for verifying scheduled/batch jobs)
• Custom metadata types
• Custom settings (only if the test inserts them, unless they are hierarchy custom settings with org-default values which may be visible — this is nuanced)
How Test Data Isolation Works Under the Hood
When a test method executes:
1. The platform opens a transaction and sets a savepoint.
2. If a @TestSetup method exists and has already run, the platform restores the data from that savepoint for the current test method (each method gets its own copy).
3. The test method executes — any DML (inserts, updates, deletes) is real within that transaction.
4. Assertions are evaluated.
5. The platform rolls back all changes to the savepoint. No data persists.
This rollback mechanism is why tests are safe to run in production without creating junk data.
Best Practices for the Exam and Real-World Development
• Always create your own test data. Never rely on org data. Avoid SeeAllData=true unless absolutely necessary (e.g., testing against standard price book entries in some scenarios).
• Use @TestSetup to create common data once, improving efficiency.
• Use a TestDataFactory class for reusable data creation methods.
• Bulk-test your code. Create 200+ records in tests to ensure your code handles collections properly and does not hit governor limits.
• Assert results explicitly. Use System.assertEquals() and System.assertNotEquals() to verify outcomes — data isolation guarantees that you know exactly what data exists.
• Do not hard-code record IDs. IDs differ between orgs. Always query or create records dynamically.
• Avoid using SeeAllData=true to work around data dependency problems. Instead, fix the underlying code or create proper test data.
Exam Tips: Answering Questions on Test Data Management and Isolation
1. Default behavior is SeeAllData=false. If a question asks what data a test can see by default, the answer is: only data the test creates itself (plus User, Profile, RecordType, etc.).
2. @TestSetup questions: Remember that each test method gets its own rollback copy of the @TestSetup data. Changes in one method do not leak into another. Also remember that @TestSetup is incompatible with SeeAllData=true.
3. When the exam mentions 'test data factory': They are referring to a utility class annotated with @isTest that provides static methods for creating records. It does not count toward code size limits.
4. Governor limits in tests: Test.startTest() resets governor limits. Data setup should occur before Test.startTest(), and the code being tested should run between Test.startTest() and Test.stopTest().
5. Scenario-based questions: If a test is failing in a sandbox but passing in production (or vice versa), the likely cause is reliance on org-specific data. The fix is to create test data explicitly.
6. SeeAllData precedence: If the class is annotated SeeAllData=true, methods cannot override to false. If the class is false (default), individual methods can opt into true. The exam may test this hierarchy.
7. Bulk testing: The exam frequently asks about best practices. Always choose the answer that involves testing with 200 records to validate bulk behavior — this is a core Salesforce testing best practice.
8. Mixed DML errors in tests: If a question involves creating a User and then performing DML on a non-setup object in the same transaction, remember to use System.runAs() to avoid mixed DML exceptions. This is a common test isolation pattern.
9. Read the question carefully for keywords: 'Isolated,' 'independent,' 'repeatable,' and 'environment-agnostic' all point toward creating data in the test, not relying on existing records.
10. Know what is always accessible: Questions may try to trick you into thinking you need SeeAllData=true to query Profiles or RecordTypes. You do not — these are accessible by default in test context.
By mastering test data management and isolation, you ensure that your test classes are robust, portable, and aligned with Salesforce best practices — and you will be well-prepared for the multiple exam questions that cover this critical topic.