Skip to content

Commit d480e2b

Browse files
authored
Merge pull request #18 from WebFuzzing/time-and-calls
added evaluatedHttpCalls and executionTimeInSeconds. renamed totalHtt…
2 parents 28e37f6 + bfbb40c commit d480e2b

File tree

10 files changed

+193
-53
lines changed

10 files changed

+193
-53
lines changed

release_notes.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
Under development in `master` branch.
44

5+
- in report, added info on _executionTimeInSeconds_ and _evaluatedHttpCalls_
6+
57
# 0.1.0
68

79
- first public release

src/main/resources/wfc/schemas/report.yaml

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -48,14 +48,28 @@ properties:
4848
type: array
4949
items:
5050
$ref: "#/$defs/TestCase"
51+
executionTimeInSeconds:
52+
type: integer
53+
minimum: 0
54+
description: "For how long, in seconds, the tool was running in total."
5155
#OPTIONAL
5256
extra:
5357
description: "Extra, optional coverage information, collected by different tools."
5458
type: [array, "null"]
5559
items:
5660
$ref: "#/$defs/Coverage"
5761

58-
required: ["schemaVersion","toolName","toolVersion","creationTime","faults","problemDetails","totalTests","testFilePaths","testCases"]
62+
required:
63+
- "schemaVersion"
64+
- "toolName"
65+
- "toolVersion"
66+
- "creationTime"
67+
- "faults"
68+
- "problemDetails"
69+
- "totalTests"
70+
- "testFilePaths"
71+
- "testCases"
72+
- "executionTimeInSeconds"
5973

6074
$defs:
6175
OperationId:
@@ -122,11 +136,18 @@ $defs:
122136
RESTReport:
123137
type: object
124138
properties:
125-
totalHttpCalls:
126-
description: "Total number of HTTP calls made in all the test cases. A test case could contain several HTTP calls, \
139+
outputHttpCalls:
140+
description: "Total number of HTTP calls made in all the generated test cases given as output. \
141+
A test case could contain several HTTP calls, \
127142
e.g., a POST followed by a GET and then a DELETE."
128143
type: integer
129144
minimum: 0
145+
evaluatedHttpCalls:
146+
description: "Total number of all HTTP calls made during the whole fuzzing session. \
147+
If the fuzzing was left running for hours, millions of HTTP could have been made.
148+
The output generated tests will only contain a tiny subset of these evaluated calls."
149+
type: integer
150+
minimum: 0
130151
endpointIds:
131152
description: "Unique ids of all the endpoints in the tested API."
132153
type: array
@@ -138,7 +159,7 @@ $defs:
138159
type: array
139160
items:
140161
$ref: "#/$defs/CoveredEndpoint"
141-
required: ["totalHttpCalls","endpointIds","coveredHttpStatus"]
162+
required: ["outputHttpCalls","evaluatedHttpCalls","endpointIds","coveredHttpStatus"]
142163

143164
TestCase:
144165
type: object

web-report/src-e2e/App.test.tsx

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -41,10 +41,10 @@ describe('App test', () => {
4141

4242
it('handles successful data loading', async () => {
4343
render(<App />);
44-
44+
4545
// Initially shows loading state
4646
expect(screen.getByText(/Please wait, files are loading.../)).toBeInTheDocument();
47-
47+
4848
// Wait for loading to complete and verify header data
4949
await waitFor(() => {
5050
expect(screen.queryByText(/Please wait, files are loading.../)).toBeNull();
@@ -79,11 +79,13 @@ describe('App test', () => {
7979
render(<App />);
8080
expect(screen.getByText(/Please wait, files are loading.../)).toBeInTheDocument();
8181
const total = reportData.problemDetails.rest.endpointIds.length;
82-
const totalHttpCalls = reportData.problemDetails.rest.totalHttpCalls;
82+
const outputHttpCalls = reportData.problemDetails.rest.outputHttpCalls;
83+
const evaluatedHttpCalls = reportData.problemDetails.rest.evaluatedHttpCalls;
8384

8485
await waitFor(() => {
8586
expect(screen.getByTestId('rest-report-endpoint')).toContainHTML(`${total}`);
86-
expect(screen.getByTestId('rest-report-http-calls')).toContainHTML(`${totalHttpCalls}`);
87+
expect(screen.getByTestId('rest-report-output-http-calls')).toContainHTML(`${outputHttpCalls}`);
88+
expect(screen.getByTestId('rest-report-evaluated-http-calls')).toContainHTML(`${evaluatedHttpCalls}`);
8789
});
8890

8991
});
@@ -143,4 +145,4 @@ describe('App test', () => {
143145
expect(screen.getByTestId('faults-component-fault-counts')).toContainHTML(faultCounts.length.toString());
144146
});
145147
});
146-
});
148+
});

