Skip to content

Commit

Permalink
Organize the exports
Browse files Browse the repository at this point in the history
  • Loading branch information
nazarhussain committed Dec 11, 2024
1 parent 6654249 commit 58b7513
Show file tree
Hide file tree
Showing 6 changed files with 72 additions and 88 deletions.
52 changes: 5 additions & 47 deletions src/benchmark/benchmarkFn.ts
Original file line number Diff line number Diff line change
@@ -1,39 +1,13 @@
import fs from "node:fs";
import path from "node:path";
import {getCurrentSuite, Suite, SuiteCollector} from "@vitest/runner";
import {getCurrentSuite} from "@vitest/runner";
import {createChainable} from "@vitest/runner/utils";
import {store} from "./globalState.js";
import {BenchmarkOpts} from "../types.js";
import {BenchApi, BenchmarkOpts, BenchmarkRunOptsWithFn, PartialBy} from "../types.js";
import {runBenchFn} from "./runBenchmarkFn.js";
import {optionsDefault} from "../cli/options.js";

export type BenchmarkRunOptsWithFn<T, T2> = BenchmarkOpts & {
id: string;
fn: (arg: T) => void | Promise<void>;
before?: () => T2 | Promise<T2>;
beforeEach?: (arg: T2, i: number) => T | Promise<T>;
};

// Create partial only for specific keys
type PartialBy<T, K extends keyof T> = Omit<T, K> & Partial<Pick<T, K>>;

export function getRootSuite(suite: Suite | SuiteCollector): Suite {
if (suite.type === "collector") {
return getRootSuite(suite.tasks[0] as Suite);
}

if (suite.name === "") {
return suite;
} else if (suite.suite) {
getRootSuite(suite.suite);
} else {
return suite;
}

throw new Error("Can not find root suite");
}

