Skip to content

Commit

Permalink
Added tape to list of benchmarks
Browse files Browse the repository at this point in the history
  • Loading branch information
EvHaus committed Mar 3, 2024
1 parent a88d5a0 commit 93ec87f
Show file tree
Hide file tree
Showing 68 changed files with 2,326 additions and 239 deletions.
8 changes: 4 additions & 4 deletions .github/workflows/benchmark.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -28,13 +28,13 @@ jobs:
- name: Install bun
uses: oven-sh/setup-bun@v1
with:
bun-version: canary
# Cannot upgrade due to https://github.com/oven-sh/bun/issues/8314
bun-version: 1.0.23

- name: Run
run: |
hyperfine --warmup 1 \
'yarn workspace jasmine test' \
'yarn workspace jest test' \
'yarn workspace vitest test' \
'yarn workspace vitest test --pool=vmThreads' \
'yarn workspace vitest test --poolOptions.threads.isolate=false'
'yarn workspace vitest test --poolOptions.threads.isolate=false' \
'yarn workspace tape test'
26 changes: 18 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,15 @@ This repo is setup to test the performance of various test runners. Specially to
- Help the **Jest** team with https://github.com/facebook/jest/issues/6694.
- Help the **Vitest** team with https://github.com/vitest-dev/vitest/issues/229 & https://github.com/vitest-dev/vitest/issues/579

![](results.png?raw=true)
## Results

### Single-thread (on GitHub Actions CI)

![](result-single-thread.png?raw=true)

### Multi-thread (12 core PC)

![](result-multi-thread.png?raw=true)

## Setup

Expand All @@ -19,12 +27,11 @@ Then you can run benchmarks via:

```sh
hyperfine --warmup 1 \
'yarn workspace bun test' \
'yarn workspace jasmine test' \
'yarn workspace jest test' \
'yarn workspace vitest test' \
'yarn workspace vitest test --pool=vmThreads' \
'yarn workspace vitest test --poolOptions.threads.isolate=false' \
'yarn workspace bun test'
'yarn workspace tape test' \
'yarn workspace vitest test --poolOptions.threads.isolate=false'
```

> [!NOTE]
Expand All @@ -33,9 +40,12 @@ hyperfine --warmup 1 \
## Suites

