Why Is My Code Coverage Low and How Can I Fix It?

Question
Code coverage is a measurement of how many unique lines of code are executed when running automated tests. The percentage is calculated
Code Coverage = Covered Lines/ Covered Lines+Uncovered Lines * 100
Only executable lines are counted—comments, blank lines, System.debug()
statements, and standalone curly braces {}
are ignored. However, even after writing test methods, certain lines remain uncovered. Why does this happen, and how can I increase my code coverage effectively?
Answer
To increase code coverage, you must write functional unit tests that execute the untested code paths. While achieving high coverage is useful, the primary focus should be testing logic and behavior through well-designed test cases with proper assertions. Below are some common scenarios where code coverage issues arise and how to address them:
1. Conditional Statements (if/else, switch)
If your unit test only covers one branch of a conditional statement, the other branch remains uncovered.
Example:
public class SFSEExample {
public static void updateAccountDetails(Account a) {
if (a.Industry == 'Finance') {
a.Description = 'NOTE: Finance Industry. ' + a.Description;
} else {
a.Description = 'Non-finance industry. ' + a.Description;
}
}
}
Test Class (Only Partial Coverage):
@isTest
public class SFSEExample_TEST {
@isTest
public static void runTest() {
Account a = new Account(Name = 'Test', Industry = 'Finance', Description = 'Desc');
Test.startTest();
SFSEExample.updateAccountDetails(a);
Test.stopTest();
System.assertEquals('NOTE: Finance Industry. Desc', a.Description);
}
}
Here, only the if
block executes because the test sets Industry = 'Finance'
. The else
block remains uncovered.
Fix: Write another test case where Industry
is not 'Finance'
to ensure full coverage.
@isTest
public class SFSEExample_TEST {
@isTest
public static void testFinanceIndustry() {
Account a = new Account(Name = 'Test', Industry = 'Finance', Description = 'Desc');
Test.startTest();
SFSEExample.updateAccountDetails(a);
Test.stopTest();
System.assertEquals('NOTE: Finance Industry. Desc', a.Description);
}
@isTest
public static void testNonFinanceIndustry() {
Account a = new Account(Name = 'Test', Industry = 'Healthcare', Description = 'Desc');
Test.startTest();
SFSEExample.updateAccountDetails(a);
Test.stopTest();
System.assertEquals('Non-finance industry. Desc', a.Description);
}
}
2. Loops (for, while, do-while)
If a loop is not executed during tests, its body remains uncovered.
Example:
for (Account a : [SELECT Id, Name FROM Account WHERE Name LIKE 'ACME%']) {
a.Description = 'Here are some more details.';
}
If no Account
records exist that match the query, the loop never runs, leaving its body uncovered.
Fix: Ensure test data setup includes records that satisfy the query conditions:
@isTest
public class LoopTest {
@isTest
public static void testLoop() {
Account testAccount = new Account(Name = 'ACME Corp');
insert testAccount;
Test.startTest();
for (Account a : [SELECT Id, Name FROM Account WHERE Name LIKE 'ACME%']) {
a.Description = 'Here are some more details.';
}
Test.stopTest();
}
}
3. Batch Apex Coverage
If a Batch Apex class’s execute()
method isn’t covered, it’s often because start()
returns no records.
Example
public class MyBatch implements Database.Batchable<SObject> {
public Database.QueryLocator start(Database.BatchableContext BC) {
return Database.getQueryLocator('SELECT Id FROM Account WHERE Name LIKE \'ACME%\'');
}
public void execute(Database.BatchableContext BC, List<SObject> scope) {
for (Account a : (List<Account>) scope) {
a.Description = 'Batch Updated';
}
update scope;
}
public void finish(Database.BatchableContext BC) {}
}
Fix: Insert test records before executing the batch:
@isTest
public class MyBatchTest {
@isTest
public static void testBatch() {
Account testAccount = new Account(Name = 'ACME Corp');
insert testAccount;
Test.startTest();
MyBatch batch = new MyBatch();
Database.executeBatch(batch);
Test.stopTest();
}
}
4. Exception Handling
Code inside a catch
block is executable and must be covered by tests.
Example (Uncovered Catch Block):
public class ExceptionExample {
public static void riskyMethod() {
try {
Integer x = 5 / 0; // Division by zero error
} catch (Exception e) {
System.debug('Exception caught: ' + e.getMessage());
}
}
}
Fix: Write a test case that triggers the exception.
@isTest
public class ExceptionExampleTest {
@isTest
public static void testExceptionHandling() {
Test.startTest();
ExceptionExample.riskyMethod();
Test.stopTest();
}
}
5. Savepoint and addError()
Coverage
Apex methods that use addError()
or rollbacks need explicit tests.
Example:
public class AccountTriggerHandler {
public static void validateAccount(Account a) {
if (a.Name == 'Restricted') {
a.addError('This name is not allowed.');
}
}
}
Fix: Use Database.insert(yourTestRecord, false)
to capture errors:
@isTest
public class AccountTriggerHandlerTest {
@isTest
public static void testAddError() {
Account a = new Account(Name = 'Restricted');
Database.SaveResult result = Database.insert(a, false);
System.assert(!result.isSuccess(), 'Insert should fail');
System.assertEquals('This name is not allowed.', result.getErrors()[0].getMessage());
}
}
6. Covering Properties
Properties with explicit or implicit getters/setters are executable and require coverage.
Example:
public class PropertyExample {
public Integer index { get; set; }
}
Fix: Access the property in your test:
@isTest
public class PropertyExampleTest {
@isTest
public static void testProperty() {
PropertyExample obj = new PropertyExample();
obj.index = 5;
System.assertEquals(5, obj.index);
}
}
Code coverage issues are often caused by missing test data, untested conditional paths, and overlooked edge cases. By understanding these patterns and writing targeted unit tests, you can increase your code coverage while ensuring meaningful test coverage of logic and behavior.
Real-Time Project-Based Salesforce Training to Kick Start Your Career
Our Salesforce course is thoughtfully designed to provide a comprehensive understanding of the Salesforce platform, equipping you with the essential skills to succeed in the CRM industry. The program covers vital modules like Salesforce Admin, Developer, and AI, combining theoretical learning with hands-on application. By engaging in real-world projects and interactive exercises, you’ll gain the expertise to solve complex business challenges using Salesforce solutions. Our seasoned instructors ensure you develop both technical proficiency and industry knowledge to thrive in the Salesforce ecosystem.
Beyond technical expertise, our Salesforce Training in New York includes personalized mentorship, certification support, and interview preparation to boost your career prospects. You’ll gain access to in-depth study resources, real-time project experience, and continuous guidance throughout your learning journey. By the end of the course, you’ll be well-prepared for certification exams and possess the problem-solving skills employers seek. Take the first step toward a rewarding Salesforce career—enroll in a Free Demo today!