Skip to content

Commit

Permalink
Merge pull request #8 from gmaxlev/v1.3
Browse files Browse the repository at this point in the history
v1.3
  • Loading branch information
gmaxlev authored Oct 22, 2023
2 parents a89ba0c + d4a388f commit 7142e79
Show file tree
Hide file tree
Showing 15 changed files with 549 additions and 173 deletions.
35 changes: 35 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,9 @@ PICT will generate the following test cases:
In most cases, to generate test cases, you can use the `pict` function. The main features of this function is that you can use any data type for the values of the model.

```js
import { pict } from "pict-node";
import { createOrder } from "./src";

// Define test model
const model = [
{
Expand Down Expand Up @@ -476,6 +479,38 @@ const cases = native({
});
```

## Statistics

You can obtain model statistics using the `stats` method.

This method is accessible through the `pict`, `strings`, and `native` APIs.

```js
import { pict } from "pict-node";

const model = [
{
key: "platform",
values: ["x86", "x64", "arm"],
},
{
key: "ram",
values: [1, 4, 64],
},
];

const stats = await pict.stats({
model,
});
```

The `stats` method returns an object with the following fields:

- `generationTimeNodeJs` - model generation time (including Node.js processing time)
- `generationTime` - model generation time (excluding Node.js processing time)
- `combinations` - number of combinations
- `generatedTests` - number of generated tests

## License

[MIT](LICENSE)
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "pict-node",
"version": "1.2.1",
"version": "1.3.0",
"description": "Combinatorial Test Case Generation",
"keywords": [
"pict",
Expand Down
87 changes: 44 additions & 43 deletions src/api/native/index.ts
Original file line number Diff line number Diff line change
@@ -1,21 +1,30 @@
import fsp from "fs/promises";
import { isString, isUndefined, isBoolean, isRecord } from "tsguarder";
import { isUndefined, isBoolean, isRecord } from "tsguarder";
import { ModelSource, isModelSource } from "./types";
import type { CallPictOptions } from "./../../common/pict";
import { isPositiveNumber } from "./../../common/utils";
import {
PictCliOptions,
isRandomOption,
isModelSeparator,
PictNodeStatistics,
} from "../../common/types";
import { callPict, pictEntries } from "../../common/pict";
import { callPict } from "../../common/pict";
import { getModelFromSource } from "./utils";
import { parseResult } from "./parse";
import { performance } from "perf_hooks";
import { parseStatistics } from "../../common/statistics";

interface NativeOptions {
model: ModelSource;
seed?: ModelSource;
options?: Partial<Omit<PictCliOptions, "seed">>;
options?: Partial<Omit<PictCliOptions, "seed" | "statistics">>;
}

type Native = {
(options: NativeOptions): Promise<Record<string, string>[]>;
stats: (options: NativeOptions) => Promise<PictNodeStatistics>;
};

function validate(options: NativeOptions) {
isRecord.assert(options, "the first argument");
isModelSource.assert(options.model, '"model"');
Expand Down Expand Up @@ -63,63 +72,55 @@ function validate(options: NativeOptions) {
}
}

function parseResult(result: string): Array<Record<string, string>> {
const cases: any[] = [];

for (const item of pictEntries(result)) {
let currentCase;
async function prepare(options: NativeOptions) {
validate(options);

if (item.valueIndex === 0) {
currentCase = {};
cases.push(currentCase);
} else {
currentCase = cases[cases.length - 1];
}
const callPictOptions: CallPictOptions = {
modelText: await getModelFromSource(options.model),
options: {},
};

currentCase[item.rowName as string] = item.value;
if (!isUndefined(options.seed)) {
callPictOptions.seedText = await getModelFromSource(options.seed);
}

cases[cases.length - 1] = currentCase;
if (!isUndefined(options.options)) {
callPictOptions.options = options.options;
}

return cases;
return callPictOptions;
}

async function getModelFromSource(source: ModelSource) {
if (isString(source)) {
return source;
}

export const native: Native = async function native(options: NativeOptions) {
try {
const fileContent = await fsp.readFile(source.file);
return fileContent.toString();
const callPictOptions = await prepare(options);

callPictOptions.options.statistics = false;

const result = await callPict(callPictOptions);

return parseResult(result);
} catch (error) {
console.error(`Error while reading model file. ${source.file}`);
console.error('Error while calling "native" function.');
throw error;
}
}
};

export async function native(options: NativeOptions) {
native.stats = async function native(options: NativeOptions) {
try {
validate(options);
const start = performance.now();

const callPictOptions: CallPictOptions = {
modelText: await getModelFromSource(options.model),
options: {},
};
const callPictOptions = await prepare(options);

if (!isUndefined(options.seed)) {
callPictOptions.seedText = await getModelFromSource(options.seed);
}

if (!isUndefined(options.options)) {
callPictOptions.options = options.options;
}
callPictOptions.options.statistics = true;

const result = await callPict(callPictOptions);

return parseResult(result);
const end = performance.now() - start;

return parseStatistics(result, end);
} catch (error) {
console.error('Error while calling "native" function.');
console.error('Error while calling "native.stats" function.');
throw error;
}
}
};
22 changes: 22 additions & 0 deletions src/api/native/parse.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { pictEntries } from "../../common/pict";

export function parseResult(result: string): Array<Record<string, string>> {
const cases: any[] = [];

for (const item of pictEntries(result)) {
let currentCase;

if (item.valueIndex === 0) {
currentCase = {};
cases.push(currentCase);
} else {
currentCase = cases[cases.length - 1];
}

currentCase[item.rowName as string] = item.value;

cases[cases.length - 1] = currentCase;
}

return cases;
}
17 changes: 17 additions & 0 deletions src/api/native/utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import type { ModelSource } from "./types";
import { isString } from "tsguarder";
import fsp from "fs/promises";

export async function getModelFromSource(source: ModelSource) {
if (isString(source)) {
return source;
}

try {
const fileContent = await fsp.readFile(source.file);
return fileContent.toString();
} catch (error) {
console.error(`Error while reading model file. ${source.file}`);
throw error;
}
}
Loading

0 comments on commit 7142e79

Please sign in to comment.