Skip to content

Commit d091bdb

Browse files
Merge pull request #2 from crewdevio/development
Maven information
2 parents 65ef962 + bc4aed7 commit d091bdb

File tree

5 files changed

+413
-45
lines changed

5 files changed

+413
-45
lines changed

README.md

Lines changed: 139 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -22,39 +22,30 @@ Merlin is a [Jest](https://jestjs.io/en/)-inspired testing framework for deno.
2222

2323
### All Matchers
2424

25-
- `testEqual(label: string, config)`_Compare two values and throws an error if the expect and toBe are not equal._
26-
27-
- `testNotEqual(label: string, config)`_Compare two values and throws an error if the expect and notBe are equal._
28-
29-
- `evalEquals(testEqual[])` _evaluate multiple equality tests in an array. If the data is not the same it throws an error._
30-
31-
- `fetchEqual(label: string, config)` _evaluate if two values ​​are equal. If the request data is not the same as expected, it throws an error._
32-
33-
- `arrayContains(label: string, config)`_evaluates that the array contains an especific data. if the array does not contain the data it throws an error._
34-
35-
- `stringContains(label: string, config)`_evaluates if a string contains an especific word. if the string does not contain the word it throws an error._
36-
37-
- `beNull(label: string, config)` _evaluates if a data is null._
38-
39-
- `beFalsy(label: string, config)`_evaluates if a data is a falsy value._
40-
41-
- `beTruthy(label: string, config)`_evaluates if a data is a truthy value._
42-
43-
- `isBigInt(label: string, config)`_evaluates if a data is a bigInt value type._
44-
45-
- `isZero(label: string, config)`_evaluates if a data is a Zero_
46-
47-
- `isNaN(label: string, config)`_evaluates if a data is NaN value._
48-
49-
- `sameLength(label: string, config)`_evaluates if data has a especific length_
50-
51-
- `testRegExp(label: string, config)`_evaluates if a regular expression match_
52-
53-
- `isFunction(label: string, config)` _evaluates if a data is a function_
54-
55-
- `isSymbol(label: string, config)`_evaluates if a data is a symbol_
56-
57-
- `isUndefined(label: string, config)`_evaluates if a data is undefined_
25+
- `testEqual(label: string, config)` Compare two values and throws an error if the expect and toBe are not equal
26+
- `testNotEqual(label: string, config)` Compare two values and throws an error if the expect and notBe are equal
27+
- `evalEquals(testEqual[])` evaluate multiple equality tests in an array. If the data is not the same it throws an error
28+
- `fetchEqual(label: string, config)` evaluate if two values are equal. If the request data is not the same as expected, it throws an error
29+
- `arrayContains(label: string, config)` evaluates that the array contains an especific data. if the array does not contain the data it throws an error
30+
- `stringContains(label: string, config)` evaluates if a string contains an especific word. if the string does not contain the word it throws an error
31+
- `beNull(label: string, config)` evaluates if a data is null
32+
- `beFalsy(label: string, config)` evaluates if a data is a falsy value
33+
- `beTruthy(label: string, config)` evaluates if a data is a truthy value
34+
- `isBigInt(label: string, config)` evaluates if a data is a bigInt value type
35+
- `isZero(label: string, config)` evaluates if a data is a Zero
36+
- `isNaN(label: string, config)` evaluates if a data is NaN value
37+
- `sameLength(label: string, config)` evaluates if data has a especific length
38+
- `testRegExp(label: string, config)` evaluates if a regular expression match
39+
- `isFunction(label: string, config)` evaluates if a data is a function
40+
- `isSymbol(label: string, config)` evaluates if a data is a symbol
41+
- `isUndefined(label: string, config)` evaluates if a data is undefined
42+
- `testSame(label: string, config)` evaluates if two values are strictly the same
43+
- `testGreaterOrEqual(label: string, config)` evaluates whether the expected data is greater than or equal to another
44+
- `testGreater(label: string, config)` evaluates whether the expected data is greater than another
45+
- `testLess(label: string, config)` evaluates if the expected data is less than another
46+
- `testLessOrEqual(label: string, config)` evaluates if the expected data is less than or equal to another
47+
- `testInstanceOf(label: string, config)` evaluates that one object is an instance of another
48+
- `testFloat(label: string, config)` evaluates if two decimal numbers are equal
5849

5950
### Basic Use
6051

@@ -108,7 +99,7 @@ all assertions have parameters that they can receive, these parameters can chang
10899
- `Resources (optional)` receives a boolean, terminates all asynchronous processes that interact with the system. by default is `true`.
109100
- `only (optional)` receives a boolean, only tests that have `only in true` will be executed, the rest will not run.
110101

111-
## about resources and ops sanitizers
102+
### about resources and ops sanitizers
112103

113104
Certain actions in Deno create resources in the resource table . These resources should be closed after you are done using them.
114105

@@ -126,20 +117,22 @@ async function writeSomething(): Promise<string> {
126117
}
127118

128119
test.testEqual("Leak resources test", {
129-
expect:() => "test",
130-
toBe:() =>writeSomething(),
120+
expect: async () => await writeSomething(),
121+
toBe: () => "test",
131122
only: true,
132123
Ops: false,
133-
Resources: false
124+
Resources: false,
134125
});
135126
```
127+
136128
```sh
137129
deno test
138130

139131
test Leak resources test ... ok (5ms)
140132

141133
test result: ok. 3 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out
142134
```
135+
143136
### Multiple tests
144137

145138
`example.test.ts`
@@ -263,16 +256,120 @@ test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out
263256
```
264257

265258
### testRegExp
259+
266260
```typescript
267-
test.testRegExp("regEx match",{
268-
expect:()=> "https://google.com",
269-
toBe:()=> new RegExp("^https?:\/\/[a-z.]+\.com$"),
270-
})
261+
test.testRegExp("regEx match", {
262+
expect: () => "https://google.com",
263+
toBe: () => new RegExp("^https?://[a-z.]+.com$"),
264+
});
271265
```
266+
272267
```sh
273268
deno test
274269

275270
test regEx match ... ok (6ms)
276271

277272
test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out (342ms)
278-
```
273+
```
274+
275+
### Usin async code.
276+
277+
you can use asynchronous code by adding `async` in `expect`, `toBe` and `value` functions.
278+
279+
example
280+
281+
```typescript
282+
const test = new Merlin();
283+
284+
test.testEqual("get error 404", {
285+
async expect() {
286+
const response = await fetch("https://deno.land/std/example/examples.ts");
287+
288+
const data = response.text();
289+
290+
return data;
291+
},
292+
toBe() {
293+
return "404: Not Found";
294+
},
295+
});
296+
```
297+
298+
> **Note**: all the methods of the merlin class support asyn function since they have top level await
299+
300+
## Create benchmarks using Maven
301+
302+
Maven is a benchmark tool for deno included in Merlin.
303+
304+
It's easy to use. `example`:
305+
306+
```typescript
307+
import { Maven } from "https://deno.land/x/merlin/mod.ts";
308+
309+
const benchmark = new Maven();
310+
311+
benchmark.Bench({
312+
name: "Sorting arrays",
313+
fn: () => {
314+
new Array(10000).fill(Math.random()).sort();
315+
},
316+
steps: 1000,
317+
});
318+
319+
benchmark.runBench();
320+
```
321+
322+
this is the terminal output
323+
324+
![gif](https://cdn.discordapp.com/attachments/656976424778989602/735278025742221324/ezgif.com-video-to-gif.gif)
325+
326+
### Parameters
327+
328+
maven receives the following parameters.
329+
330+
- `name: string` benchmark name
331+
- `fn(): void` function that contains the code
332+
- `steps: number` number of times to repeat the benchmark
333+
334+
you can see the details at the end of the benchmark using
335+
336+
```typescript
337+
import { Maven } from "https://deno.land/x/merlin/mod.ts";
338+
339+
const benchmark = new Maven();
340+
341+
benchmark.Bench({
342+
name: "Sorting arrays",
343+
fn: () => {
344+
new Array(10000).fill(Math.random()).sort();
345+
},
346+
steps: 1000,
347+
});
348+
349+
benchmark.runBench().then(benchmark.Result());
350+
```
351+
352+
It has a table with the detailed values
353+
354+
```sh
355+
▒▒▒▒▒▒▒▒ Benchmarking finished
356+
357+
┌───────────────────────────────────────────────────────────────────────────────────────────┐
358+
│ 🧪 Benchmark name: Sorting arrays │
359+
├───────────────────────┬──────────────────────────────┬────────────────────────────────────┤
360+
│ Total runs: 1000 │ Total time: 1099.6591 ms │ Avg time: 1.0997 ms │
361+
├───────────────────────┼────────────────────┬─────────┴───────────┬────────────────────────┤
362+
│ min: 0.7768 ms │ max: 9.9867 ms │ mean: 5.3817 ms │ median: 0.8511 ms │
363+
├───────────────────────┴────────────────────┴─────────────────────┴────────────────────────┤
364+
│ Thresholds: 0 ========== 70 ========== 90 ========== ∞ │
365+
├───────────────────────────────┬───────────────────────────────────────────────────────────┤
366+
│ │ │
367+
│ 0.7768 ms _[ 965][96.5%] │======================================================== │
368+
│ 2.6188 ms _[ 33][ 3.3%] │== │
369+
│ 4.4608 ms _[ 1][ 0.1%] │= │
370+
│ 6.3027 ms _[ 0][ 0%] │ │
371+
│ 8.1447 ms _[ 1][ 0.1%] │= │
372+
│ │ │
373+
└───────────────────────────────┴───────────────────────────────────────────────────────────┘
374+
375+
```

cli.ts

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
/**
2+
* Copyright (c) Crew Dev.
3+
*
4+
* This source code is licensed under the MIT license found in the
5+
* LICENSE file in the root directory of this source tree.
6+
*
7+
*/
8+
9+
import { colors } from "./deps.ts";
10+
11+
async function main() {
12+
const [command, ...args] = Deno.args;
13+
14+
if (command === "start") {
15+
const process = Deno.run({
16+
cmd: ["deno", "test", "--allow-hrtime", ...args],
17+
});
18+
19+
if ((await process.status()).success) {
20+
Deno.close(process.rid);
21+
} else {
22+
Deno.close(process.rid);
23+
throw new Error(colors.red("something went wrong trying to run the test"))
24+
.message;
25+
}
26+
} else if (command === "help") {
27+
console.log("help info...");
28+
} else {
29+
throw new Error(
30+
colors.red("this command was not found, try run: merlin help")
31+
).message;
32+
}
33+
}
34+
35+
if (import.meta.main) {
36+
await main();
37+
}

deps.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
* LICENSE file in the root directory of this source tree.
66
*
77
*/
8-
8+
export * from "https://deno.land/x/pretty_benching@v0.1.2/mod.ts";
9+
export * as colors from "https://deno.land/std/fmt/colors.ts";
910
export * from "https://deno.land/std/testing/asserts.ts";
1011
export * from "https://deno.land/std/testing/bench.ts";

src/maven.ts

Lines changed: 44 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,22 +11,45 @@ import {
1111
runBenchmarks,
1212
BenchmarkResult,
1313
BenchmarkRunOptions,
14+
prettyBenchmarkProgress,
15+
prettyBenchmarkResult,
16+
colors,
1417
} from "../deps.ts";
15-
1618
interface Bench {
1719
name: string;
1820
steps?: number;
1921
fn: Function;
2022
}
2123

24+
interface Thresholds {
25+
[key: string]: { green: number; yellow: number };
26+
}
27+
2228
export type BenchResult = BenchmarkResult;
2329

2430
export class Maven {
2531
private bench = bench;
2632

33+
private thresholds: Thresholds = {};
34+
2735
private config: BenchmarkRunOptions = {};
2836

37+
private indicators = [
38+
{
39+
benches: /./,
40+
tableColor: colors.cyan,
41+
modFn: () => "🧪",
42+
},
43+
];
44+
45+
private runIndicator = [{ benches: /./, modFn: () => colors.green(" ==> ") }];
46+
47+
private addThreasholds(name: string) {
48+
this.thresholds[name] = { green: 70, yellow: 90 };
49+
}
50+
2951
public Bench({ fn, name, steps = 1 }: Bench) {
52+
this.addThreasholds(name);
3053
this.bench({
3154
name,
3255
func(bench) {
@@ -40,10 +63,29 @@ export class Maven {
4063

4164
public async runBench(config?: BenchmarkRunOptions) {
4265
this.config = config as BenchmarkRunOptions;
43-
return runBenchmarks(config);
66+
return runBenchmarks(
67+
{ silent: true, ...config },
68+
prettyBenchmarkProgress({
69+
indicators: this.runIndicator,
70+
thresholds: this.thresholds,
71+
})
72+
);
4473
}
4574

4675
public async success() {
4776
return await this.runBench(this.config);
4877
}
78+
79+
public Result(graphBars = 5) {
80+
return prettyBenchmarkResult({
81+
thresholds: this.thresholds,
82+
indicators: this.indicators,
83+
parts: {
84+
extraMetrics: true,
85+
graph: true,
86+
threshold: true,
87+
graphBars,
88+
},
89+
});
90+
}
4991
}

0 commit comments

Comments
 (0)