- `jasmine`: This is our baseline, using Jasmine and happy-dom.
- `jest`: Same test suite, but running using Jest.
- `vitest`: Same test suite, but running using Vitest. NOTE: That benchmarks include vitest with the `--poolOptions.threads.isolate` setting both enabled and disabled due to [this issue](https://github.com/vitest-dev/vitest/issues/229#issuecomment-1003235680)
- *NOTE*: Jasmine doesn't support shapshot testing so those tests do a basic comparison
- `bun`: Same test suite, but running using Bun.
- `jest`: Same test suite, but running using Jest.
- `tape`: Same test suite, but running using Tape and ts-node.
- *NOTE*: Tape doesn't support shapshot testing so those tests do a basic comparison
- `vitest`: Same test suite, but running using Vitest. *NOTE*: That benchmarks use `--poolOptions.threads.isolate=false` as it has the best performance (see [this comment](https://github.com/vitest-dev/vitest/issues/579#issuecomment-1946462435))

## Results

Expand All @@ -46,7 +56,7 @@ Benchmarks are run via GitHub Actions. You can check the latest run results [her
- Use `hyperfine` for consistent and reproducible benchmark collection
- Discard the first run (via `--warmup 1`) to let various caches build up
- Use minimal configurations (ie. stock configurations)
- Tests should represent real-world scenarios (in this case, they are copies of real files used in real projects)
- Tests should represent a modern real-world scenario (in this case, they are copies of real files used in a real TypeScript React project)
- Tests should be updated for each test runner's best practices and APIs to give them the best chance possible to be optimized (eg. Jasmine uses APIs like `createSpy()` whereas Jest has `jest.fn()` and Vitest has `vi.fn()`)

## Other Suites
Expand Down
10 changes: 5 additions & 5 deletions benchmarks/bun/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,16 @@
"author": "",
"license": "MIT",
"dependencies": {
"@blueprintjs/icons": "4.6.3",
"@floating-ui/react-dom-interactions": "0.10.1",
"clsx": "1.2.1",
"@blueprintjs/icons": "4.16.0",
"@floating-ui/react-dom-interactions": "0.10.3",
"clsx": "2.1.0",
"date-fns": "2.29.3",
"framer-motion": "7.5.3",
"react": "18.2.0",
"react-dom": "18.2.0"
},
"devDependencies": {
"@happy-dom/global-registrator": "12.10.3",
"happy-dom": "12.0.1"
"@happy-dom/global-registrator": "13.6.2",
"happy-dom": "13.6.2"
}
}
10 changes: 5 additions & 5 deletions benchmarks/jasmine/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,18 +8,18 @@
"author": "",
"license": "MIT",
"dependencies": {
"@blueprintjs/icons": "4.6.3",
"@floating-ui/react-dom-interactions": "0.10.1",
"clsx": "1.2.1",
"@blueprintjs/icons": "4.16.0",
"@floating-ui/react-dom-interactions": "0.10.3",
"clsx": "2.1.0",
"date-fns": "2.29.3",
"framer-motion": "7.5.3",
"react": "18.2.0",
"react-dom": "18.2.0"
},
"devDependencies": {
"@types/jasmine": "4.3.0",
"@types/jasmine": "5.1.4",
"css-modules-require-hook": "4.2.3",
"happy-dom": "12.0.1",
"happy-dom": "13.6.2",
"jasmine": "5.1.0",
"ts-node": "10.9.2"
}
Expand Down
3 changes: 0 additions & 3 deletions benchmarks/jasmine/spec/helpers/happydom.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,7 @@ global.window = window;
'document',
'Element',
'getComputedStyle',
'HTMLCanvasElement',
'HTMLElement',
'HTMLInputElement',
'navigator',
'SVGElement'
].forEach((key) => {
global[key] = global.window[key];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import StatusBadge from '.';
describe('<StatusBadge />', () => {
it('should render without failure', () => {
const {asFragment} = render(<StatusBadge status='DRAFTED' />);
// Jasmine doesn't support shapshot testing, so we just check for Object
// Jasmine doesn't support shapshot testing, so we just check for Object
expect(asFragment()).toEqual(jasmine.any(Object));
});
});
14 changes: 7 additions & 7 deletions benchmarks/jest/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,22 +8,22 @@
"author": "",
"license": "MIT",
"dependencies": {
"@blueprintjs/icons": "4.6.3",
"@floating-ui/react-dom-interactions": "0.10.1",
"clsx": "1.2.1",
"@blueprintjs/icons": "4.16.0",
"@floating-ui/react-dom-interactions": "0.10.3",
"clsx": "2.1.0",
"date-fns": "2.29.3",
"framer-motion": "7.5.3",
"react": "18.2.0",
"react-dom": "18.2.0"
},
"devDependencies": {
"@happy-dom/jest-environment": "12.0.1",
"@testing-library/react": "13.4.0",
"@testing-library/user-event": "14.4.3",
"@happy-dom/jest-environment": "13.6.2",
"@testing-library/react": "14.2.1",
"@testing-library/user-event": "14.5.2",
"identity-obj-proxy": "3.0.0",
"jest": "29.7.0",
"ts-jest": "29.1.2",
"typescript": "4.8.4"
"typescript": "5.3.3"
},
"jest": {
"moduleNameMapper": {
Expand Down
6 changes: 6 additions & 0 deletions benchmarks/tape/helpers/css.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import hook from 'css-modules-require-hook';

// Support for CSS modules
hook({
generateScopedName: '[name]__[local]___[hash:base64:5]',
});
16 changes: 16 additions & 0 deletions benchmarks/tape/helpers/happydom.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { Window } from 'happy-dom';

// Setup happy-dom
const window = new Window();
global.window = window;

// Register global window extensions
[
'document',
'Element',
'getComputedStyle',
'HTMLElement',
'SVGElement'
].forEach((key) => {
global[key] = global.window[key];
});
11 changes: 11 additions & 0 deletions benchmarks/tape/helpers/wrapper.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import {cleanup} from '@testing-library/react';

const withAsyncAndTeardown = (test) => {
return async (t) => {
t.teardown(cleanup);
await test(t);
t.end();
};
}

export default withAsyncAndTeardown;
30 changes: 30 additions & 0 deletions benchmarks/tape/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
{
"name": "tape",
"version": "0.2.0",
"description": "",
"scripts": {
"test": "TZ=UTC ts-node --esm -P tsconfig.json ../../node_modules/.bin/tape -r ./helpers/css.ts -r ./helpers/happydom.ts tests/**/*.test.tsx"
},
"author": "",
"license": "MIT",
"dependencies": {
"@blueprintjs/icons": "4.16.0",
"@floating-ui/react-dom-interactions": "0.10.3",
"clsx": "2.1.0",
"date-fns": "2.29.3",
"framer-motion": "7.5.3",
"react": "18.2.0",
"react-dom": "18.2.0"
},
"devDependencies": {
"@testing-library/react": "14.2.1",
"@testing-library/user-event": "14.5.2",
"css-modules-require-hook": "4.2.3",
"happy-dom": "13.6.2",
"sinon": "17.0.1",
"tape": "5.7.5",
"tape-describe": "1.0.3",
"ts-node": "10.9.2",
"typescript": "5.3.3"
}
}
1 change: 1 addition & 0 deletions benchmarks/tape/tests/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
replica*
60 changes: 60 additions & 0 deletions benchmarks/tape/tests/original/Alert/Alert.module.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
.main {
border: 1px solid transparent;
border-radius: 8px;
display: flex;
font-size: 14px;
padding: 16px;
}

.error {
background: var(--R50);
border-color: var(--R400);
color: var(--R400);
}

/* stylelint-disable-next-line selector-max-type, selector-max-combinators */
.error a, .error strong { color: inherit }

.info {
background: var(--N50);
border-color: var(--N400);
color: var(--N400);
}

/* stylelint-disable-next-line selector-max-type, selector-max-combinators */
.info a, .info strong { color: inherit }

.success {
background: var(--G50);
border-color: var(--G400);
color: var(--G400);
}

/* stylelint-disable-next-line selector-max-type, selector-max-combinators */
.success a, .success strong { color: inherit }

.warning {
background: var(--Y50);
border-color: var(--Y400);
color: var(--Y500);
}

/* stylelint-disable-next-line selector-max-type, selector-max-combinators */
.warning a, .warning strong { color: inherit }

.icon {
margin-right: 16px;
}

.title {
color: inherit;
font-weight: bold;
margin: 0 0 8px;
}

.text {
display: flex;
flex-direction: column;
}

.children { color: var(--COLOR-GRAY-800) }
28 changes: 28 additions & 0 deletions benchmarks/tape/tests/original/Alert/Alert.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import describe from 'tape-describe';
import Alert from '.';
import React from 'react';
import {render} from '@testing-library/react';
import withAsyncAndTeardown from '../../../helpers/wrapper';

describe('<Alert />', (test) => {
test('should render the given message', withAsyncAndTeardown((t) => {
const {getByText} = render(<Alert>Hello World</Alert>);
t.ok(getByText('Hello World'));
}));

test('should render with only a title', withAsyncAndTeardown((t) => {
const {getByText} = render(<Alert title='Hello World' />);
t.ok(getByText('Hello World'));
}));

test('should support all the different icons', withAsyncAndTeardown((t) => {
const {getByLabelText, rerender} = render(<Alert intent='warning' />);
t.ok(getByLabelText('warning-sign'));

rerender(<Alert intent='info' />)
t.ok(getByLabelText('info-sign'));

rerender(<Alert intent='success' />)
t.ok(getByLabelText('tick-circle'));
}));
});
48 changes: 48 additions & 0 deletions benchmarks/tape/tests/original/Alert/Alert.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import Icon, {IconNames} from '../Icon';
import clsx from 'clsx';
import React from 'react';
import styles from './Alert.module.css';

type IntentType = 'error' | 'info' | 'success' | 'warning';

type PropsType = {
className?: string | null,
children?: React.ReactNode,
intent?: IntentType,
title?: string | null,
}

const getIcon = (intent: IntentType) => {
switch (intent) {
case 'info': return IconNames.InfoSign;
case 'success': return IconNames.TickCircle;
case 'warning': return IconNames.WarningSign;
case 'error': return IconNames.Error;
}
return IconNames.Error;
};

const Alert = ({
className,
children,
intent = 'error',
title,
}: PropsType) => {
const classes = clsx(styles.main, styles[intent], className);

return (
<div className={classes} role='alert'>
<Icon
className={styles.icon}
name={getIcon(intent)} />
<div className={styles.text}>
{title ? <h4 className={styles.title}>{title}</h4> : null}
{children ? (
<div className={styles.children}>{children}</div>
) : null}
</div>
</div>
);
};

export default Alert;
1 change: 1 addition & 0 deletions benchmarks/tape/tests/original/Alert/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export {default} from './Alert';
9 changes: 9 additions & 0 deletions benchmarks/tape/tests/original/Avatar/Avatar.module.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
.main {
align-items: center;
border-radius: 100%;
display: inline-flex;
font-size: 15px;
height: 40px;
justify-content: center;
width: 40px;
}
Loading

0 comments on commit 93ec87f

Please sign in to comment.