From f48cb1218a197b5c8b1f8a9bff7025c435781d96 Mon Sep 17 00:00:00 2001 From: Mike Donnalley Date: Fri, 13 Dec 2024 10:17:48 -0700 Subject: [PATCH] feat: support TAP format for test results --- src/agentTester.ts | 35 ++++++++++++++----- src/index.ts | 1 + test/agentTester.test.ts | 28 ++++++++++++++- ...tions_runs_4KBSM000000003F4AQ_details.json | 2 ++ 4 files changed, 56 insertions(+), 10 deletions(-) diff --git a/src/agentTester.ts b/src/agentTester.ts index 2de0e08..796bf1d 100644 --- a/src/agentTester.ts +++ b/src/agentTester.ts @@ -56,6 +56,8 @@ export type AgentTestDetailsResponse = { startTime: string; endTime?: string; errorMessage?: string; + subjectName: string; + testSetName: string; testCases: TestCaseResult[]; }; @@ -178,13 +180,6 @@ export async function jsonFormat(details: AgentTestDetailsResponse): Promise { - // Ideally, these would come from the API response. - // Worst case scenario, we cache these values when the customer starts the test run. - // Caching would generally work BUT it's problematic because it doesn't allow the customer to get the results from a test they didn't start on their machine - // and it doesn't allow them to get the results after the TTL cache expires. - const subjectName = 'Copilot_for_Salesforce'; - const testSetName = 'CRM_Sanity_v1'; - const { XMLBuilder } = await import('fast-xml-parser'); const builder = new XMLBuilder({ format: true, @@ -203,7 +198,7 @@ export async function junitFormat(details: AgentTestDetailsResponse): Promise\n${suites}`.trim(); } + +export async function tapFormat(details: AgentTestDetailsResponse): Promise { + const lines: string[] = []; + let expectationCount = 0; + for (const testCase of details.testCases) { + for (const result of testCase.expectationResults) { + const status = result.result === 'Passed' ? 'ok' : 'not ok'; + expectationCount++; + lines.push(`${status} ${expectationCount} ${details.testSetName}.${testCase.number}`); + if (status === 'not ok') { + lines.push(' ---'); + lines.push(` message: ${result.errorMessage ?? 'Unknown error'}`); + lines.push(` expectation: ${result.name}`); + lines.push(` actual: ${result.actualValue}`); + lines.push(` expected: ${result.expectedValue}`); + lines.push(' ...'); + } + } + } + + return Promise.resolve(`Tap Version 14\n1..${expectationCount}\n${lines.join('\n')}`); +} diff --git a/src/index.ts b/src/index.ts index e93d73d..3a5aa53 100644 --- a/src/index.ts +++ b/src/index.ts @@ -19,6 +19,7 @@ export { humanFormat, jsonFormat, junitFormat, + tapFormat, type AgentTestDetailsResponse, type AgentTestStartResponse, type AgentTestStatusResponse, diff --git a/test/agentTester.test.ts b/test/agentTester.test.ts index 29be8bb..4db7ff5 100644 --- a/test/agentTester.test.ts +++ b/test/agentTester.test.ts @@ -8,7 +8,7 @@ import { readFile } from 'node:fs/promises'; import { expect } from 'chai'; import { MockTestOrgData, TestContext } from '@salesforce/core/testSetup'; import { Connection } from '@salesforce/core'; -import { AgentTestDetailsResponse, AgentTester, junitFormat } from '../src/agentTester'; +import { AgentTestDetailsResponse, AgentTester, junitFormat, tapFormat } from '../src/agentTester'; describe('AgentTester', () => { const $$ = new TestContext(); @@ -100,3 +100,29 @@ describe('junitFormatter', () => { `); }); }); + +describe('tapFormatter', () => { + it('should transform test results to TAP format', async () => { + const raw = await readFile('./test/mocks/einstein_ai-evaluations_runs_4KBSM000000003F4AQ_details.json', 'utf8'); + const input = JSON.parse(raw) as AgentTestDetailsResponse; + const output = await tapFormat(input); + expect(output).to.deep.equal(`Tap Version 14 +1..4 +ok 1 CRM_Sanity_v1.1 +ok 2 CRM_Sanity_v1.1 +not ok 3 CRM_Sanity_v1.2 + --- + message: Expected "Result D" but got "Result C". + expectation: topic_sequence_match + actual: Result C + expected: Result D + ... +not ok 4 CRM_Sanity_v1.2 + --- + message: Expected "Result D" but got "Result C". + expectation: topic_sequence_match + actual: Result C + expected: Result D + ...`); + }); +}); diff --git a/test/mocks/einstein_ai-evaluations_runs_4KBSM000000003F4AQ_details.json b/test/mocks/einstein_ai-evaluations_runs_4KBSM000000003F4AQ_details.json index b025d94..81974ca 100644 --- a/test/mocks/einstein_ai-evaluations_runs_4KBSM000000003F4AQ_details.json +++ b/test/mocks/einstein_ai-evaluations_runs_4KBSM000000003F4AQ_details.json @@ -3,6 +3,8 @@ "startTime": "2024-11-28T12:00:00Z", "endTime": "2024-11-28T12:05:00Z", "errorMessage": null, + "subjectName": "Copilot_for_Salesforce", + "testSetName": "CRM_Sanity_v1", "testCases": [ { "status": "COMPLETED",