export const bench = createBenchmarkFunction(function <T, T2>(
export const bench: BenchApi = createBenchmarkFunction(function <T, T2>(
this: Record<"skip" | "only", boolean | undefined>,
idOrOpts: string | PartialBy<BenchmarkRunOptsWithFn<T, T2>, "fn">,
fn?: (arg: T) => void | Promise<void>
Expand Down Expand Up @@ -99,26 +73,10 @@ function createBenchmarkFunction(
idOrOpts: string | PartialBy<BenchmarkRunOptsWithFn<T, T2>, "fn">,
fn?: (arg: T) => void | Promise<void>
) => void
): BenchFuncApi {
return createChainable(["skip", "only"], fn) as BenchFuncApi;
}

interface BenchFuncApi {
<T, T2>(opts: BenchmarkRunOptsWithFn<T, T2>): void;
<T, T2>(idOrOpts: string | Omit<BenchmarkRunOptsWithFn<T, T2>, "fn">, fn: (arg: T) => void): void;
<T, T2>(
idOrOpts: string | PartialBy<BenchmarkRunOptsWithFn<T, T2>, "fn">,
fn?: (arg: T) => void | Promise<void>
): void;
}

interface BenchApi extends BenchFuncApi {
only: BenchFuncApi;
skip: BenchFuncApi;
): BenchApi {
return createChainable(["skip", "only"], fn) as BenchApi;
}

export const itBench = bench as BenchApi;

function coerceToOptsObj<T, T2>(
idOrOpts: string | PartialBy<BenchmarkRunOptsWithFn<T, T2>, "fn">,
fn?: (arg: T) => void | Promise<void>
Expand Down
6 changes: 3 additions & 3 deletions src/compare/compute.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
import {ResultComparision, BenchmarkComparision, Benchmark, BenchmarkResult} from "../types.js";
import {ResultComparison, BenchmarkComparison, Benchmark, BenchmarkResult} from "../types.js";

export function computeBenchComparision(
currBench: Benchmark,
prevBench: Benchmark | null,
threshold: number
): BenchmarkComparision {
): BenchmarkComparison {
const prevResults = new Map<string, BenchmarkResult>();
if (prevBench) {
for (const bench of prevBench.results) {
prevResults.set(bench.id, bench);
}
}

const results = currBench.results.map((currBench): ResultComparision => {
const results = currBench.results.map((currBench): ResultComparison => {
const {id} = currBench;
const prevBench = prevResults.get(id);
const thresholdBench = currBench.threshold ?? threshold;
Expand Down
4 changes: 2 additions & 2 deletions src/github/comment.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import * as github from "@actions/github";
import {BenchmarkComparision} from "../types.js";
import {BenchmarkComparison} from "../types.js";
import {commetToPrUpdatable, commentToCommit} from "./octokit.js";
import {getGithubEventData, GithubActionsEventData, renderComment} from "../utils/index.js";

export async function postGaComment(resultsComp: BenchmarkComparision): Promise<void> {
export async function postGaComment(resultsComp: BenchmarkComparison): Promise<void> {
switch (github.context.eventName) {
case "pull_request": {
const eventData = getGithubEventData<GithubActionsEventData["pull_request"]>();
Expand Down
37 changes: 34 additions & 3 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,36 @@
import {suite, test} from "@vitest/runner";
export {suite as describe, beforeEach, beforeAll} from "@vitest/runner";
export {bench, setBenchOpts, setBenchmarkOptions} from "./benchmark/index.js";

export {bench, itBench, setBenchOpts, setBenchmarkOptions} from "./benchmark/index.js";
export const describe = suite;
import {bench} from "./benchmark/index.js";
import {test} from "@vitest/runner";

/**
* @deprecated We recommend to use `bench` instead.
*/
export const itBench = bench;

/**
* Defines a test case with a given name and test function. The test function can optionally be configured with test options.
*
* * **Note:** We expose this utility for user flexibility but recommends users to not mix normal tests with benchmarks
*
* @param {string | Function} name - The name of the test or a function that will be used as a test name.
* @param {TestOptions | TestFunction} [optionsOrFn] - Optional. The test options or the test function if no explicit name is provided.
* @param {number | TestOptions | TestFunction} [optionsOrTest] - Optional. The test function or options, depending on the previous parameters.
* @throws {Error} If called inside another test function.
* @example
* ```ts
* // Define a simple test
* it('should add two numbers', () => {
* expect(add(1, 2)).toBe(3);
* });
* ```
* @example
* ```ts
* // Define a test with options
* it('should subtract two numbers', { retry: 3 }, () => {
* expect(subtract(5, 2)).toBe(3);
* });
* ```
*/
export const it = test;
53 changes: 24 additions & 29 deletions src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,33 +61,28 @@ export type BenchmarkOpts = {
skip?: boolean;
};

/** Manual lodash.pick() function. Ensure no unwanted options end up in optsByRootSuite */
export function onlyBenchmarkOpts(opts: BenchmarkOpts): BenchmarkOpts {
// Define in this way so Typescript guarantees all keys are considered
const keysObj: Record<keyof BenchmarkOpts, true> = {
maxRuns: true,
minRuns: true,
maxMs: true,
minMs: true,
maxWarmUpMs: true,
maxWarmUpRuns: true,
convergeFactor: true,
runsFactor: true,
yieldEventLoopAfterEach: true,
timeoutBench: true,
threshold: true,
noThreshold: true,
only: true,
skip: true,
};
// Create partial only for specific keys
export type PartialBy<T, K extends keyof T> = Omit<T, K> & Partial<Pick<T, K>>;

export type BenchmarkRunOptsWithFn<T, T2> = BenchmarkOpts & {
id: string;
fn: (arg: T) => void | Promise<void>;
before?: () => T2 | Promise<T2>;
beforeEach?: (arg: T2, i: number) => T | Promise<T>;
};

export interface BenchFuncApi {
<T, T2>(opts: BenchmarkRunOptsWithFn<T, T2>): void;
<T, T2>(idOrOpts: string | Omit<BenchmarkRunOptsWithFn<T, T2>, "fn">, fn: (arg: T) => void): void;
<T, T2>(
idOrOpts: string | PartialBy<BenchmarkRunOptsWithFn<T, T2>, "fn">,
fn?: (arg: T) => void | Promise<void>
): void;
}

const optsOut = {} as Record<keyof BenchmarkOpts, BenchmarkOpts[keyof BenchmarkOpts]>;
for (const key of Object.keys(keysObj) as (keyof BenchmarkOpts)[]) {
if (opts[key] !== undefined) {
optsOut[key] = opts[key];
}
}
return optsOut as BenchmarkOpts;
export interface BenchApi extends BenchFuncApi {
only: BenchFuncApi;
skip: BenchFuncApi;
}

export type BenchmarkResults = BenchmarkResult[];
Expand Down Expand Up @@ -115,14 +110,14 @@ export type BenchmarkHistory = {
};
};

export type BenchmarkComparision = {
export type BenchmarkComparison = {
currCommitSha: string;
prevCommitSha: string | null;
someFailed: boolean;
results: ResultComparision[];
results: ResultComparison[];
};

export type ResultComparision = {
export type ResultComparison = {
id: string;
currAverageNs: number;
prevAverageNs: number | null;
Expand Down
8 changes: 4 additions & 4 deletions src/utils/render.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import {BenchmarkComparision, ResultComparision} from "../types.js";
import {BenchmarkComparison, ResultComparison} from "../types.js";

type CommitsSha = Pick<BenchmarkComparision, "currCommitSha" | "prevCommitSha">;
type CommitsSha = Pick<BenchmarkComparison, "currCommitSha" | "prevCommitSha">;

export function renderComment(benchComp: BenchmarkComparision): string {
export function renderComment(benchComp: BenchmarkComparison): string {
const isFailedResults = benchComp.results.filter((r) => r.isFailed);
const isImprovedResults = benchComp.results.filter((r) => r.isImproved);

Expand Down Expand Up @@ -42,7 +42,7 @@ ${renderBenchmarkTable(benchComp.results, benchComp)}
`;
}

function renderBenchmarkTable(benchComp: ResultComparision[], {currCommitSha, prevCommitSha}: CommitsSha): string {
function renderBenchmarkTable(benchComp: ResultComparison[], {currCommitSha, prevCommitSha}: CommitsSha): string {
function toRow(arr: (number | string)[]): string {
// Don't surround string items with \`, it doesn't look great rendered in Github comments
const row = arr.map((e) => `${e}`).join(" | ");
Expand Down

0 comments on commit 58b7513

Please sign in to comment.