Since: PMD 6.13.0
Priority: Medium (3)
The second parameter of System.assert/third parameter of System.assertEquals/System.assertNotEquals is a message.Having a second/third parameter provides more information and makes it easier to debug the test failure andimproves the readability of test output.
This rule is defined by the following Java class:net.sourceforge.pmd.lang.apex.rule.bestpractices.ApexAssertionsShouldIncludeMessageRule
Example(s):
@isTestpublicclassFoo{@isTeststaticvoidmethodATest(){System.assertNotEquals('123',o.StageName);// not goodSystem.assertEquals('123',o.StageName,'OpportunitystageNameiswrong.');// goodSystem.assert(o.isClosed);// not goodSystem.assert(o.isClosed,'Opportunityisnotclosed.');// good}}
Use this rule by referencing it:
<ruleref="category/apex/bestpractices.xml/ApexAssertionsShouldIncludeMessage"/>
Since: PMD 5.5.1
Priority: Medium (3)
Apex unit tests should include at least one assertion. This makes the tests more robust, and using assertwith messages provide the developer a clearer idea of what the test does. Custom assert method invocationpatterns can be specified using the ‘additionalAssertMethodPattern’ property if required.
This rule is defined by the following Java class:net.sourceforge.pmd.lang.apex.rule.bestpractices.ApexUnitTestClassShouldHaveAssertsRule
Example(s):
@isTestpublicclassFoo{publicstatictestMethodvoidtestSomething(){Accounta=null;// This is better than having a NullPointerException// System.assertNotEquals(a, null, 'account not found');a.toString();}}
This rule has the following properties:
Name | Default Value | Description |
---|---|---|
additionalAssertMethodPattern | A regular expression for one or more custom test assertion method patterns. |
Use this rule with the default properties by just referencing it:
<ruleref="category/apex/bestpractices.xml/ApexUnitTestClassShouldHaveAsserts"/>
Use this rule and customize it:
<ruleref="category/apex/bestpractices.xml/ApexUnitTestClassShouldHaveAsserts"><properties><propertyname="additionalAssertMethodPattern"value=""/></properties></rule>
Since: PMD 6.51.0
Priority: Medium (3)
Apex unit tests should include at least one runAs method. This makes the tests more robust, and independent from the user running it.
This rule is defined by the following Java class:net.sourceforge.pmd.lang.apex.rule.bestpractices.ApexUnitTestClassShouldHaveRunAsRule
Example(s):
@isTestprivateclassTestRunAs{publicstatictestMethodvoidtestRunAs(){// Setup test data// Create a unique UserNameStringuniqueUserName='standarduser'+DateTime.now().getTime()+'@testorg.com';// This code runs as the system userProfilep=[SELECTIdFROMProfileWHEREName='StandardUser'];Useru=newUser(Alias='standt',Email='standarduser@testorg.com',EmailEncodingKey='UTF-8',LastName='Testing',LanguageLocaleKey='en_US',LocaleSidKey='en_US',ProfileId=p.Id,TimeZoneSidKey='America/Los_Angeles',UserName=uniqueUserName);System.runAs(u){// The following code runs as user 'u'System.debug('CurrentUser:'+UserInfo.getUserName());System.debug('CurrentProfile:'+UserInfo.getProfileId());}}}
Use this rule by referencing it:
<ruleref="category/apex/bestpractices.xml/ApexUnitTestClassShouldHaveRunAs"/>
Since: PMD 6.13.0
Priority: Medium (3)
Apex test methods should have@isTest
annotation instead of thetestMethod
keyword,astestMethod
is deprecated.Salesforce advices to use@isTestannotation for test classes and methods.
This rule is defined by the following XPath expression:
//Method[ModifierNode[@DeprecatedTestMethod=true()]]
Example(s):
@isTestprivateclassATest{@isTeststaticvoidmethodATest(){}staticvoidmethodBTest(){}@isTeststaticvoidmethodCTest(){System.assert(1==2);}statictestmethodvoidmethodCTest(){System.debug('Iamadebugstatement');}privatevoidfetchData(){}}
Use this rule by referencing it:
<ruleref="category/apex/bestpractices.xml/ApexUnitTestMethodShouldHaveIsTestAnnotation"/>
Since: PMD 5.5.1
Priority: Medium (3)
Apex unit tests should not use @isTest(seeAllData=true) because it opens up the existing database data for unexpected modification by tests.
This rule is defined by the following Java class:net.sourceforge.pmd.lang.apex.rule.bestpractices.ApexUnitTestShouldNotUseSeeAllDataTrueRule
Example(s):
@isTest(seeAllData=true)publicclassFoo{publicstatictestMethodvoidtestSomething(){Accounta=null;// This is better than having a NullPointerException// System.assertNotEquals(a, null, 'account not found');a.toString();}}
Use this rule by referencing it:
<ruleref="category/apex/bestpractices.xml/ApexUnitTestShouldNotUseSeeAllDataTrue"/>
Since: PMD 5.5.0
Priority: Medium (3)
Global classes should be avoided (especially in managed packages) as they can never be deleted or changed in signature. Always check twice if something needs to be global.Many interfaces (e.g. Batch) required global modifiers in the past but don’t require this anymore. Don’t lock yourself in.
This rule is defined by the following Java class:net.sourceforge.pmd.lang.apex.rule.bestpractices.AvoidGlobalModifierRule
Example(s):
globalclassUnchangeable{globalUndeletableTypeunchangable(UndeletableTypeparam){// ...}}
Use this rule by referencing it:
<ruleref="category/apex/bestpractices.xml/AvoidGlobalModifier"/>
Since: PMD 5.5.0
Priority: Medium (3)
As triggers do not allow methods like regular classes they are less flexible and suited to apply good encapsulation style.Therefore delegate the triggers work to a regular class (often called Trigger handler class).
See more here:https://developer.salesforce.com/page/Trigger_Frameworks_and_Apex_Trigger_Best_Practices
This rule is defined by the following Java class:net.sourceforge.pmd.lang.apex.rule.bestpractices.AvoidLogicInTriggerRule
Example(s):
triggerAccountsonAccount(beforeinsert,beforeupdate,beforedelete,afterinsert,afterupdate,afterdelete,afterundelete){for(Accountacc:Trigger.new){if(Trigger.isInsert){// ...}// ...if(Trigger.isDelete){// ...}}}
Use this rule by referencing it:
<ruleref="category/apex/bestpractices.xml/AvoidLogicInTrigger"/>
Since: PMD 6.18.0
Priority: Medium (3)
The first parameter of System.debug, when using the signature with two parameters, is a LoggingLevel enum.
Having the Logging Level specified provides a cleaner log, and improves readability of it.
This rule is defined by the following XPath expression:
//MethodCallExpression[lower-case(@FullMethodName)='system.debug'][count(*)=2or($strictMode=true()andcount(*)=3andlower-case(VariableExpression/@Image)='debug')]
Example(s):
@isTestpublicclassFoo{@isTeststaticvoidbar(){System.debug('Heythiscodeexecuted.');// not goodSystem.debug(LoggingLevel.WARN,'Hey,somethingmightbewrong.');// goodSystem.debug(LoggingLevel.DEBUG,'Hey,somethinghappened.');// not good when on strict mode}}
This rule has the following properties:
Name | Default Value | Description |
---|---|---|
strictMode | false | If true, mark statements that use the DEBUG enum of LoggingLevel. |
Use this rule with the default properties by just referencing it:
<ruleref="category/apex/bestpractices.xml/DebugsShouldUseLoggingLevel"/>
Use this rule and customize it:
<ruleref="category/apex/bestpractices.xml/DebugsShouldUseLoggingLevel"><properties><propertyname="strictMode"value="false"/></properties></rule>
Since: PMD 7.8.0
Priority: Low (5)
Detects when the Queueable interface is used but a Finalizer is not attached.It is best practice to call theSystem.attachFinalizer(Finalizer f)
method within theexecute
method of a class which implements theQueueable
interface.Without attaching a Finalizer, there is no way of designing error recovery actions should the Queueable action fail.
This rule is defined by the following Java class:net.sourceforge.pmd.lang.apex.rule.bestpractices.QueueableWithoutFinalizerRule
Example(s):
// Incorrect code, does not attach a finalizer.publicclassUserUpdaterimplementsQueueable{publicList<User>usersToUpdate;publicUserUpdater(List<User>usersToUpdate){this.usersToUpdate=usersToUpdate;}publicvoidexecute(QueueableContextcontext){// no Finalizer is attachedupdateusersToUpdate;}}// Proper code, attaches a finalizer.publicclassUserUpdaterimplementsQueueable,Finalizer{publicList<User>usersToUpdate;publicUserUpdater(List<User>usersToUpdate){this.usersToUpdate=usersToUpdate;}publicvoidexecute(QueueableContextcontext){System.attachFinalizer(this);updateusersToUpdate;}publicvoidexecute(FinalizerContextctx){if(ctx.getResult()==ParentJobResult.SUCCESS){// Handle success}else{// Handle failure}}}
Use this rule by referencing it:
<ruleref="category/apex/bestpractices.xml/QueueableWithoutFinalizer"/>
Since: PMD 6.23.0
Priority: Low (5)
Detects when a local variable is declared and/or assigned but not used.
This rule is defined by the following Java class:net.sourceforge.pmd.lang.apex.rule.bestpractices.UnusedLocalVariableRule
Example(s):
publicBooleanbar(Stringz){Stringx='somestring';// not usedStringy='someotherstring';// used in the next linereturnz.equals(y);}
Use this rule by referencing it:
<ruleref="category/apex/bestpractices.xml/UnusedLocalVariable"/>