-
Notifications
You must be signed in to change notification settings - Fork 1.5k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #5809 from NomicFoundation/feat/solidity-test-repo…
…rter feat: replace spec with a custom hardhat solidity test reporter
- Loading branch information
Showing
8 changed files
with
222 additions
and
83 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
5 changes: 5 additions & 0 deletions
5
v-next/hardhat/src/internal/builtin-plugins/solidity-test/formatters.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
import type { ArtifactId } from "@ignored/edr"; | ||
|
||
export function formatArtifactId(artifactId: ArtifactId): string { | ||
return `${artifactId.source}:${artifactId.name} (v${artifactId.solcVersion})`; | ||
} |
49 changes: 1 addition & 48 deletions
49
v-next/hardhat/src/internal/builtin-plugins/solidity-test/helpers.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
8 changes: 8 additions & 0 deletions
8
v-next/hardhat/src/internal/builtin-plugins/solidity-test/index.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
60 changes: 60 additions & 0 deletions
60
v-next/hardhat/src/internal/builtin-plugins/solidity-test/reporter.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
import type { | ||
TestEventSource, | ||
TestReporterResult, | ||
TestStatus, | ||
} from "./types.js"; | ||
|
||
import chalk from "chalk"; | ||
|
||
/** | ||
* This is a solidity test reporter. It is intended to be composed with the | ||
* solidity test runner's test stream. It was based on the hardhat node test | ||
* reporter's design. | ||
*/ | ||
export async function* testReporter( | ||
source: TestEventSource, | ||
): TestReporterResult { | ||
let testResultCount = 0; | ||
let successCount = 0; | ||
let failureCount = 0; | ||
let skippedCount = 0; | ||
|
||
for await (const event of source) { | ||
switch (event.type) { | ||
case "suite:result": { | ||
const { data: suiteResult } = event; | ||
for (const testResult of suiteResult.testResults) { | ||
testResultCount++; | ||
let name = suiteResult.id.name + " | " + testResult.name; | ||
if ("runs" in testResult?.kind) { | ||
name += ` (${testResult.kind.runs} runs)`; | ||
} | ||
const status: TestStatus = testResult.status; | ||
switch (status) { | ||
case "Success": { | ||
yield chalk.green(`✔ ${name}`); | ||
successCount++; | ||
break; | ||
} | ||
case "Failure": { | ||
yield chalk.red(`✖ ${name}`); | ||
failureCount++; | ||
break; | ||
} | ||
case "Skipped": { | ||
yield chalk.yellow(`⚠️ ${name}`); | ||
skippedCount++; | ||
break; | ||
} | ||
} | ||
yield "\n"; | ||
} | ||
break; | ||
} | ||
} | ||
} | ||
|
||
yield "\n"; | ||
yield `${testResultCount} tests found, ${successCount} passed, ${failureCount} failed, ${skippedCount} skipped`; | ||
yield "\n"; | ||
} |
92 changes: 92 additions & 0 deletions
92
v-next/hardhat/src/internal/builtin-plugins/solidity-test/runner.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,92 @@ | ||
import type { TestEvent, TestsStream } from "./types.js"; | ||
import type { | ||
ArtifactId, | ||
Artifact, | ||
SolidityTestRunnerConfigArgs, | ||
} from "@ignored/edr"; | ||
|
||
import { Readable } from "node:stream"; | ||
|
||
import { runSolidityTests } from "@ignored/edr"; | ||
import { HardhatError } from "@ignored/hardhat-vnext-errors"; | ||
|
||
import { formatArtifactId } from "./formatters.js"; | ||
|
||
export interface RunOptions { | ||
/** | ||
* The maximum time in milliseconds to wait for all the test suites to finish. | ||
* | ||
* If not provided, the default is 1 hour. | ||
*/ | ||
timeout?: number; | ||
} | ||
|
||
/** | ||
* Run all the given solidity tests and returns the stream of results. | ||
* | ||
* It returns a Readable stream that emits the test events similarly to how the | ||
* node test runner does it. | ||
* | ||
* The stream is closed when all the test suites have been run. | ||
* | ||
* This function, initially, was a direct port of the example v2 integration in | ||
* the EDR repo (see https://github.com/NomicFoundation/edr/blob/feat/solidity-tests/js/helpers/src/index.ts). | ||
* | ||
* Despite the changes, the signature of the function should still be considered | ||
* a draft that may change in the future. | ||
* | ||
* TODO: Once the signature is finalised, give feedback to the EDR team. | ||
*/ | ||
export function run( | ||
artifacts: Artifact[], | ||
testSuiteIds: ArtifactId[], | ||
configArgs: SolidityTestRunnerConfigArgs, | ||
options?: RunOptions, | ||
): TestsStream { | ||
const stream = new ReadableStream<TestEvent>({ | ||
start(controller) { | ||
if (testSuiteIds.length === 0) { | ||
controller.close(); | ||
return; | ||
} | ||
|
||
const remainingSuites = new Set(testSuiteIds.map(formatArtifactId)); | ||
|
||
// NOTE: The timeout prevents the situation in which the stream is never | ||
// closed. This can happen if we receive fewer suite results than the | ||
// number of test suites. The timeout is set to 1 hour. | ||
const duration = options?.timeout ?? 60 * 60 * 1000; | ||
const timeout = setTimeout(() => { | ||
controller.error( | ||
new HardhatError(HardhatError.ERRORS.SOLIDITY_TESTS.RUNNER_TIMEOUT, { | ||
duration, | ||
suites: Array.from(remainingSuites).join(", "), | ||
}), | ||
); | ||
}, duration); | ||
|
||
runSolidityTests( | ||
artifacts, | ||
testSuiteIds, | ||
configArgs, | ||
(suiteResult) => { | ||
controller.enqueue({ | ||
type: "suite:result", | ||
data: suiteResult, | ||
}); | ||
remainingSuites.delete(formatArtifactId(suiteResult.id)); | ||
if (remainingSuites.size === 0) { | ||
clearTimeout(timeout); | ||
controller.close(); | ||
} | ||
}, | ||
(error) => { | ||
clearTimeout(timeout); | ||
controller.error(error); | ||
}, | ||
); | ||
}, | ||
}); | ||
|
||
return Readable.from(stream); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
17 changes: 17 additions & 0 deletions
17
v-next/hardhat/src/internal/builtin-plugins/solidity-test/types.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
import type { SuiteResult } from "@ignored/edr"; | ||
import type { Readable } from "node:stream"; | ||
|
||
export type TestStatus = "Success" | "Failure" | "Skipped"; | ||
|
||
export type TestsStream = Readable; | ||
|
||
// NOTE: The interface can be turned into a type and extended with more event types as needed. | ||
export interface TestEvent { | ||
type: "suite:result"; | ||
data: SuiteResult; | ||
} | ||
|
||
export type TestEventSource = AsyncGenerator<TestEvent, void>; | ||
export type TestReporterResult = AsyncGenerator<string, void>; | ||
|
||
export type TestReporter = (source: TestEventSource) => TestReporterResult; |