Skip to content

Commit

Permalink
Merge pull request #2 from crewdevio/development
Browse files Browse the repository at this point in the history
Maven information
  • Loading branch information
RivierGrullon authored Jul 22, 2020
2 parents 65ef962 + bc4aed7 commit d091bdb
Show file tree
Hide file tree
Showing 5 changed files with 413 additions and 45 deletions.
181 changes: 139 additions & 42 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,39 +22,30 @@ Merlin is a [Jest](https://jestjs.io/en/)-inspired testing framework for deno.

### All Matchers

- `testEqual(label: string, config)`_Compare two values and throws an error if the expect and toBe are not equal._

- `testNotEqual(label: string, config)`_Compare two values and throws an error if the expect and notBe are equal._

- `evalEquals(testEqual[])` _evaluate multiple equality tests in an array. If the data is not the same it throws an error._

- `fetchEqual(label: string, config)` _evaluate if two values ​​are equal. If the request data is not the same as expected, it throws an error._

- `arrayContains(label: string, config)`_evaluates that the array contains an especific data. if the array does not contain the data it throws an error._

- `stringContains(label: string, config)`_evaluates if a string contains an especific word. if the string does not contain the word it throws an error._

- `beNull(label: string, config)` _evaluates if a data is null._

- `beFalsy(label: string, config)`_evaluates if a data is a falsy value._

- `beTruthy(label: string, config)`_evaluates if a data is a truthy value._

- `isBigInt(label: string, config)`_evaluates if a data is a bigInt value type._

- `isZero(label: string, config)`_evaluates if a data is a Zero_

- `isNaN(label: string, config)`_evaluates if a data is NaN value._

- `sameLength(label: string, config)`_evaluates if data has a especific length_

- `testRegExp(label: string, config)`_evaluates if a regular expression match_

- `isFunction(label: string, config)` _evaluates if a data is a function_

- `isSymbol(label: string, config)`_evaluates if a data is a symbol_

- `isUndefined(label: string, config)`_evaluates if a data is undefined_
- `testEqual(label: string, config)` Compare two values and throws an error if the expect and toBe are not equal
- `testNotEqual(label: string, config)` Compare two values and throws an error if the expect and notBe are equal
- `evalEquals(testEqual[])` evaluate multiple equality tests in an array. If the data is not the same it throws an error
- `fetchEqual(label: string, config)` evaluate if two values are equal. If the request data is not the same as expected, it throws an error
- `arrayContains(label: string, config)` evaluates that the array contains an especific data. if the array does not contain the data it throws an error
- `stringContains(label: string, config)` evaluates if a string contains an especific word. if the string does not contain the word it throws an error
- `beNull(label: string, config)` evaluates if a data is null
- `beFalsy(label: string, config)` evaluates if a data is a falsy value
- `beTruthy(label: string, config)` evaluates if a data is a truthy value
- `isBigInt(label: string, config)` evaluates if a data is a bigInt value type
- `isZero(label: string, config)` evaluates if a data is a Zero
- `isNaN(label: string, config)` evaluates if a data is NaN value
- `sameLength(label: string, config)` evaluates if data has a especific length
- `testRegExp(label: string, config)` evaluates if a regular expression match
- `isFunction(label: string, config)` evaluates if a data is a function
- `isSymbol(label: string, config)` evaluates if a data is a symbol
- `isUndefined(label: string, config)` evaluates if a data is undefined
- `testSame(label: string, config)` evaluates if two values are strictly the same
- `testGreaterOrEqual(label: string, config)` evaluates whether the expected data is greater than or equal to another
- `testGreater(label: string, config)` evaluates whether the expected data is greater than another
- `testLess(label: string, config)` evaluates if the expected data is less than another
- `testLessOrEqual(label: string, config)` evaluates if the expected data is less than or equal to another
- `testInstanceOf(label: string, config)` evaluates that one object is an instance of another
- `testFloat(label: string, config)` evaluates if two decimal numbers are equal

### Basic Use

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

## about resources and ops sanitizers
### about resources and ops sanitizers

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

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

test.testEqual("Leak resources test", {
expect:() => "test",
toBe:() =>writeSomething(),
expect: async () => await writeSomething(),
toBe: () => "test",
only: true,
Ops: false,
Resources: false
Resources: false,
});
```

```sh
deno test

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

test result: ok. 3 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out
```

### Multiple tests

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

### testRegExp

```typescript
test.testRegExp("regEx match",{
expect:()=> "https://google.com",
toBe:()=> new RegExp("^https?:\/\/[a-z.]+\.com$"),
})
test.testRegExp("regEx match", {
expect: () => "https://google.com",
toBe: () => new RegExp("^https?://[a-z.]+.com$"),
});
```

```sh
deno test

test regEx match ... ok (6ms)

test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out (342ms)
```
```

### Usin async code.

you can use asynchronous code by adding `async` in `expect`, `toBe` and `value` functions.

example

```typescript
const test = new Merlin();

test.testEqual("get error 404", {
async expect() {
const response = await fetch("https://deno.land/std/example/examples.ts");

const data = response.text();

return data;
},
toBe() {
return "404: Not Found";
},
});
```

> **Note**: all the methods of the merlin class support asyn function since they have top level await
## Create benchmarks using Maven

Maven is a benchmark tool for deno included in Merlin.

It's easy to use. `example`:

```typescript
import { Maven } from "https://deno.land/x/merlin/mod.ts";

const benchmark = new Maven();

benchmark.Bench({
name: "Sorting arrays",
fn: () => {
new Array(10000).fill(Math.random()).sort();
},
steps: 1000,
});

benchmark.runBench();
```

this is the terminal output

![gif](https://cdn.discordapp.com/attachments/656976424778989602/735278025742221324/ezgif.com-video-to-gif.gif)

### Parameters

maven receives the following parameters.

- `name: string` benchmark name
- `fn(): void` function that contains the code
- `steps: number` number of times to repeat the benchmark

you can see the details at the end of the benchmark using

```typescript
import { Maven } from "https://deno.land/x/merlin/mod.ts";

const benchmark = new Maven();

benchmark.Bench({
name: "Sorting arrays",
fn: () => {
new Array(10000).fill(Math.random()).sort();
},
steps: 1000,
});

benchmark.runBench().then(benchmark.Result());
```

It has a table with the detailed values

```sh
▒▒▒▒▒▒▒▒ Benchmarking finished

┌───────────────────────────────────────────────────────────────────────────────────────────┐
│ 🧪 Benchmark name: Sorting arrays │
├───────────────────────┬──────────────────────────────┬────────────────────────────────────┤
│ Total runs: 1000 │ Total time: 1099.6591 ms │ Avg time: 1.0997 ms │
├───────────────────────┼────────────────────┬─────────┴───────────┬────────────────────────┤
│ min: 0.7768 ms │ max: 9.9867 ms │ mean: 5.3817 ms │ median: 0.8511 ms │
├───────────────────────┴────────────────────┴─────────────────────┴────────────────────────┤
│ Thresholds: 0 ========== 70 ========== 90 ========== ∞ │
├───────────────────────────────┬───────────────────────────────────────────────────────────┤
│ │ │
│ 0.7768 ms _[ 965][96.5%] │======================================================== │
│ 2.6188 ms _[ 33][ 3.3%] │== │
│ 4.4608 ms _[ 1][ 0.1%] │= │
│ 6.3027 ms _[ 0][ 0%] │ │
│ 8.1447 ms _[ 1][ 0.1%] │= │
│ │ │
└───────────────────────────────┴───────────────────────────────────────────────────────────┘

```
37 changes: 37 additions & 0 deletions cli.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
/**
* Copyright (c) Crew Dev.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
*/

import { colors } from "./deps.ts";

async function main() {
const [command, ...args] = Deno.args;

if (command === "start") {
const process = Deno.run({
cmd: ["deno", "test", "--allow-hrtime", ...args],
});

if ((await process.status()).success) {
Deno.close(process.rid);
} else {
Deno.close(process.rid);
throw new Error(colors.red("something went wrong trying to run the test"))
.message;
}
} else if (command === "help") {
console.log("help info...");
} else {
throw new Error(
colors.red("this command was not found, try run: merlin help")
).message;
}
}

if (import.meta.main) {
await main();
}
3 changes: 2 additions & 1 deletion deps.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
* LICENSE file in the root directory of this source tree.
*
*/

export * from "https://deno.land/x/[email protected]/mod.ts";
export * as colors from "https://deno.land/std/fmt/colors.ts";
export * from "https://deno.land/std/testing/asserts.ts";
export * from "https://deno.land/std/testing/bench.ts";
46 changes: 44 additions & 2 deletions src/maven.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,22 +11,45 @@ import {
runBenchmarks,
BenchmarkResult,
BenchmarkRunOptions,
prettyBenchmarkProgress,
prettyBenchmarkResult,
colors,
} from "../deps.ts";

interface Bench {
name: string;
steps?: number;
fn: Function;
}

interface Thresholds {
[key: string]: { green: number; yellow: number };
}

export type BenchResult = BenchmarkResult;

export class Maven {
private bench = bench;

private thresholds: Thresholds = {};

private config: BenchmarkRunOptions = {};

private indicators = [
{
benches: /./,
tableColor: colors.cyan,
modFn: () => "🧪",
},
];

private runIndicator = [{ benches: /./, modFn: () => colors.green(" ==> ") }];

private addThreasholds(name: string) {
this.thresholds[name] = { green: 70, yellow: 90 };
}

public Bench({ fn, name, steps = 1 }: Bench) {
this.addThreasholds(name);
this.bench({
name,
func(bench) {
Expand All @@ -40,10 +63,29 @@ export class Maven {

public async runBench(config?: BenchmarkRunOptions) {
this.config = config as BenchmarkRunOptions;
return runBenchmarks(config);
return runBenchmarks(
{ silent: true, ...config },
prettyBenchmarkProgress({
indicators: this.runIndicator,
thresholds: this.thresholds,
})
);
}

public async success() {
return await this.runBench(this.config);
}

public Result(graphBars = 5) {
return prettyBenchmarkResult({
thresholds: this.thresholds,
indicators: this.indicators,
parts: {
extraMetrics: true,
graph: true,
threshold: true,
graphBars,
},
});
}
}
Loading

0 comments on commit d091bdb

Please sign in to comment.