Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

sfdx force:apex:test:report returns nothing for an AsyncApexJobId with any Aborted ApexClassIds #297

Closed
Pyronewbic opened this issue Feb 7, 2020 · 4 comments
Labels
area:apex Highlights the apex functional area of the CLI. owned by another team The Salesforce CLI team does not own this work but will pass on the information to the correct team.

Comments

@Pyronewbic
Copy link

Summary

Occasionally, on the platform, we run into issues with particular testMethods for an ApexClass running into loops. Therefore, we abort them (via an sfdx plugin we've created) - but any AsyncApexJobId that has Aborted ApexClassIds returns nothing when the report command is run for the AsyncApexJobId.

Steps To Reproduce:

Here's what a snippet of our code looks like:

private async runAllTests(): Promise<AnyJson>{

    ApexTestRunCommand.id = 'force:apex:test:run' 
    let testRun : any
    if(!this.flags.classnames){
      testRun = await ApexTestRunCommand.run(['-u',this.flags.targetusername,'--json','-l',this.flags.level])
    }else{
      this.ux.log(`Running for Specific TestClassNames!`)
      testRun = await ApexTestRunCommand.run(['-u',this.flags.targetusername,'--json','-n',this.flags.classnames])
    }
    let allTests : any = await this.testRun(testRun.testRunId,0)

    return allTests
  }
private async testRun(testRunId: string, ms:number): Promise<AnyJson>{

    let time = this.flags.retrytime+ms
    let skippedIds = []
    let flag = true

    DataRecordUpdateCommand.id = 'force:apex:data:update'
    DataRecordCreateCommand.id = 'force:apex:data:create'
  
    do {
        let res : any = await this.conn.query(`select Id,ApexClassId,MethodName,RunTime,ApexClass.Name FROM ApexTestResult where AsyncApexJobId='${testRunId}' and RunTime>${time} and ApexTestResult.ApexClassId in (select ApexTestQueueItem.ApexClassId from ApexTestQueueItem where Status='Processing' and ParentJobId='${testRunId}')`)
        
        if(res.records.length>0){
            for(const record of res.records){
              if(skippedIds.includes[record.ApexClassId]){
                this.ux.log(`ApexClassId ${record.ApexClassId} for ${record.ApexClass.Name} has already been Aborted, and records on ApexTestResult have been updated!`)
              }else{
                this.ux.log(`Aborting ApexClassId ${record.ApexClassId} since ${record.ApexClass.Name}.${record.MethodName} has crossed it's Threshold of ${time} milliseconds!`)
                await DataRecordUpdateCommand.run(['-s','ApexTestQueueItem','-w',`ParentJobId=${testRunId} ApexClassId=${record.ApexClassId}`,'-v','status=Aborted'])
                skippedIds.push(record.ApexClassId)
                let resp = await this.conn.query(`select Id,ApexClass.Name,MethodName from ApexTestResult where AsyncApexJobId='${testRunId}' and ApexClassId='${record.ApexClassId}'`)
                let rec : any
                for(rec of resp.records){
                  this.ux.log(`Updating ${rec.ApexClass.Name}.${rec.MethodName} with Id ${rec.Id} as Fail with an error Message!`)
                  await DataRecordUpdateCommand.run(['-s','ApexTestResult','-i',rec.Id,'-v',`Outcome=Fail Message='Class Was Looping!'`])
                }
                this.ux.log('\n') 
              }
            }
        }
        
        await new Promise(r => setTimeout(r, 30000))
        
        let resp: any = await this.conn.query(`select Status FROM ApexTestRunResult where AsyncApexJobId='${testRunId}'`)
        if(resp.records[0].Status=='Completed'){
          this.ux.log(`Running All Tests for id ${testRunId} is done!`)
          flag = false
        }else if(resp.records[0].Status=='Aborted'){
          throw new SfdxError(`This Particular ApexTestRun has been Aborted!`)
        }
    } while (flag)

    let testResults: any = await ApexTestReportCommand.run(['-w', this.TIMEOUT, '-i', testRunId, '-u', this.flags.targetusername , '--json'])
    return testResults
  }

Expected result

The ApexTestReportCommand should've returned results in json, considering that the test run was Completed.

Actual result

The result returned is { status: 0 }

Additional information

I've dug through the code (to salesforce-alm/dist/lib/apex/apexTestApi.js) and noticed this on line 671 under the 'checkProgress' method

if (status.Status === 'Completed' || status.Status === 'Failed'){
    this.completed[status.Id] = status;
  }
  else {
    allCompleted = false;
 }

and have updated it to be

if (status.Status === 'Completed' || status.Status === 'Failed' || status.Status === 'Aborted') {...}

It looks like it returns the test results successfully now - I know this was intended to be by design, but consider this scenario.

SFDX CLI Version: sfdx-cli/7.42.1 win32-x64 node-v8.11.3

SFDX plugin Version: salesforcedx 47.15.0 (core)

OS and version: Windows 10, Version 1809 (OS Build 17763.973)

@clairebianchi clairebianchi added the owned by another team The Salesforce CLI team does not own this work but will pass on the information to the correct team. label Feb 25, 2020
@clairebianchi
Copy link
Collaborator

@Pyronewbic I have notified the team that owns this command and they are taking a look.

@smaddox-sf
Copy link

Hi @Pyronewbic - Thanks for raising this. It is working as designed today, but this is an interesting use case. We will look this as a potential enhancement to consider when we do upcoming work in this area.

@preddivari preddivari added the area:apex Highlights the apex functional area of the CLI. label Sep 21, 2023
@iowillhoit
Copy link
Contributor

Hey @Pyronewbic, I am grooming some old Github Issues. This one is a little tricky to track down – a lot of migrations, ownership changes, and features have happened since it was opened. A quick scan of the [migrated] code looks like this might be fixed here.

If this is still not working as you'd expect when using the latest version of sf (currently 2.13.9), could you please open a new Github Issue with updated information. Thank you!

@Pyronewbic
Copy link
Author

Hi there, @iowillhoit - it's been a while since I've worked with sfdx, but I've upgraded deps to the latest version, and the changes made help my parallel apex class runs (with aborted ones if they cross a threshold time), return the required output. Thanks for pointing it out!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area:apex Highlights the apex functional area of the CLI. owned by another team The Salesforce CLI team does not own this work but will pass on the information to the correct team.
Projects
None yet
Development

No branches or pull requests

5 participants