web-report/src-e2e/static/report.json

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
"toolName": "EvoMaster",
44
"toolVersion": "unknown",
55
"creationTime": "2025-04-09T19:31:54.258Z",
6+
"executionTimeInSeconds": 6780000,
67
"faults": {
78
"totalNumber": 529,
89
"foundFaults": [
@@ -2970,7 +2971,7 @@
29702971
},
29712972
"problemDetails": {
29722973
"rest": {
2973-
"totalHttpCalls": 130,
2974+
"outputHttpCalls": 25,
29742975
"endpointIds": [
29752976
"GET:/app/api/assignments",
29762977
"POST:/app/api/assignments",
@@ -3951,7 +3952,8 @@
39513952
200
39523953
]
39533954
}
3954-
]
3955+
],
3956+
"evaluatedHttpCalls": 132
39553957
}
39563958
},
39573959
"totalTests": 127,
@@ -4867,4 +4869,4 @@
48674869
]
48684870
}
48694871
]
4870-
}
4872+
}

web-report/src/assets/info.json

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
{
22
"numberOfEndpoints": "Number of endpoints (verb:path) in the API.",
3-
"numberOfHttpCalls": "Total number of HTTP calls in the generated test suites.",
3+
"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).",
4+
"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.",
5+
"executionTimeInSeconds": "For how long, in seconds, the tool was running in total.",
46
"codeNumberIdentifiers": "Code number identifiers for detected fault types",
57
"identifierName": "Identifier name for the fault type.",
68
"testFilesLocated": "{numberOfTestCases} test cases are located in {fileName}",
@@ -15,4 +17,4 @@
1517
"creationDate": "Date when the report was generated.",
1618
"toolNameVersion": "Name and version of the tool that generated the report.",
1719
"schemaVersion": "Version of the schema used for the report."
18-
}
20+
}

web-report/src/components/Dashboard.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,9 @@ export const Dashboard: React.FC = () => {
114114
<Overview rest={data.problemDetails.rest}
115115
testCases={data.testCases}
116116
testFiles={numberOfTestCaseOfFiles}
117-
faults={data.faults}/>
117+
faults={data.faults}
118+
executionTimeInSeconds={data.executionTimeInSeconds}
119+
/>
118120
</TabsContent>
119121

120122
<TabsContent value="endpoints">
Lines changed: 126 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import {Card} from "@/components/ui/card.tsx";
2-
import {Target} from "lucide-react";
2+
import {Target, Clock, FileText, TestTube, Network, CheckCircle, FolderOpen} from "lucide-react";
33
import type React from "react";
44
import {getFileColor, getText} from "@/lib/utils";
55
import info from "@/assets/info.json";
@@ -11,57 +11,151 @@ interface IGeneratedTests {
1111
fileName: string,
1212
numberOfTestCases: number
1313
}>
14-
totalHttpCalls?: number
14+
outputHttpCalls?: number
15+
evaluatedHttpCalls?: number
16+
executionTimeInSeconds?: number
1517
}
1618

