From 85ff2a0bec83825dc087f44b0a6b139041500f11 Mon Sep 17 00:00:00 2001 From: arcuri82 Date: Mon, 27 Oct 2025 14:14:41 +0100 Subject: [PATCH 1/5] added evaluatedHttpCalls and executionTimeInSeconds. renamed totalHttpCalls into outputHttpCalls --- src/main/resources/wfc/schemas/report.yaml | 29 +++++++++++++++++--- web-report/src-e2e/App.test.tsx | 4 +-- web-report/src-e2e/static/report.json | 2 +- web-report/src/components/GeneratedTests.tsx | 6 ++-- web-report/src/pages/Overview.tsx | 2 +- web-report/src/types/GeneratedTypes.tsx | 12 ++++++-- web-report/src/types/GeneratedTypesZod.ts | 4 ++- 7 files changed, 45 insertions(+), 14 deletions(-) diff --git a/src/main/resources/wfc/schemas/report.yaml b/src/main/resources/wfc/schemas/report.yaml index cd2ce3f..26e76bc 100644 --- a/src/main/resources/wfc/schemas/report.yaml +++ b/src/main/resources/wfc/schemas/report.yaml @@ -48,6 +48,10 @@ properties: type: array items: $ref: "#/$defs/TestCase" + executionTimeInSeconds: + type: integer + minimum: 0 + description: "For how long, in seconds, the tool was running in total." #OPTIONAL extra: description: "Extra, optional coverage information, collected by different tools." @@ -55,7 +59,17 @@ properties: items: $ref: "#/$defs/Coverage" -required: ["schemaVersion","toolName","toolVersion","creationTime","faults","problemDetails","totalTests","testFilePaths","testCases"] +required: + - "schemaVersion" + - "toolName" + - "toolVersion" + - "creationTime" + - "faults" + - "problemDetails" + - "totalTests" + - "testFilePaths" + - "testCases" + - "executionTimeInSeconds" $defs: OperationId: @@ -122,11 +136,18 @@ $defs: RESTReport: type: object properties: - totalHttpCalls: - description: "Total number of HTTP calls made in all the test cases. A test case could contain several HTTP calls, \ + outputHttpCalls: + description: "Total number of HTTP calls made in all the generated test cases given as output. \ + A test case could contain several HTTP calls, \ e.g., a POST followed by a GET and then a DELETE." type: integer minimum: 0 + evaluatedHttpCalls: + description: "Total number of all HTTP calls made during the whole fuzzing session. \ + If the fuzzing was left running for hours, millions of HTTP could have been made. + The output generated tests will only contain a tiny subset of these evaluated calls." + type: integer + minimum: 0 endpointIds: description: "Unique ids of all the endpoints in the tested API." type: array @@ -138,7 +159,7 @@ $defs: type: array items: $ref: "#/$defs/CoveredEndpoint" - required: ["totalHttpCalls","endpointIds","coveredHttpStatus"] + required: ["outputHttpCalls","evaluatedHttpCalls","endpointIds","coveredHttpStatus"] TestCase: type: object diff --git a/web-report/src-e2e/App.test.tsx b/web-report/src-e2e/App.test.tsx index 2fca749..5b95d82 100644 --- a/web-report/src-e2e/App.test.tsx +++ b/web-report/src-e2e/App.test.tsx @@ -79,11 +79,11 @@ describe('App test', () => { render(); expect(screen.getByText(/Please wait, files are loading.../)).toBeInTheDocument(); const total = reportData.problemDetails.rest.endpointIds.length; - const totalHttpCalls = reportData.problemDetails.rest.totalHttpCalls; + const outputHttpCalls = reportData.problemDetails.rest.outputHttpCalls; await waitFor(() => { expect(screen.getByTestId('rest-report-endpoint')).toContainHTML(`${total}`); - expect(screen.getByTestId('rest-report-http-calls')).toContainHTML(`${totalHttpCalls}`); + expect(screen.getByTestId('rest-report-http-calls')).toContainHTML(`${outputHttpCalls}`); }); }); diff --git a/web-report/src-e2e/static/report.json b/web-report/src-e2e/static/report.json index 93a9940..7679913 100644 --- a/web-report/src-e2e/static/report.json +++ b/web-report/src-e2e/static/report.json @@ -2970,7 +2970,7 @@ }, "problemDetails": { "rest": { - "totalHttpCalls": 130, + "outputHttpCalls": 130, "endpointIds": [ "GET:/app/api/assignments", "POST:/app/api/assignments", diff --git a/web-report/src/components/GeneratedTests.tsx b/web-report/src/components/GeneratedTests.tsx index 8a4db65..1426e7a 100644 --- a/web-report/src/components/GeneratedTests.tsx +++ b/web-report/src/components/GeneratedTests.tsx @@ -11,10 +11,10 @@ interface IGeneratedTests { fileName: string, numberOfTestCases: number }> - totalHttpCalls?: number + outputHttpCalls?: number } -export const GeneratedTests: React.FC = ({totalTests, testFiles, totalHttpCalls}) => ( +export const GeneratedTests: React.FC = ({totalTests, testFiles, outputHttpCalls}) => (
@@ -35,7 +35,7 @@ export const GeneratedTests: React.FC = ({totalTests, testFiles # HTTP Calls: - {totalHttpCalls} + {outputHttpCalls}
diff --git a/web-report/src/pages/Overview.tsx b/web-report/src/pages/Overview.tsx index e05119c..6f96d84 100644 --- a/web-report/src/pages/Overview.tsx +++ b/web-report/src/pages/Overview.tsx @@ -22,7 +22,7 @@ export const Overview: React.FC = ({rest, testCases, testFiles, f {/* Right Panel */}
{/* Generated Tests */} - + {/* Faults */}
diff --git a/web-report/src/types/GeneratedTypes.tsx b/web-report/src/types/GeneratedTypes.tsx index 41d430f..a6d2a0a 100644 --- a/web-report/src/types/GeneratedTypes.tsx +++ b/web-report/src/types/GeneratedTypes.tsx @@ -56,6 +56,10 @@ export interface WebFuzzingCommonsReport { * Information on each generated test case. */ testCases: TestCase[]; + /** + * For how long, in seconds, the tool was running in total. + */ + executionTimeInSeconds: number; /** * Extra, optional coverage information, collected by different tools. */ @@ -101,9 +105,13 @@ export interface FaultCategoryId { } export interface RESTReport { /** - * Total number of HTTP calls made in all the test cases. A test case could contain several HTTP calls, e.g., a POST followed by a GET and then a DELETE. + * Total number of HTTP calls made in all the generated test cases given as output. A test case could contain several HTTP calls, e.g., a POST followed by a GET and then a DELETE. + */ + outputHttpCalls: number; + /** + * Total number of all HTTP calls made during the whole fuzzing session. If the fuzzing was left running for hours, millions of HTTP could have been made. The output generated tests will only contain a tiny subset of these evaluated calls. */ - totalHttpCalls: number; + evaluatedHttpCalls: number; /** * Unique ids of all the endpoints in the tested API. */ diff --git a/web-report/src/types/GeneratedTypesZod.ts b/web-report/src/types/GeneratedTypesZod.ts index 941f69a..279beff 100644 --- a/web-report/src/types/GeneratedTypesZod.ts +++ b/web-report/src/types/GeneratedTypesZod.ts @@ -44,7 +44,8 @@ export const coverageCriterionSchema = z.record(z.unknown()).and( export const rESTReportSchema = z.record(z.unknown()).and( z.object({ - totalHttpCalls: z.number(), + outputHttpCalls: z.number(), + evaluatedHttpCalls: z.number(), endpointIds: z.array(operationIdSchema), coveredHttpStatus: z.array(coveredEndpointSchema), }), @@ -89,6 +90,7 @@ export const webFuzzingCommonsReportSchema = z.record(z.unknown()).and( totalTests: z.number(), testFilePaths: z.array(testFilePathSchema), testCases: z.array(testCaseSchema), + executionTimeInSeconds: z.number(), extra: z.array(coverageSchema).optional().nullable(), }), ); From 555e84d468e2ceda2142b93c66d267fbed67ff32 Mon Sep 17 00:00:00 2001 From: Omur Sahin Date: Tue, 28 Oct 2025 22:24:16 +0300 Subject: [PATCH 2/5] adding new entries --- web-report/package.json | 2 +- web-report/src-e2e/App.test.tsx | 10 ++-- web-report/src-e2e/static/report.json | 8 ++- web-report/src/assets/info.json | 6 +- web-report/src/components/Dashboard.tsx | 4 +- web-report/src/components/GeneratedTests.tsx | 63 ++++++++++++++++++-- web-report/src/pages/Overview.tsx | 11 +++- 7 files changed, 84 insertions(+), 20 deletions(-) diff --git a/web-report/package.json b/web-report/package.json index 2467ea8..8f68eb0 100644 --- a/web-report/package.json +++ b/web-report/package.json @@ -11,7 +11,7 @@ "copyRunFiles": "cpx webreport.bat '../target/classes/webreport' && cpx webreport.command '../target/classes/webreport' && cpx webreport.py '../target/classes/webreport' && cpx 'src-e2e/static/robots.txt' '../target/classes/webreport'", "lint": "eslint .", "preview": "vite preview", - "debug": "vite build && cpx 'src-e2e/static/*' '../target/classes/webreport' && vite preview", + "debug": "vite build && cpx src-e2e/static/* ../target/classes/webreport && vite preview", "test": "vitest" }, "dependencies": { diff --git a/web-report/src-e2e/App.test.tsx b/web-report/src-e2e/App.test.tsx index 5b95d82..e55b676 100644 --- a/web-report/src-e2e/App.test.tsx +++ b/web-report/src-e2e/App.test.tsx @@ -41,10 +41,10 @@ describe('App test', () => { it('handles successful data loading', async () => { render(); - + // Initially shows loading state expect(screen.getByText(/Please wait, files are loading.../)).toBeInTheDocument(); - + // Wait for loading to complete and verify header data await waitFor(() => { expect(screen.queryByText(/Please wait, files are loading.../)).toBeNull(); @@ -80,10 +80,12 @@ describe('App test', () => { expect(screen.getByText(/Please wait, files are loading.../)).toBeInTheDocument(); const total = reportData.problemDetails.rest.endpointIds.length; const outputHttpCalls = reportData.problemDetails.rest.outputHttpCalls; + const evaluatedHttpCalls = reportData.problemDetails.rest.evaluatedHttpCalls; await waitFor(() => { expect(screen.getByTestId('rest-report-endpoint')).toContainHTML(`${total}`); - expect(screen.getByTestId('rest-report-http-calls')).toContainHTML(`${outputHttpCalls}`); + expect(screen.getByTestId('rest-report-output-http-calls')).toContainHTML(`${outputHttpCalls}`); + expect(screen.getByTestId('rest-report-evaluated-http-calls')).toContainHTML(`${evaluatedHttpCalls}`); }); }); @@ -143,4 +145,4 @@ describe('App test', () => { expect(screen.getByTestId('faults-component-fault-counts')).toContainHTML(faultCounts.length.toString()); }); }); -}); \ No newline at end of file +}); diff --git a/web-report/src-e2e/static/report.json b/web-report/src-e2e/static/report.json index 7679913..7f32b47 100644 --- a/web-report/src-e2e/static/report.json +++ b/web-report/src-e2e/static/report.json @@ -3,6 +3,7 @@ "toolName": "EvoMaster", "toolVersion": "unknown", "creationTime": "2025-04-09T19:31:54.258Z", + "executionTimeInSeconds": 6780000, "faults": { "totalNumber": 529, "foundFaults": [ @@ -2970,7 +2971,7 @@ }, "problemDetails": { "rest": { - "outputHttpCalls": 130, + "outputHttpCalls": 25, "endpointIds": [ "GET:/app/api/assignments", "POST:/app/api/assignments", @@ -3951,7 +3952,8 @@ 200 ] } - ] + ], + "evaluatedHttpCalls": 132 } }, "totalTests": 127, @@ -4867,4 +4869,4 @@ ] } ] -} \ No newline at end of file +} diff --git a/web-report/src/assets/info.json b/web-report/src/assets/info.json index c95eb28..36c02cb 100644 --- a/web-report/src/assets/info.json +++ b/web-report/src/assets/info.json @@ -1,6 +1,8 @@ { "numberOfEndpoints": "Number of endpoints (verb:path) in the API.", - "numberOfHttpCalls": "Total number of HTTP calls in the generated test suites.", + "outputHttpCalls": "Total number of HTTP calls contained in all generated test cases - a single test case may include multiple calls (e.g., a POST followed by a GET and then a DELETE).", + "evaluatedHttpCalls": "Total number of all HTTP calls made during the entire fuzzing session - in long runs, this can reach millions, while the generated tests include only a small subset of these calls.", + "executionTimeInSeconds": "For how long, in seconds, the tool was running in total.", "codeNumberIdentifiers": "Code number identifiers for detected fault types", "identifierName": "Identifier name for the fault type.", "testFilesLocated": "{numberOfTestCases} test cases are located in {fileName}", @@ -15,4 +17,4 @@ "creationDate": "Date when the report was generated.", "toolNameVersion": "Name and version of the tool that generated the report.", "schemaVersion": "Version of the schema used for the report." -} \ No newline at end of file +} diff --git a/web-report/src/components/Dashboard.tsx b/web-report/src/components/Dashboard.tsx index 6c41ade..f5b1f2e 100644 --- a/web-report/src/components/Dashboard.tsx +++ b/web-report/src/components/Dashboard.tsx @@ -114,7 +114,9 @@ export const Dashboard: React.FC = () => { + faults={data.faults} + executionTimeInSeconds={data.executionTimeInSeconds} + /> diff --git a/web-report/src/components/GeneratedTests.tsx b/web-report/src/components/GeneratedTests.tsx index 1426e7a..ecd6878 100644 --- a/web-report/src/components/GeneratedTests.tsx +++ b/web-report/src/components/GeneratedTests.tsx @@ -1,5 +1,5 @@ import {Card} from "@/components/ui/card.tsx"; -import {Target} from "lucide-react"; +import {Target, Clock} from "lucide-react"; import type React from "react"; import {getFileColor, getText} from "@/lib/utils"; import info from "@/assets/info.json"; @@ -12,9 +12,25 @@ interface IGeneratedTests { numberOfTestCases: number }> outputHttpCalls?: number + evaluatedHttpCalls?: number + executionTimeInSeconds?: number } -export const GeneratedTests: React.FC = ({totalTests, testFiles, outputHttpCalls}) => ( +const formatExecutionTime = (totalSeconds?: number) => { + if (totalSeconds === undefined || totalSeconds === null) return null; + + const days = Math.floor(totalSeconds / 86400); + const hours = Math.floor((totalSeconds % 86400) / 3600); + const minutes = Math.floor((totalSeconds % 3600) / 60); + const seconds = Math.floor(totalSeconds % 60); + + return { days, hours, minutes, seconds }; +}; + +export const GeneratedTests: React.FC = ({totalTests, testFiles, outputHttpCalls, evaluatedHttpCalls, executionTimeInSeconds}) => { + const timeBreakdown = formatExecutionTime(executionTimeInSeconds); + + return (
@@ -32,11 +48,45 @@ export const GeneratedTests: React.FC = ({totalTests, testFiles {totalTests}
- - # HTTP Calls: + + # Output HTTP Calls: - {outputHttpCalls} + {outputHttpCalls}
+
+ + # Evaluated HTTP Calls: + + {evaluatedHttpCalls} +
+ {timeBreakdown && ( +
+ +
+ + Execution Time +
+
+
+
+
{timeBreakdown.days}
+
Days
+
+
+
{timeBreakdown.hours}
+
Hours
+
+
+
{timeBreakdown.minutes}
+
Minutes
+
+
+
{timeBreakdown.seconds}
+
Seconds
+
+
+
+ )}
Test Files
@@ -64,4 +114,5 @@ export const GeneratedTests: React.FC = ({totalTests, testFiles
-) \ No newline at end of file + ); +}; diff --git a/web-report/src/pages/Overview.tsx b/web-report/src/pages/Overview.tsx index 6f96d84..d447227 100644 --- a/web-report/src/pages/Overview.tsx +++ b/web-report/src/pages/Overview.tsx @@ -12,9 +12,10 @@ interface IOverviewType { numberOfTestCases: number }>, faults: Faults + executionTimeInSeconds: number; } -export const Overview: React.FC = ({rest, testCases, testFiles, faults}) => { +export const Overview: React.FC = ({rest, testCases, testFiles, faults, executionTimeInSeconds}) => { return (
{/* Left Panel */} @@ -22,10 +23,14 @@ export const Overview: React.FC = ({rest, testCases, testFiles, f {/* Right Panel */}
{/* Generated Tests */} - + {/* Faults */}
) -} \ No newline at end of file +} From ac3874b151a52b96c02b41c0fe73d083a8914870 Mon Sep 17 00:00:00 2001 From: Omur Sahin Date: Tue, 28 Oct 2025 22:58:19 +0300 Subject: [PATCH 3/5] update --- web-report/src/components/GeneratedTests.tsx | 107 +++++++++++++------ 1 file changed, 75 insertions(+), 32 deletions(-) diff --git a/web-report/src/components/GeneratedTests.tsx b/web-report/src/components/GeneratedTests.tsx index ecd6878..b9c3d89 100644 --- a/web-report/src/components/GeneratedTests.tsx +++ b/web-report/src/components/GeneratedTests.tsx @@ -1,5 +1,5 @@ import {Card} from "@/components/ui/card.tsx"; -import {Target, Clock} from "lucide-react"; +import {Target, Clock, FileText, TestTube, Network, CheckCircle, FolderOpen} from "lucide-react"; import type React from "react"; import {getFileColor, getText} from "@/lib/utils"; import info from "@/assets/info.json"; @@ -35,29 +35,62 @@ export const GeneratedTests: React.FC = ({totalTests, testFiles
-
+
- # Generated Test Files: +
+
+
+ +
+
+
Generated Test Files
+
{testFiles.length}
+
+
+
- {testFiles.length} -
-
+ - # Generated Tests Cases: +
+
+
+ +
+
+
Generated Test Cases
+
{totalTests}
+
+
+
- {totalTests} -
-
+ - # Output HTTP Calls: +
+
+
+ +
+
+
Output HTTP Calls
+
{outputHttpCalls}
+
+
+
- {outputHttpCalls} -
-
+ - # Evaluated HTTP Calls: +
+
+
+ +
+
+
Evaluated HTTP Calls
+
{evaluatedHttpCalls}
+
+
+
- {evaluatedHttpCalls}
{timeBreakdown && (
@@ -88,27 +121,37 @@ export const GeneratedTests: React.FC = ({totalTests, testFiles
)} -
-
Test Files
-
- { - testFiles.length > 0 ? ( - testFiles.map((file, index) => ( -
-
- +
+
+ + Test Files +
+
+ { + testFiles.length > 0 ? ( + testFiles.map((file, index) => ( + - {file.fileName} (# {file.numberOfTestCases}) +
+
+
+ {file.fileName} +
+
+ {file.numberOfTestCases} +
+
-
- )) - ) : ( -
No test files generated.
- ) - } + )) + ) : ( +
No test files generated.
+ ) + } +
From 9ac863f6faa0781700d57b4503a6f7e42eefc752 Mon Sep 17 00:00:00 2001 From: Omur Date: Thu, 30 Oct 2025 12:04:42 +0300 Subject: [PATCH 4/5] minor fix --- web-report/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web-report/package.json b/web-report/package.json index 8f68eb0..2467ea8 100644 --- a/web-report/package.json +++ b/web-report/package.json @@ -11,7 +11,7 @@ "copyRunFiles": "cpx webreport.bat '../target/classes/webreport' && cpx webreport.command '../target/classes/webreport' && cpx webreport.py '../target/classes/webreport' && cpx 'src-e2e/static/robots.txt' '../target/classes/webreport'", "lint": "eslint .", "preview": "vite preview", - "debug": "vite build && cpx src-e2e/static/* ../target/classes/webreport && vite preview", + "debug": "vite build && cpx 'src-e2e/static/*' '../target/classes/webreport' && vite preview", "test": "vitest" }, "dependencies": { From bfbb40ca7b64b1aff682b79ba4f03fa3836a3723 Mon Sep 17 00:00:00 2001 From: arcuri82 Date: Thu, 30 Oct 2025 10:17:33 +0100 Subject: [PATCH 5/5] relese notes --- release_notes.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/release_notes.md b/release_notes.md index 6fa9b60..7cad534 100644 --- a/release_notes.md +++ b/release_notes.md @@ -2,6 +2,8 @@ Under development in `master` branch. +- in report, added info on _executionTimeInSeconds_ and _evaluatedHttpCalls_ + # 0.1.0 - first public release