10

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

  • 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 – Tushar Sharma 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 at 18:18
17

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);
    }
}
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.

  • 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});
0

While unfortunately, there currently no way to get this via the tooling api or metadata api, you can retrieve all test class information form an org by sending a request to /_ui/common/apex/test/ApexTestQueueServlet.

This is definitely a bit of a hack and to make the request you will need pass the sid cookie (which can be retrieved in a separate call). Below is some example code (typescript) which shows how this can be done.

export interface OrgTests {
    success: boolean;
    testClasses: TestClass[];
    namespaces: string[][];
}

export interface TestClass {
    id: string;
    name: string;
    ns: string;
}

async function getOrgTests(instanceUrl: string, apiAccessToken: string): Promise<OrgTests> {
    //get SID cookie
    let url = `${instanceUrl}/secur/frontdoor.jsp?sid=${apiAccessToken}`;
    let frontDoor = await axios.default.get(
        url,
        {
            maxRedirects: 0, //IMPORTANT!
            validateStatus: (status) => status === 302
        }
    );
    //parse cookies
    let cookies: string[] = frontDoor.headers['set-cookie'];
    let cObject = {}
    for (let c of cookies) {
        let parts = c.split('=');
        let val = parts[1].split(';')[0]
        cObject[parts[0]] = val;
    }

    //get tests
    let result = await axios.default.post(`${instanceUrl}/_ui/common/apex/test/ApexTestQueueServlet`, 'action=GET_TESTS', {
        headers: {
            'content-type': 'application/x-www-form-urlencoded',
            'cookie': `sid=${cObject['sid']}`
        },
    })
    let sanitizedResult = result.data.replace('while(1);', '')
    console.log(sanitizedResult)
    return JSON.parse(sanitizedResult);
}

As with any "unofficially supported solution", SF could break this at any time without any warning.

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.