17-
export const GeneratedTests: React.FC<IGeneratedTests> = ({totalTests, testFiles, totalHttpCalls}) => (
19+
const formatExecutionTime = (totalSeconds?: number) => {
20+
if (totalSeconds === undefined || totalSeconds === null) return null;
21+
22+
const days = Math.floor(totalSeconds / 86400);
23+
const hours = Math.floor((totalSeconds % 86400) / 3600);
24+
const minutes = Math.floor((totalSeconds % 3600) / 60);
25+
const seconds = Math.floor(totalSeconds % 60);
26+
27+
return { days, hours, minutes, seconds };
28+
};
29+
30+
export const GeneratedTests: React.FC<IGeneratedTests> = ({totalTests, testFiles, outputHttpCalls, evaluatedHttpCalls, executionTimeInSeconds}) => {
31+
const timeBreakdown = formatExecutionTime(executionTimeInSeconds);
32+
33+
return (
1834
<Card className="border-2 border-black p-6 rounded-none">
1935
<div className="flex items-start gap-4">
2036
<Target className="w-6 h-6 text-gray-500"/>
2137
<div className="flex-1">
22-
<div className="flex justify-between">
38+
<div className="grid grid-cols-1 sm:grid-cols-2 gap-4">
2339
<ReportTooltip tooltipText={info.generatedTestFiles}>
24-
<span className="text-lg font-bold"># Generated Test Files:</span>
40+
<div className="bg-gradient-to-br from-green-50 to-emerald-50 border-2 border-green-300 rounded-lg p-4 hover:shadow-md transition-shadow">
41+
<div className="flex items-center gap-3">
42+
<div className="bg-green-500 rounded-full p-2">
43+
<FileText className="w-5 h-5 text-white"/>
44+
</div>
45+
<div className="flex-1">
46+
<div className="text-sm font-medium text-gray-600">Generated Test Files</div>
47+
<div className="text-2xl font-bold text-green-700" data-testid="generated-tests-total-test-files">{testFiles.length}</div>
48+
</div>
49+
</div>
50+
</div>
2551
</ReportTooltip>
26-
<span className="text-lg font-bold" data-testid="generated-tests-total-test-files">{testFiles.length}</span>
27-
</div>
28-
<div className="flex justify-between">
52+
2953
<ReportTooltip tooltipText={info.generatedTestCases}>
30-
<span className="text-lg font-bold"># Generated Tests Cases:</span>
54+
<div className="bg-gradient-to-br from-orange-50 to-amber-50 border-2 border-orange-300 rounded-lg p-4 hover:shadow-md transition-shadow">
55+
<div className="flex items-center gap-3">
56+
<div className="bg-orange-500 rounded-full p-2">
57+
<TestTube className="w-5 h-5 text-white"/>
58+
</div>
59+
<div className="flex-1">
60+
<div className="text-sm font-medium text-gray-600">Generated Test Cases</div>
61+
<div className="text-2xl font-bold text-orange-700" data-testid="generated-tests-total-tests">{totalTests}</div>
62+
</div>
63+
</div>
64+
</div>
3165
</ReportTooltip>
32-
<span className="text-lg font-bold" data-testid="generated-tests-total-tests">{totalTests}</span>
33-
</div>
34-
<div className="flex justify-between">
35-
<ReportTooltip tooltipText={info.numberOfHttpCalls}>
36-
<span className="text-lg font-bold"># HTTP Calls:</span>
66+
67+
<ReportTooltip tooltipText={info.outputHttpCalls}>
68+
<div className="bg-gradient-to-br from-cyan-50 to-sky-50 border-2 border-cyan-300 rounded-lg p-4 hover:shadow-md transition-shadow">
69+
<div className="flex items-center gap-3">
70+
<div className="bg-cyan-500 rounded-full p-2">
71+
<Network className="w-5 h-5 text-white"/>
72+
</div>
73+
<div className="flex-1">
74+
<div className="text-sm font-medium text-gray-600">Output HTTP Calls</div>
75+
<div className="text-2xl font-bold text-cyan-700" data-testid="rest-report-output-http-calls">{outputHttpCalls}</div>
76+
</div>
77+
</div>
78+
</div>
79+
</ReportTooltip>
80+
81+
<ReportTooltip tooltipText={info.evaluatedHttpCalls}>
82+
<div className="bg-gradient-to-br from-pink-50 to-rose-50 border-2 border-pink-300 rounded-lg p-4 hover:shadow-md transition-shadow">
83+
<div className="flex items-center gap-3">
84+
<div className="bg-pink-500 rounded-full p-2">
85+
<CheckCircle className="w-5 h-5 text-white"/>
86+
</div>
87+
<div className="flex-1">
88+
<div className="text-sm font-medium text-gray-600">Evaluated HTTP Calls</div>
89+
<div className="text-2xl font-bold text-pink-700" data-testid="rest-report-evaluated-http-calls">{evaluatedHttpCalls}</div>
90+
</div>
91+
</div>
92+
</div>
3793
</ReportTooltip>
38-
<span className="text-lg font-bold" data-testid="rest-report-http-calls">{totalHttpCalls}</span>
3994
</div>
95+
{timeBreakdown && (
96+
<div className="mt-4 p-4 bg-gradient-to-r from-blue-50 to-indigo-50 border-2 border-blue-300 rounded-lg">
97+
<ReportTooltip tooltipText={info.executionTimeInSeconds}>
98+
<div className="flex items-center gap-2 mb-3">
99+
<Clock className="w-5 h-5 text-blue-600"/>
100+
<span className="text-base font-bold text-blue-900">Execution Time</span>
101+
</div>
102+
</ReportTooltip>
103+
<div className="grid grid-cols-2 sm:grid-cols-4 gap-3" data-testid="rest-report-execution-time">
104+
<div className="text-center bg-white rounded-lg p-3 border border-blue-200 shadow-sm">
105+
<div className="text-2xl font-bold text-blue-600">{timeBreakdown.days}</div>
106+
<div className="text-xs font-medium text-gray-600 mt-1">Days</div>
107+
</div>
108+
<div className="text-center bg-white rounded-lg p-3 border border-blue-200 shadow-sm">
109+
<div className="text-2xl font-bold text-indigo-600">{timeBreakdown.hours}</div>
110+
<div className="text-xs font-medium text-gray-600 mt-1">Hours</div>
111+
</div>
112+
<div className="text-center bg-white rounded-lg p-3 border border-blue-200 shadow-sm">
113+
<div className="text-2xl font-bold text-purple-600">{timeBreakdown.minutes}</div>
114+
<div className="text-xs font-medium text-gray-600 mt-1">Minutes</div>
115+
</div>
116+
<div className="text-center bg-white rounded-lg p-3 border border-blue-200 shadow-sm">
117+
<div className="text-2xl font-bold text-violet-600">{timeBreakdown.seconds}</div>
118+
<div className="text-xs font-medium text-gray-600 mt-1">Seconds</div>
119+
</div>
120+
</div>
121+
</div>
122+
)}
40123

41-
<div className="mt-4 pt-4 border-t border-gray-200">
42-
<div className="text-sm font-medium text-gray-700 mb-2">Test Files</div>
43-
<div className="space-y-1">
44-
{
45-
testFiles.length > 0 ? (
46-
testFiles.map((file, index) => (
47-
<div className="flex items-center gap-2 text-sm text-gray-600" key={index}>
48-
<div className={`w-2 h-2 ${getFileColor(index, file.fileName)} rounded-full`}></div>
49-
<ReportTooltip tooltipText={getText(info.testFilesLocated,
124+
<div className="mt-4">
125+
<div className="bg-gradient-to-r from-slate-50 to-gray-50 border-2 border-slate-300 rounded-lg p-4">
126+
<div className="flex items-center gap-2 mb-3">
127+
<FolderOpen className="w-5 h-5 text-slate-600"/>
128+
<span className="text-base font-bold text-slate-900">Test Files</span>
129+
</div>
130+
<div className="space-y-2">
131+
{
132+
testFiles.length > 0 ? (
133+
testFiles.map((file, index) => (
134+
<ReportTooltip key={index} tooltipText={getText(info.testFilesLocated,
50135
{
51136
fileName: file.fileName,
52137
numberOfTestCases: file.numberOfTestCases
53138
})}>
54-
<span>{file.fileName} (# {file.numberOfTestCases})</span>
139+
<div className="flex items-center gap-3 bg-white rounded-md p-3 border border-slate-200 hover:border-slate-400 hover:shadow-sm transition-all">
140+
<div className={`w-3 h-3 ${getFileColor(index, file.fileName)} rounded-full flex-shrink-0`}></div>
141+
<div className="flex-1 min-w-0">
142+
<span className="text-sm font-medium text-gray-700 truncate block">{file.fileName}</span>
143+
</div>
144+
<div className="flex-shrink-0 bg-slate-100 px-2 py-1 rounded-md">
145+
<span className="text-xs font-bold text-slate-700">{file.numberOfTestCases}</span>
146+
</div>
147+
</div>
55148
</ReportTooltip>
56-
</div>
57-
))
58-
) : (
59-
<div className="text-gray-500 italic">No test files generated.</div>
60-
)
61-
}
149+
))
150+
) : (
151+
<div className="text-center text-gray-500 italic py-4">No test files generated.</div>
152+
)
153+
}
154+
</div>
62155
</div>
63156
</div>
64157
</div>
65158
</div>
66159
</Card>
67-
)
160+
);
161+
};

web-report/src/pages/Overview.tsx

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,20 +12,25 @@ interface IOverviewType {
1212
numberOfTestCases: number
1313
}>,
1414
faults: Faults
15+
executionTimeInSeconds: number;
1516
}
1617

17-
export const Overview: React.FC<IOverviewType> = ({rest, testCases, testFiles, faults}) => {
18+
export const Overview: React.FC<IOverviewType> = ({rest, testCases, testFiles, faults, executionTimeInSeconds}) => {
1819
return (
1920
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
2021
{/* Left Panel */}
2122
{rest ? <RestReports {...rest}/> : <div>Please provide rest report.</div>}
2223
{/* Right Panel */}
2324
<div className="flex flex-col gap-6">
2425
{/* Generated Tests */}
25-
<GeneratedTests totalTests={testCases.length} testFiles={testFiles} totalHttpCalls={rest?.totalHttpCalls}/>
26+
<GeneratedTests totalTests={testCases.length} testFiles={testFiles}
27+
outputHttpCalls={rest?.outputHttpCalls}
28+
evaluatedHttpCalls={rest?.evaluatedHttpCalls}
29+
executionTimeInSeconds={executionTimeInSeconds}
30+
/>
2631
{/* Faults */}
2732
<FaultsComponent {...faults}/>
2833
</div>
2934
</div>
3035
)
31-
}
36+
}

0 commit comments

Comments
 (0)