16

I need to get all test classes (classes with isTest Annotation) in an Org.. Is there anyway to filter test classes out of all the Apex Classes

2
  • 1
    I don't know if you need them in codebut if you want them in UI then go to Developer console and select run test class . where you will get all test classes name May 22 '16 at 6:53
  • Unless Apex and a UI in the org is an absolute requirement, I think the command-console solution is worth a try. It is very fast and simple.
    – SeanW
    Jun 10 '19 at 18:18
20

You can use a SOSL query to find your test classes. Note that this is not foolproof, as SOSL doesn't differentiate between comments and non-comments.

ApexClass[] unitTests = [FIND '@isTest' IN ALL FIELDS RETURNING ApexClass(Id, Name)][0];

I actually use this technique in my orgs to automate regression testing (runs once every 24 hours, and emails a result file). Just avoid using the word '@isTest' in your production code. In my processor, I also specifically exclude scheduler that calls this query to avoid having it run itself (harmless, but doesn't need to be run).

6

Based on previous answer, following approach worked for me

Http http = new Http();
HttpRequest request = new HttpRequest();
request.setEndpoint(URL.getOrgDomainUrl().toExternalForm() + '/_ui/common/apex/test/ApexTestQueueServlet');
request.setMethod('POST');
request.setHeader('content-type', 'application/x-www-form-urlencoded');
request.setHeader('cookie', 'sid=' + UserInfo.getSessionId());
request.setBody('action=GET_TESTS');
HttpResponse response = http.send(request);
// Parse the JSON response
if (response.getStatusCode() == 200) {
    String body = response.getBody().replace('while(1);', '');
    // Deserialize the JSON string into collections of primitive data types.
    Map<String, Object> results = (Map<String, Object>)JSON.deserializeUntyped(body);
    // Cast the values in the 'testClasses' key as a list
    List<Object> testClasses = (List<Object>) results.get('testClasses');
    System.debug('Received the following testClasses:');
    for (Object testClass: testClasses) {
        System.debug(testClass);
    }
}
3

With SFDX CLI, we can use the below query to get all test class names in the org:

sfdx force:data:soql:query 
--query="SELECT Id,Name,SymbolTable FROM ApexClass WHERE NamespacePrefix = ''" 
--usetoolingapi 
--targetusername=prod 
--json 
| jq '.result.records[] | select(.SymbolTable != null) 
|  select(.SymbolTable.methods[].annotations[].name == "IsTest")' 
| jq '.Name' | uniq

uniq and jq utilities are needed to run this command. It might be possible to get this working with just jq utility but i took the easy route.

2

You can go to "Setup > Develop > Apex Test Execution". There you can press on the button "Select Tests...", this will list all the current test classes in your org.

1

I'm assuming that you are asking to filter out the classes on Apex class list page of Salesforce.

Generally we follow a naming convention for the test classes that it is exactly the same name of class for which it is written plus have "Test" concatenated in the end or at least a test class always have "Test" in it's name.

for eg. ApexClassTest

If that is the case you can create a view in which you will apply a filter Name Contains Test.This will give you all the test classes of your org.

It's not a 100% foolproof method but maybe helpful for you.

4
  • That approach works well, until you realize that you need the word Test for some class or other. Personally, I'd avoid using that word and pick something you're not likely to use for a class name, such as a word in a different language, like "Prueba" ("Test" in Spanish), or even a convention of using specific nonsense letters like "ZZYZZ" (unless, of course, your team includes that one guy that legally changed his name to be in the Guinness Book of World Records...).
    – sfdcfox
    May 22 '16 at 6:27
  • @sfdcfox That's funny one but i'm really trying to understand the last two lines of your comments :D .And behind the answer my thought was that sometimes some orgs have really 100's of number of classes so if one or two non test class would also have "test" in there name that will not be very much of worry i guess ;)
    – Mr.Frodo
    May 22 '16 at 6:35
  • 1
    It really depends on specific scenarios. For example, one project I worked on I remember had a bunch of classes that were not unit tests with "Test" in the name, which made it impossible to filter lists using "Name contains Test". If the actual unit tests had a unique name style, it would have helped immensely. In most other projects I've done, using Test for unit tests was convention, and we went out of our way to make sure non-unit-tests did not contain Test. I'd learned a lesson though, and so I'd recommend using an uncommon or made up word for list view purposes.
    – sfdcfox
    May 22 '16 at 6:44
  • @sfdcfox Gotcha :)
    – Mr.Frodo
    May 22 '16 at 6:50
1

You can execute the following in the Anonymous Apex to get a CSV report of all the test classes.

Few things to keep in mind,

  • You may get the Actual Classes (not test) in the report if they have @isTest in the comment section.
  • If you have many classes in your org, you may hit the heap size. May be separating the SOQL query based on the Alphabets might help.
  • Make sure to change the e-mail address in the code. (8th line from bottom)
List<ApexClass> ac = [SELECT Id, Name, Body FROM ApexClass];
List<ApexClass> testClasses = new List<ApexClass>();
for(ApexClass a : ac){
    if(a.Body.containsIgnoreCase('@istest') || a.Body.contains('static testmethod')){
        testClasses.add(a);
    }
}
System.debug('Total classes: '+testClasses.size());

String myHeader = 'ID, NAME \n';
String fnlHeader = myHeader;

for(ApexClass apc : testClasses){
    String recString = apc.Id + ',' + apc.Name + '\n';
    fnlHeader = fnlHeader + recString;
}

Messaging.EmailFileAttachment csvAttc = new Messaging.EmailFileAttachment();
blob csvBlob = Blob.valueOf(fnlHeader);
string csvname= 'ApexTestClasses.csv';
csvAttc.setFileName(csvname);
csvAttc.setBody(csvBlob);
Messaging.SingleEmailMessage email =new Messaging.SingleEmailMessage();
String[] toAddresses = new list<string> {'YOUREMAIL@EXAMPLE.COM'};
String subject ='Apex Test Classes Report';
email.setSubject(subject);
email.setToAddresses( toAddresses );
email.setPlainTextBody('Apex Test Classes CSV ');
email.setFileAttachments(new Messaging.EmailFileAttachment[]{csvAttc});
Messaging.SendEmailResult [] r = Messaging.sendEmail(new Messaging.SingleEmailMessage[] {email});
1

Slight improvement on @sfdcfox's answer to also get any tests which use the testmethod modifier (recently depreciated but might still show up in older orgs).

ApexClass[] testClasses = [FIND '@istest or testmethod' 
                           IN ALL FIELDS 
                           RETURNING ApexClass(Id, Name)][0];

Again, this may return false positives, so avoid using either @istest or testmethod anywhere else in your code.

0

I would use a command prompt search, like this: findstr /L /I /M "@IsTest" *.cls

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.