diff --git a/.eslintrc.json b/.eslintrc.json
index 915d1a42cc907d01b1e35bb2d47219144436f34f..f5ca99a3bea9c559bd4d9cdd685d35552822eb90 100644
--- a/.eslintrc.json
+++ b/.eslintrc.json
@@ -42,7 +42,6 @@
        "@typescript-eslint/semi": ["error", "always"],
        "@typescript-eslint/indent": ["error", 2],
        "@typescript-eslint/method-signature-style": ["error", "method"],
-       "@typescript-eslint/naming-convention": "error",
        "@typescript-eslint/no-duplicate-enum-values": "error",
        "@typescript-eslint/restrict-plus-operands": "error",
        "@typescript-eslint/typedef": [
diff --git a/k6_modules/SummaryData.d.ts b/k6_modules/SummaryData.d.ts
new file mode 100644
index 0000000000000000000000000000000000000000..423da1ab45edf8efa86e24dca4f889149f7870c8
--- /dev/null
+++ b/k6_modules/SummaryData.d.ts
@@ -0,0 +1,112 @@
+declare module "k6/data" {
+  type Options = {
+    noColor: boolean;
+    summaryTrendStats: string[];
+    summaryTimeUnit: string;
+  };
+
+  type State = {
+    isStdOutTTY: boolean;
+    isStdErrTTY: boolean;
+    testRunDurationMs: number;
+  };
+
+  type Metrics = {
+    requests_per_second: {
+      contains: string;
+      values: {
+        rate: number;
+        passes: number;
+        fails: number;
+      };
+      type: string;
+    };
+    iterations: {
+      type: string;
+      contains: string;
+      values: {
+        rate: number;
+        count: number;
+      };
+    };
+    data_sent: {
+      type: string;
+      contains: string;
+      values: {
+        count: number;
+        rate: number;
+      };
+    };
+    data_received: {
+      type: string;
+      contains: string;
+      values: {
+        count: number;
+        rate: number;
+      };
+    };
+    iteration_duration: {
+      type: string;
+      contains: string;
+      values: {
+        med: number;
+        max: number;
+        p90: number;
+        p95: number;
+        avg: number;
+        min: number;
+      };
+    };
+    response_time: {
+      type: string;
+      contains: string;
+      values: {
+        min: number;
+        med: number;
+        max: number;
+        p90: number;
+        p95: number;
+        avg: number;
+      };
+    };
+    total_requests: {
+      type: string;
+      contains: string;
+      values: {
+        rate: number;
+        count: number;
+      };
+    };
+    vus: {
+      min: number;
+      max: number;
+      value: number;
+    };
+    vus_max: {
+      value: number;
+      min: number;
+      max: number;
+    };
+  };
+
+  type Group = {
+    name: string;
+    path: string;
+    id: string;
+    groups: Group[];
+  };
+
+  type Root = {
+    name: string;
+    path: string;
+    id: string;
+    groups: Group[];
+  };
+
+  export type SummaryData = {
+    options: Options;
+    state: State;
+    metrics: Metrics;
+    root_group: Root;
+  };
+}
diff --git a/k6_modules/k6Utils.d.ts b/k6_modules/k6Utils.d.ts
deleted file mode 100644
index 838205170d76499cd63774469463bfe31dfcc652..0000000000000000000000000000000000000000
--- a/k6_modules/k6Utils.d.ts
+++ /dev/null
@@ -1,10 +0,0 @@
-// Declaring modules like this allows to declare types for k6 libraries
-declare module "https://jslib.k6.io/k6-utils/1.4.0/index.js" {
-  interface K6Utils {
-    randomItem<T>(array: Array<T>): T;
-  }
-
-  const package: K6Utils;
-
-  export = package;
-}
diff --git a/src/App.ts b/src/App.ts
index a9712d09b4eb3fd276ac83a7c9d38d77c52e1e30..1887cc58d8e579164eaa9129d2f56487667b17f3 100644
--- a/src/App.ts
+++ b/src/App.ts
@@ -1,5 +1,4 @@
-/* eslint-disable import/no-unresolved */
-/* eslint-disable @typescript-eslint/typedef */
+import { SummaryData } from "k6/data";
 import IPROTO, { TarantoolConnection } from "k6/x/tarantool";
 
 import Metrics from "../src/Metrics";
@@ -26,7 +25,7 @@ if (CLIENTS === undefined) {
 // Connection pool of clients
 const connections: TarantoolConnection[] = CLIENTS.map((host: string) => IPROTO.connect([host]));
 // Parsed and validated scenario.yml
-const scenario: Scenario = new ScenarioParser(SCENARIO_PATH).parse();
+const scenario: Scenario = new ScenarioParser(open(SCENARIO_PATH)).parse();
 // Generated SQL queue from scenario.yml
 const queryQueue: SQLQueue = new SQLQueue(SEED, scenario.queries, QUERY_REQUEST_AMOUNT);
 // Metrics object, that counts requests and measures responce time
@@ -34,11 +33,7 @@ const metrics: Metrics = new Metrics();
 // Array of generated data for each column
 const columnsGeneratedData: Array<Column> = [];
 
-export const setup = () => {
-  console.info(`SCENARIO: ${scenario.name}`);
-  console.info(`SEED: ${SEED}`);
-  //console.log(queryQueue.queue);
-
+export const setup: () => void = () => {
   // Itterate through array of Table classes
   for (const table of scenario.tables) {
     table.create(getClient(connections));
@@ -69,10 +64,42 @@ export default () => {
   }
 };
 
-export const teardown = () => {
+export const teardown: () => void = () => {
   // Itterate through array of Table classes
   for (const table of scenario.tables) {
     // Drop table
     table.drop(getClient(connections));
   }
 };
+
+export function handleSummary(data: SummaryData) {
+  console.log("--- Test Summary ---");
+  const summary: object = {
+    seed: SEED,
+    reqsSent: QUERY_REQUEST_AMOUNT,
+    reqsActual: data.metrics.total_requests.values.count,
+    totalReqs: {
+      ratePerSec: data.metrics.total_requests.values.rate,
+      count: data.metrics.total_requests.values.count
+    },
+    reqs: {
+      pass: data.metrics.requests_per_second.values.passes,
+      fail: data.metrics.requests_per_second.values.fails,
+      rate: data.metrics.requests_per_second.values.rate
+    },
+    responceTime: {
+      min: data.metrics.response_time.values.min,
+      max: data.metrics.response_time.values.max,
+      avg: data.metrics.response_time.values.avg.toFixed(2)
+    },
+    iterationDurationAvg: data.metrics.iteration_duration.values.avg.toFixed(2)
+  };
+  return {
+    stdout: JSON.stringify(summary, null, 2)
+      .replace(/"/g, "")
+      .replace(/[{}]/g, "")
+      .replace(/,/g, "")
+      .replace(/(\n\s*\n)+/g, "\n"),
+    [`summary/summary_${SEED}.json`]: JSON.stringify(summary, null, 2)
+  };
+}
diff --git a/src/Column.ts b/src/Column.ts
index 6a5c4a8630e0e33edcc56c42b1a06b7c59330962..c07664221471a5c4ea7348ec5f686b7445eb6c87 100644
--- a/src/Column.ts
+++ b/src/Column.ts
@@ -1,6 +1,7 @@
-import { IDistribution } from "./distributions/IDistribution";
+import { DistributionOpts, IDistribution } from "./distributions/IDistribution";
 import NormalDistribution from "./distributions/NormalDistribution";
 import UniformDistribution from "./distributions/UniformDistribution";
+import ZipfDistribution from "./distributions/ZipfDistribution";
 import { BooleanType } from "./types/Boolean";
 import { DecimalType } from "./types/Decimal";
 import { SignedIntType } from "./types/SignedInt";
@@ -34,6 +35,8 @@ export abstract class AbstractColumn<T> implements IColumn<T> {
         return useSingleton ? NormalDistribution.getInstance(seed, this.type) : new NormalDistribution(seed);
       case "UNIFORM":
         return useSingleton ? UniformDistribution.getInstance(seed, this.type) : new UniformDistribution(seed);
+      case "ZIPF":
+        return useSingleton ? ZipfDistribution.getInstance(seed, this.type) : new ZipfDistribution(seed);
       default:
         throw new Error("Column : getDistribution: Distribution not supported");
     }
@@ -45,22 +48,22 @@ export abstract class AbstractColumn<T> implements IColumn<T> {
 export class StringColumn extends AbstractColumn<string> {
   readonly range: [number, number];
   readonly alphabet: string[];
-  readonly unique: boolean;
+  readonly distributionOpts: DistributionOpts;
 
   constructor(
     name: string,
     type: string,
     distribution: string,
+    distributionOpts: DistributionOpts,
     range: [number, number],
     alphabet: string[],
     isNullable: boolean,
-    nullPercentage: number,
-    unique: boolean
+    nullPercentage: number
   ) {
     super(name, type, distribution, isNullable, nullPercentage);
     this.range = range;
     this.alphabet = alphabet;
-    this.unique = unique;
+    this.distributionOpts = distributionOpts;
   }
 
   public generateData(seed: number, size: number, useSingleton: boolean): Array<string | null> {
@@ -70,29 +73,29 @@ export class StringColumn extends AbstractColumn<string> {
       : new StringType(distribution, this.range, this.alphabet);
 
     if (this.isNullable === true) {
-      return typeInstance.generateArrayWithNull(size, this.nullPercentage, this.unique);
+      return typeInstance.generateArrayWithNull(size, this.nullPercentage, this.distributionOpts);
     } else {
-      return typeInstance.generateArrayWithoutNull(size, this.unique);
+      return typeInstance.generateArrayWithoutNull(size, this.distributionOpts);
     }
   }
 }
 
 export class UnsignedColumn extends AbstractColumn<number> {
   readonly range: [number, number];
-  readonly unique: boolean;
+  readonly distributionOpts: DistributionOpts;
 
   constructor(
     name: string,
     type: string,
     distribution: string,
+    distributionOpts: DistributionOpts,
     range: [number, number],
     isNullable: boolean,
-    nullPercentage: number,
-    unique: boolean
+    nullPercentage: number
   ) {
     super(name, type, distribution, isNullable, nullPercentage);
     this.range = range;
-    this.unique = unique;
+    this.distributionOpts = distributionOpts;
   }
 
   public generateData(seed: number, size: number, useSingleton: boolean): Array<number | null> {
@@ -102,9 +105,9 @@ export class UnsignedColumn extends AbstractColumn<number> {
       : new UnsignedIntType(distribution, this.range);
 
     if (this.isNullable === true) {
-      return typeInstance.generateArrayWithNull(size, this.nullPercentage, this.unique);
+      return typeInstance.generateArrayWithNull(size, this.nullPercentage, this.distributionOpts);
     } else {
-      return typeInstance.generateArrayWithoutNull(size, this.unique);
+      return typeInstance.generateArrayWithoutNull(size, this.distributionOpts);
     }
   }
 }
@@ -114,12 +117,12 @@ export class IntegerColumn extends UnsignedColumn {
     name: string,
     type: string,
     distribution: string,
+    distributionOpts: DistributionOpts,
     range: [number, number],
     isNullable: boolean,
-    nullPercentage: number,
-    unique: boolean
+    nullPercentage: number
   ) {
-    super(name, type, distribution, range, isNullable, nullPercentage, unique);
+    super(name, type, distribution, distributionOpts, range, isNullable, nullPercentage);
   }
 
   public generateData(seed: number, size: number, useSingleton: boolean): Array<number | null> {
@@ -129,9 +132,9 @@ export class IntegerColumn extends UnsignedColumn {
       : new SignedIntType(distribution, this.range);
 
     if (this.isNullable === true) {
-      return typeInstance.generateArrayWithNull(size, this.nullPercentage, this.unique);
+      return typeInstance.generateArrayWithNull(size, this.nullPercentage, this.distributionOpts);
     } else {
-      return typeInstance.generateArrayWithoutNull(size, this.unique);
+      return typeInstance.generateArrayWithoutNull(size, this.distributionOpts);
     }
   }
 }
@@ -141,12 +144,12 @@ export class DecimalColumn extends IntegerColumn {
     name: string,
     type: string,
     distribution: string,
+    distributionOpts: DistributionOpts,
     range: [number, number],
     isNullable: boolean,
-    nullPercentage: number,
-    unique: boolean
+    nullPercentage: number
   ) {
-    super(name, type, distribution, range, isNullable, nullPercentage, unique);
+    super(name, type, distribution, distributionOpts, range, isNullable, nullPercentage);
   }
 
   public generateData(seed: number, size: number, useSingleton: boolean): Array<number | null> {
@@ -156,16 +159,25 @@ export class DecimalColumn extends IntegerColumn {
       : new DecimalType(distribution, this.range);
 
     if (this.isNullable === true) {
-      return typeInstance.generateArrayWithNull(size, this.nullPercentage, this.unique);
+      return typeInstance.generateArrayWithNull(size, this.nullPercentage, this.distributionOpts);
     } else {
-      return typeInstance.generateArrayWithoutNull(size, this.unique);
+      return typeInstance.generateArrayWithoutNull(size, this.distributionOpts);
     }
   }
 }
 
 export class BooleanColumn extends AbstractColumn<boolean> {
-  constructor(name: string, type: string, distribution: string, isNullable: boolean, nullPercentage: number) {
+  readonly distributionOpts: DistributionOpts;
+  constructor(
+    name: string,
+    type: string,
+    distribution: string,
+    distributionOpts: DistributionOpts,
+    isNullable: boolean,
+    nullPercentage: number
+  ) {
     super(name, type, distribution, isNullable, nullPercentage);
+    this.distributionOpts = distributionOpts;
   }
 
   public generateData(seed: number, size: number, useSingleton: boolean): Array<boolean | null> {
@@ -175,9 +187,9 @@ export class BooleanColumn extends AbstractColumn<boolean> {
       : new BooleanType(distribution);
 
     if (this.isNullable === true) {
-      return typeInstance.generateArrayWithNull(size, this.nullPercentage);
+      return typeInstance.generateArrayWithNull(size, this.nullPercentage, this.distributionOpts);
     } else {
-      return typeInstance.generateArrayWithoutNull(size);
+      return typeInstance.generateArrayWithoutNull(size, this.distributionOpts);
     }
   }
 }
diff --git a/src/Cutter.ts b/src/Cutter.ts
index 5388b928a1f21574e372587428a50a883fda2d17..ce73409258282db67f885926f69237b232985194 100644
--- a/src/Cutter.ts
+++ b/src/Cutter.ts
@@ -1,7 +1,7 @@
 import { ITape } from "./Tape";
 
 export interface ICutter {
-  generateWords(amount: number, uniqueWords: boolean): string[];
+  generateWords(amount: number, uniqueWords?: boolean): string[];
 }
 
 /**
diff --git a/src/ScenarioParser.ts b/src/ScenarioParser.ts
index 12e34053903311a1b27f62bc4b13eac3410d63e6..fc50f8db6ceb64ea06faf2f31a22cf89dddd6c49 100644
--- a/src/ScenarioParser.ts
+++ b/src/ScenarioParser.ts
@@ -10,6 +10,7 @@ import YAML from "k6/x/yaml";
 import { AbstractColumn, BooleanColumn, DecimalColumn, IntegerColumn, StringColumn, UnsignedColumn } from "./Column";
 import { Query } from "./Query";
 import { Table } from "./Table";
+import { PrimitiveTypes } from "./types/IType";
 
 export type Scenario = {
   name: string;
@@ -23,126 +24,155 @@ function newScenario(name: string, tables: Table[], queries: Query[]): Scenario
 export class ScenarioParser {
   private _parsedYAML: string;
 
-  constructor(scenarioPath: string) {
-    this._parsedYAML = YAML.parse(open(scenarioPath));
+  constructor(yaml: string) {
+    this._parsedYAML = YAML.parse(yaml);
     this._validateScenario();
   }
 
   private _validateTag(tagName: string): void {
-    if (this._parsedYAML[tagName] !== undefined) {
-      if (this._parsedYAML[tagName] === null) throw new Error(`Missing ${tagName} tag value`);
-    } else {
-      throw new Error(`Missing ${tagName} tag`);
-    }
+    if (this._parsedYAML[tagName] === undefined) throw new Error(`Missing ${tagName} tag`);
+    if (this._parsedYAML[tagName] === null) throw new Error(`Missing ${tagName} tag value`);
   }
 
-  private _validateTableField(i: number, fieldName: string): void {
-    if (this._parsedYAML["tables_schema"][i][fieldName] !== undefined) {
-      if (this._parsedYAML["tables_schema"][i][fieldName] === null)
-        throw new Error(`Table ${i + 1}: Missing ${fieldName} value`);
-    } else {
+  private _validateTableField(i: number, fieldName: string, fieldType: string): void {
+    if (this._parsedYAML["tables_schema"][i][fieldName] === undefined) {
       throw new Error(`Table ${i + 1}: Missing ${fieldName} field`);
     }
+    if (this._parsedYAML["tables_schema"][i][fieldName] === null) {
+      throw new Error(`Table ${i + 1}: Missing ${fieldName} value`);
+    }
+    if (typeof this._parsedYAML["tables_schema"][i][fieldName] !== fieldType) {
+      throw new Error(`Table ${i + 1}: ${fieldName} field is not a ${fieldType}`);
+    }
   }
 
-  private _validateTableColumnField(i: number, j: number, columnName: string): void {
-    if (this._parsedYAML["tables_schema"][i]["columns"][j][columnName] !== undefined) {
-      if (this._parsedYAML["tables_schema"][i]["columns"][j][columnName] === null)
-        throw new Error(`Table ${i + 1}, Column ${j + 1}: Missing ${columnName} value`);
-    } else {
+  private _validateTableColumnField(i: number, j: number, columnName: string, columnType: string): void {
+    if (this._parsedYAML["tables_schema"][i]["columns"][j][columnName] === undefined) {
       throw new Error(`Table ${i + 1}, Column ${j + 1}: Missing ${columnName} field`);
     }
+    if (this._parsedYAML["tables_schema"][i]["columns"][j][columnName] === null) {
+      throw new Error(`Table ${i + 1}, Column ${j + 1}: Missing ${columnName} value`);
+    }
+    if (typeof this._parsedYAML["tables_schema"][i]["columns"][j][columnName] !== columnType) {
+      throw new Error(`Table ${i + 1}, Column ${j + 1}: ${columnName} field is not a ${columnType}`);
+    }
   }
 
-  private _validateQueriesField(i: number, fieldName: string): void {
-    if (this._parsedYAML["queries"][i][fieldName] !== undefined) {
-      if (this._parsedYAML["queries"][i][fieldName] === null)
-        throw new Error(`Query ${i + 1}: Missing ${fieldName} value`);
-    } else {
+  private _validateQueriesField(i: number, fieldName: string, fieldType: string): void {
+    if (this._parsedYAML["queries"][i][fieldName] === undefined) {
       throw new Error(`Query ${i + 1}: Missing ${fieldName} field`);
     }
+    if (this._parsedYAML["queries"][i][fieldName] === null) {
+      throw new Error(`Query ${i + 1}: Missing ${fieldName} value`);
+    }
+    if (typeof this._parsedYAML["queries"][i][fieldName] !== fieldType) {
+      throw new Error(`Query ${i + 1}: ${fieldName} field is not a ${fieldType}`);
+    }
   }
 
-  private _validateQueriesParamsTypesFields(i: number, j: number, fieldname: string): void {
-    if (this._parsedYAML["queries"][i]["params"][j][fieldname] !== undefined) {
-      if (this._parsedYAML["queries"][i]["params"][j][fieldname] === null) {
-        throw new Error(`Query ${i + 1}, Parameter ${j + 1}: Missing ${fieldname} value`);
-      }
-    } else {
-      throw new Error(`Query ${i + 1}, Parameter ${j + 1}: Missing ${fieldname} field`);
+  private _validateQueriesParamsTypesFields(i: number, j: number, fieldName: string, fieldType: string): void {
+    if (this._parsedYAML["queries"][i]["params"][j][fieldName] === undefined) {
+      throw new Error(`Query ${i + 1}, Parameter ${j + 1}: Missing ${fieldName} field`);
+    }
+    if (this._parsedYAML["queries"][i]["params"][j][fieldName] === null) {
+      throw new Error(`Query ${i + 1}, Parameter ${j + 1}: Missing ${fieldName} value`);
+    }
+    if (typeof this._parsedYAML["queries"][i]["params"][j][fieldName] !== fieldType) {
+      throw new Error(`Query ${i + 1}, Parameter ${j + 1}: ${fieldName} field is not a ${fieldType}`);
     }
   }
 
   private _validateQueriesParamsField(i: number, j: number): void {
-    if (this._parsedYAML["queries"][i]["params"][j] !== undefined) {
-      if (this._parsedYAML["queries"][i]["params"][j] !== null) {
-        if (this._parsedYAML["queries"][i]["params"][j]["value"] !== undefined) {
-          return;
-        } else if (this._parsedYAML["queries"][i]["params"][j]["type"] !== undefined) {
-          if (this._parsedYAML["queries"][i]["params"][j]["type"] !== null) {
-            this._validateQueriesParamsTypesFields(i, j, "distribution");
-            switch (this._parsedYAML["queries"][i]["params"][j]["type"].toUpperCase()) {
-              case "STRING":
-                this._validateQueriesParamsTypesFields(i, j, "range");
-                this._validateQueriesParamsTypesFields(i, j, "alphabet");
-                break;
-              case "UNSIGNED":
-              case "INTEGER":
-              case "DECIMAL":
-                this._validateQueriesParamsTypesFields(i, j, "range");
-                break;
-              case "BOOLEAN":
-                break;
-              default:
-                throw new Error(`Query ${i + 1}, Parameter ${j + 1}:: Unknown parameter type`);
-            }
-            this._validateQueriesParamsTypesFields(i, j, "is_nullable");
-            this._validateQueriesParamsTypesFields(i, j, "null_percentage");
-          } else {
-            throw new Error(`Query ${i + 1}, Parameter ${j + 1}: Missing type value`);
-          }
-        } else {
-          throw new Error(`Query ${i + 1}, Parameter ${j + 1}: Missing type field`);
-        }
-      } else {
-        throw new Error(`Query ${i + 1}, Parameter ${j + 1}: Missing value`);
-      }
-    } else {
+    if (this._parsedYAML["queries"][i]["params"][j] === undefined) {
       throw new Error(`Query ${i + 1}, Parameter ${j + 1}: Missing field`);
     }
+    if (this._parsedYAML["queries"][i]["params"][j] === null) {
+      throw new Error(`Query ${i + 1}, Parameter ${j + 1}: Missing value`);
+    }
+    //if element is predefined
+    if (this._parsedYAML["queries"][i]["params"][j]["value"] !== undefined) {
+      return;
+    }
+    //validate type class fields
+    this._validateQueriesParamsTypesFields(i, j, "type", "string");
+    switch (this._parsedYAML["queries"][i]["params"][j]["type"].toUpperCase()) {
+      case "STRING":
+        this._validateQueriesParamsTypesFields(i, j, "range", "object");
+        this._validateQueriesParamsTypesFields(i, j, "alphabet", "object");
+        break;
+      case "UNSIGNED":
+      case "INTEGER":
+      case "DECIMAL":
+        this._validateQueriesParamsTypesFields(i, j, "range", "object");
+        break;
+      case "BOOLEAN":
+        break;
+      default:
+        throw new Error(`Query ${i + 1}, Parameter ${j + 1}: Unsupported type`);
+    }
+    this._validateQueriesParamsTypesFields(i, j, "is_nullable", "boolean");
+    this._validateQueriesParamsTypesFields(i, j, "null_percentage", "number");
+    this._validateQueriesParamsTypesFields(i, j, "distribution", "string");
+    switch (this._parsedYAML["queries"][i]["params"][j]["distribution"].toUpperCase()) {
+      case "NORMAL":
+      case "UNIFORM":
+        break;
+      case "ZIPF":
+        this._validateQueriesParamsTypesFields(i, j, "distribution_param", "number");
+        break;
+      default:
+        throw new Error(`Query ${i + 1}, Parameter ${j + 1}: Unsupported distribution`);
+    }
   }
 
   private _validateScenario(): void {
+    //****************************************VALIDATE*SCENARIO*************************************************
     let primaryKeyColumnName: string;
     // validate scenario_name tag
     this._validateTag("scenario_name");
     // validate tables_schema tag
     this._validateTag("tables_schema");
-    // validate tables_schema fields
+    //****************************************VALIDATE*TABLES**************************************************
     for (let i: number = 0; i < this._parsedYAML["tables_schema"].length; i++) {
-      this._validateTableField(i, "name");
-      this._validateTableField(i, "row_count");
-      this._validateTableField(i, "columns");
-      this._validateTableField(i, "primary_key");
+      this._validateTableField(i, "name", "string");
+      this._validateTableField(i, "row_count", "number");
+      this._validateTableField(i, "columns", "object");
+      this._validateTableField(i, "primary_key", "string");
       primaryKeyColumnName = this._parsedYAML["tables_schema"][i]["primary_key"];
-      this._validateTableField(i, "distribution_key");
-      this._validateTableField(i, "timeout");
-      // validate table[i] columns
+      this._validateTableField(i, "distribution_key", "string");
+      this._validateTableField(i, "timeout", "number");
+      //************************************END*VALIDATE*TABLES**************************************************
+
+      //****************************************VALIDATE*COLUMNS*************************************************
       for (let j: number = 0; j < this._parsedYAML["tables_schema"][i]["columns"].length; j++) {
-        this._validateTableColumnField(i, j, "name");
-        this._validateTableColumnField(i, j, "type");
+        this._validateTableColumnField(i, j, "name", "string");
+        this._validateTableColumnField(i, j, "type", "string");
         // each type may own its unique fields
         switch (this._parsedYAML["tables_schema"][i]["columns"][j]["type"].toUpperCase()) {
           case "STRING":
-            this._validateTableColumnField(i, j, "range");
-            this._validateTableColumnField(i, j, "alphabet");
-            this._validateTableColumnField(i, j, "unique");
+            this._validateTableColumnField(i, j, "range", "object");
+            this._validateTableColumnField(i, j, "alphabet", "object");
             break;
           case "UNSIGNED":
           case "INTEGER":
           case "DECIMAL":
-            this._validateTableColumnField(i, j, "range");
-            this._validateTableColumnField(i, j, "unique");
+            this._validateTableColumnField(i, j, "range", "object");
+            break;
+          // Boolean type doesn't have unique fields
+          case "BOOLEAN":
+            break;
+          default:
+            throw new Error(`Table ${i + 1}, Column ${j + 1}: Unknown column type`);
+        }
+        //****************************************VALIDATE*DISTRIBUTIONS**************************************************
+        this._validateTableColumnField(i, j, "distribution", "string");
+        switch (this._parsedYAML["tables_schema"][i]["columns"][j]["distribution"].toUpperCase()) {
+          case "NORMAL":
+          case "UNIFORM":
+            if (this._parsedYAML["tables_schema"][i]["columns"][j]["type"].toUpperCase() === "BOOLEAN") {
+              break;
+            }
+            this._validateTableColumnField(i, j, "unique", "boolean");
             // Check if row_count is less or equal to items count from specified range
             if (
               this._parsedYAML["tables_schema"][i]["columns"][j]["unique"] === true &&
@@ -159,15 +189,15 @@ export class ScenarioParser {
               );
             }
             break;
-          // Boolean type doesn't have unique fields
-          case "BOOLEAN":
+          case "ZIPF":
+            this._validateTableColumnField(i, j, "distribution_param", "number");
             break;
           default:
-            throw new Error(`Table ${i + 1}, Column ${j + 1}: Unknown column type`);
+            throw new Error(`Table ${i + 1}, Column ${j + 1}: Unknown distribution name`);
         }
-        this._validateTableColumnField(i, j, "distribution");
-        this._validateTableColumnField(i, j, "is_nullable");
-        this._validateTableColumnField(i, j, "null_percentage");
+        //************************************END*VALIDATE*DISTRIBUTIONS**************************************************
+        this._validateTableColumnField(i, j, "is_nullable", "boolean");
+        this._validateTableColumnField(i, j, "null_percentage", "number");
         // Check if null_percentage equals zero if is_nullable is false
         if (
           this._parsedYAML["tables_schema"][i]["columns"][j]["is_nullable"] === false &&
@@ -185,29 +215,36 @@ export class ScenarioParser {
           }
         }
       }
-      // validate queries tag
+      //************************************END*VALIDATE*COLUMNS*************************************************
+
+      //****************************************VALIDATE*QUERIES*************************************************
       this._validateTag("queries");
       // validate queries fields
       for (let i: number = 0; i < this._parsedYAML["queries"].length; i++) {
-        this._validateQueriesField(i, "sql");
-        this._validateQueriesField(i, "params");
-        this._validateQueriesField(i, "weight");
-        if (typeof this._parsedYAML["queries"][i]["params"] === "object") {
-          if (this._parsedYAML["queries"][i]["params"].length === 0) {
-            continue;
-          } else if (this._parsedYAML["queries"][i]["params"].length > 0) {
-            for (let j: number = 0; j < this._parsedYAML["queries"][i]["params"].length; j++) {
-              this._validateQueriesParamsField(i, j);
-            }
+        this._validateQueriesField(i, "sql", "string");
+        this._validateQueriesField(i, "params", "object");
+        this._validateQueriesField(i, "weight", "number");
+        if (this._parsedYAML["queries"][i]["params"].length === 0) {
+          continue;
+        } else if (
+          (this._parsedYAML["queries"][i]["params"].length > 0 &&
+            this._parsedYAML["queries"][i]["params"][0]["type"] !== undefined) ||
+          this._parsedYAML["queries"][i]["params"][0]["value"] !== undefined
+        ) {
+          for (let j: number = 0; j < this._parsedYAML["queries"][i]["params"].length; j++) {
+            this._validateQueriesParamsField(i, j);
           }
         } else {
-          throw new Error(`Query ${i + 1}: Unexpected params content`);
+          throw new Error(`Query ${i + 1}: params field must contain predefined value or type fields`);
         }
       }
+      //************************************END*VALIDATE*QUERIES*************************************************
     }
+    //************************************END*VALIDATE*SCENARIO*************************************************
   }
-  private _parseColumns(i: number): AbstractColumn<string | number | boolean | null>[] {
-    const columns: AbstractColumn<string | number | boolean | null>[] = [];
+
+  private _parseColumns(i: number): AbstractColumn<PrimitiveTypes>[] {
+    const columns: AbstractColumn<PrimitiveTypes>[] = [];
 
     const tableColumns: string = this._parsedYAML["tables_schema"][i]["columns"];
 
@@ -219,11 +256,11 @@ export class ScenarioParser {
               tableColumns[j]["name"],
               tableColumns[j]["type"],
               tableColumns[j]["distribution"],
+              { unique: tableColumns[j]["unique"], parameter: tableColumns[j]["distribution_param"] },
               tableColumns[j]["range"],
               tableColumns[j]["alphabet"],
               tableColumns[j]["is_nullable"],
-              tableColumns[j]["null_percentage"],
-              tableColumns[j]["unique"]
+              tableColumns[j]["null_percentage"]
             )
           );
           break;
@@ -233,10 +270,10 @@ export class ScenarioParser {
               tableColumns[j]["name"],
               tableColumns[j]["type"],
               tableColumns[j]["distribution"],
+              { unique: tableColumns[j]["unique"], parameter: tableColumns[j]["distribution_param"] },
               tableColumns[j]["range"],
               tableColumns[j]["is_nullable"],
-              tableColumns[j]["null_percentage"],
-              tableColumns[j]["unique"]
+              tableColumns[j]["null_percentage"]
             )
           );
           break;
@@ -246,10 +283,10 @@ export class ScenarioParser {
               tableColumns[j]["name"],
               tableColumns[j]["type"],
               tableColumns[j]["distribution"],
+              { unique: tableColumns[j]["unique"], parameter: tableColumns[j]["distribution_param"] },
               tableColumns[j]["range"],
               tableColumns[j]["is_nullable"],
-              tableColumns[j]["null_percentage"],
-              tableColumns[j]["unique"]
+              tableColumns[j]["null_percentage"]
             )
           );
           break;
@@ -259,10 +296,10 @@ export class ScenarioParser {
               tableColumns[j]["name"],
               tableColumns[j]["type"],
               tableColumns[j]["distribution"],
+              { unique: tableColumns[j]["unique"], parameter: tableColumns[j]["distribution_param"] },
               tableColumns[j]["range"],
               tableColumns[j]["is_nullable"],
-              tableColumns[j]["null_percentage"],
-              tableColumns[j]["unique"]
+              tableColumns[j]["null_percentage"]
             )
           );
           break;
@@ -272,6 +309,7 @@ export class ScenarioParser {
               tableColumns[j]["name"],
               tableColumns[j]["type"],
               tableColumns[j]["distribution"],
+              { parameter: tableColumns[j]["distribution_param"] },
               tableColumns[j]["is_nullable"],
               tableColumns[j]["null_percentage"]
             )
@@ -306,7 +344,7 @@ export class ScenarioParser {
       if (query["weight"] < 0) {
         throw new Error(`Parser: Query ${query["sql"]} weight must be greater or equal zero`);
       }
-      const params: ((string | number | boolean | null) | AbstractColumn<string | number | boolean | null>)[] = [];
+      const params: (PrimitiveTypes | AbstractColumn<PrimitiveTypes>)[] = [];
       for (const param of query["params"]) {
         if (param["value"] !== undefined) params.push(param["value"]);
         else if (param["type"]) {
@@ -317,11 +355,11 @@ export class ScenarioParser {
                   "",
                   param["type"],
                   param["distribution"],
+                  { unique: false, parameter: param["distribution_param"] },
                   param["range"],
                   param["alphabet"],
                   param["is_nullable"],
-                  param["null_percentage"],
-                  false
+                  param["null_percentage"]
                 )
               );
               break;
@@ -331,10 +369,10 @@ export class ScenarioParser {
                   "",
                   param["type"],
                   param["distribution"],
+                  { unique: false, parameter: param["distribution_param"] },
                   param["range"],
                   param["is_nullable"],
-                  param["null_percentage"],
-                  false
+                  param["null_percentage"]
                 )
               );
               break;
@@ -344,10 +382,10 @@ export class ScenarioParser {
                   "",
                   param["type"],
                   param["distribution"],
+                  { unique: false, parameter: param["distribution_param"] },
                   param["range"],
                   param["is_nullable"],
-                  param["null_percentage"],
-                  false
+                  param["null_percentage"]
                 )
               );
               break;
@@ -357,10 +395,10 @@ export class ScenarioParser {
                   "",
                   param["type"],
                   param["distribution"],
+                  { unique: false, parameter: param["distribution_param"] },
                   param["range"],
                   param["is_nullable"],
-                  param["null_percentage"],
-                  false
+                  param["null_percentage"]
                 )
               );
               break;
@@ -370,6 +408,7 @@ export class ScenarioParser {
                   "",
                   param["type"],
                   param["distribution"],
+                  { parameter: param["distribution_param"] },
                   param["is_nullable"],
                   param["null_percentage"]
                 )
diff --git a/src/distributions/IDistribution.ts b/src/distributions/IDistribution.ts
index e660c60b9e3e5ec73eb55301305931bc1180d262..e4acdb4d7ed3610efd9e9cb2568321e3312c26f4 100644
--- a/src/distributions/IDistribution.ts
+++ b/src/distributions/IDistribution.ts
@@ -2,6 +2,11 @@ import Taus113PRNG from "../../third_party/randomjs/Taus113PRNG";
 import { IPRNG } from "../prng/IPRNG";
 import { IRange } from "../Range";
 
+export type DistributionOpts = {
+  unique?: boolean;
+  parameter?: number;
+};
+
 // Interface + Abstract class tandem is used to provide
 // single contract for all future Distribution classes.
 // Interfaces contains essential methods.
@@ -9,10 +14,10 @@ import { IRange } from "../Range";
 // that are common for each future child classes
 export interface IDistribution {
   readonly seed: number;
-  randomInt(range: IRange<number>): number;
-  randomFloat(range: IRange<number>): number;
-  randomIntArray(size: number, range: IRange<number>, unique: boolean): number[];
-  randomFloatArray(size: number, range: IRange<number>, unique: boolean): number[];
+  randomInt(range: IRange<number>, opts?: DistributionOpts): number;
+  randomFloat(range: IRange<number>, opts?: DistributionOpts): number;
+  randomIntArray(size: number, range: IRange<number>, opts?: DistributionOpts): number[];
+  randomFloatArray(size: number, range: IRange<number>, opts?: DistributionOpts): number[];
 }
 
 export abstract class AbstractDistribution implements IDistribution {
@@ -25,8 +30,8 @@ export abstract class AbstractDistribution implements IDistribution {
   }
 
   abstract get seed(): number;
-  abstract randomInt(range: IRange<number>): number;
-  abstract randomFloat(range: IRange<number>): number;
-  abstract randomIntArray(size: number, range: IRange<number>, unique: boolean): number[];
-  abstract randomFloatArray(size: number, range: IRange<number>, unique: boolean): number[];
+  abstract randomInt(range: IRange<number>, opts?: DistributionOpts): number;
+  abstract randomFloat(range: IRange<number>, opts?: DistributionOpts): number;
+  abstract randomIntArray(size: number, range: IRange<number>, opts?: DistributionOpts): number[];
+  abstract randomFloatArray(size: number, range: IRange<number>, opts?: DistributionOpts): number[];
 }
diff --git a/src/distributions/NormalDistribution.ts b/src/distributions/NormalDistribution.ts
index b32253ececfa771ed3ddab3bed93c6ab931dd55d..793328a66e90c9e6580f2fea96a5bd9bd2fb852a 100644
--- a/src/distributions/NormalDistribution.ts
+++ b/src/distributions/NormalDistribution.ts
@@ -1,5 +1,5 @@
 import { IRange } from "../Range";
-import { AbstractDistribution } from "./IDistribution";
+import { AbstractDistribution, DistributionOpts } from "./IDistribution";
 
 /**
  * Class generates normally distributed numbers in N(0,1) or within specified range.
@@ -76,7 +76,7 @@ export default class NormalDistribution extends AbstractDistribution {
     return Math.round(this.randomFloat(range));
   }
 
-  public randomFloatArray(size: number, range: IRange<number>, unique: boolean): number[] {
+  public randomFloatArray(size: number, range: IRange<number>, { unique }: DistributionOpts): number[] {
     if (unique) {
       const resultSet: Set<number> = new Set();
       while (resultSet.size < size) resultSet.add(this.randomFloat(range));
@@ -85,7 +85,7 @@ export default class NormalDistribution extends AbstractDistribution {
     return Array.from({ length: size }, () => this.randomFloat(range));
   }
 
-  public randomIntArray(size: number, range: IRange<number>, unique: boolean): number[] {
+  public randomIntArray(size: number, range: IRange<number>, { unique }: DistributionOpts): number[] {
     if (unique) {
       const resultSet: Set<number> = new Set();
       while (resultSet.size < size) {
diff --git a/src/distributions/UniformDistribution.ts b/src/distributions/UniformDistribution.ts
index f0630739aa8218008412f9bc3098c23e94d08a54..97dae186ec79444a7e559158f735cb58a45bff18 100644
--- a/src/distributions/UniformDistribution.ts
+++ b/src/distributions/UniformDistribution.ts
@@ -1,5 +1,5 @@
 import { IRange } from "../Range";
-import { AbstractDistribution } from "./IDistribution";
+import { AbstractDistribution, DistributionOpts } from "./IDistribution";
 
 /**
  * Class generates uniformly distributed numbers in N(0,1) or within specified range.
@@ -36,7 +36,7 @@ export default class UniformDistribution extends AbstractDistribution {
     return Math.round(this.randomFloat(range));
   }
 
-  public randomFloatArray(size: number, range: IRange<number>, unique: boolean): number[] {
+  public randomFloatArray(size: number, range: IRange<number>, { unique }: DistributionOpts): number[] {
     if (unique) {
       const resultSet: Set<number> = new Set();
       while (resultSet.size < size) resultSet.add(this.randomFloat(range));
@@ -45,7 +45,7 @@ export default class UniformDistribution extends AbstractDistribution {
     return Array.from({ length: size }, () => this.randomFloat(range));
   }
 
-  public randomIntArray(size: number, range: IRange<number>, unique: boolean): number[] {
+  public randomIntArray(size: number, range: IRange<number>, { unique }: DistributionOpts): number[] {
     if (unique) {
       const resultSet: Set<number> = new Set();
       while (resultSet.size < size) resultSet.add(this.randomInt(range));
diff --git a/src/distributions/ZipfDistribution.ts b/src/distributions/ZipfDistribution.ts
new file mode 100644
index 0000000000000000000000000000000000000000..a569836988a88a27b1878b5e503dc999609a45bd
--- /dev/null
+++ b/src/distributions/ZipfDistribution.ts
@@ -0,0 +1,82 @@
+import { IRange } from "../Range";
+import { AbstractDistribution, DistributionOpts } from "./IDistribution";
+
+export default class ZipfDistribution extends AbstractDistribution {
+  // Object, containing type name and pointer to distribution class instance
+  private static instances: { [name: string]: ZipfDistribution } = {};
+  private minZipfian: number = 1.1;
+  private maxZipfian: number = 1000.0;
+
+  constructor(seed: number) {
+    super(seed);
+  }
+
+  // Named singleton
+  // Each class type will use its own distribution generator
+  public static getInstance(seed: number, name: string): ZipfDistribution {
+    if (!ZipfDistribution.instances[name]) {
+      ZipfDistribution.instances[name] = new ZipfDistribution(seed);
+    }
+    return ZipfDistribution.instances[name];
+  }
+
+  /*
+   * Computing zipfian using rejection method, based on
+   * "Non-Uniform Random Variate Generation",
+   * Luc Devroye, p. 550-551, Springer 1986.
+   * Works for s > 1.0, but may perform badly for s very close to 1.0.
+   */
+  private _random(itemcount: number, zipfian: number): number {
+    const b: number = Math.pow(2.0, zipfian - 1.0);
+    let x: number = 0;
+    let t: number = 0;
+    let u: number = 0;
+    let v: number = 0;
+    if (itemcount <= 1) return 1;
+
+    // eslint-disable-next-line no-constant-condition
+    while (true) {
+      u = this._prng.next();
+      v = this._prng.next();
+      // Math.floor converts float to int here
+      // If you need to gen float numbers -> do not use Math.floor here
+      // And instead round returned value from this method
+      x = Math.floor(Math.pow(u, -1.0 / (zipfian - 1.0)));
+      t = Math.pow(1.0 - 1.0 / x, zipfian - 1.0);
+      if ((v * x * (t - 1.0)) / (b - 1.0) <= t / b && x <= itemcount) break;
+    }
+    return x;
+  }
+
+  public randomFloat(range: IRange<number>, { parameter }: DistributionOpts): number {
+    if (parameter) {
+      const itemcount: number = range.right - range.left + 1;
+      if (this.minZipfian > parameter || parameter > this.maxZipfian) {
+        throw new Error("ZipfDistribution : randomFloat: Please ensure, that zipfian value is in range [1.1, 1000.0]");
+      }
+      return range.left - 1 + this._random(itemcount, parameter);
+    } else {
+      throw new Error("ZipfDistribution : randomFloat: Please define zipfian parameter");
+    }
+  }
+
+  public randomInt(range: IRange<number>, { parameter }: DistributionOpts): number {
+    if (parameter) {
+      return Math.floor(this.randomFloat(range, { parameter }));
+    } else {
+      throw new Error("ZipfDistribution : randomInt: Please define zipfian parameter");
+    }
+  }
+
+  public randomFloatArray(size: number, range: IRange<number>, { parameter }: DistributionOpts): number[] {
+    return Array.from({ length: size }, () => this.randomFloat(range, { parameter }));
+  }
+
+  public randomIntArray(size: number, range: IRange<number>, { parameter }: DistributionOpts): number[] {
+    return Array.from({ length: size }, () => this.randomInt(range, { parameter }));
+  }
+
+  public get seed(): number {
+    return 1;
+  }
+}
diff --git a/src/scenario/template.yml b/src/scenario/template.yml
index bfeac1814c0351c01af1eff7ee68f52d0a60cf58..a4c3584964676ab645b7397aa6adbab8be6256fa 100644
--- a/src/scenario/template.yml
+++ b/src/scenario/template.yml
@@ -31,12 +31,19 @@ tables_schema:
         type: Decimal
         distribution: Normal
         range: [-100.5, 100.5]
-        is_nullable: true
-        null_percentage: 25
+        is_nullable: false
+        null_percentage: 0
         unique: false
       - name: stock
         type: Boolean
         distribution: Normal
+        is_nullable: true
+        null_percentage: 50
+      - name: frequencies
+        type: Unsigned
+        distribution: Zipf
+        distribution_param: 1.3
+        range: [0, 10]
         is_nullable: false
         null_percentage: 0
     primary_key: id
@@ -45,7 +52,8 @@ tables_schema:
 
 # Template SQL queries with parameters and weights
 queries:
-  - sql: select sum("id") from "cars"
+    # bug: select sum("id") from "cars"
+  - sql: select "id" from "cars"
     params: []
     weight: 33
   - sql: select count("id") from "cars" where "id" = ?
@@ -57,7 +65,7 @@ queries:
       - value: 5
       - value: true
     weight: 60
-  - sql: select * from "cars" where "score" = ? and "rating" = ? and and "id" = ? and "brand" = ?
+  - sql: select * from "cars" where "score" = ? and "rating" = ? and and "id" = ? and "brand" = ? and "frequencies" = ?
     params: 
       - value: null #blank value also interpetiers as null
       - value: -5
@@ -72,4 +80,10 @@ queries:
         alphabet: ["en"]
         is_nullable: false
         null_percentage: 0
+      - type: Unsigned
+        distribution: Zipf
+        distribution_param: 1.3
+        range: [0, 10]
+        is_nullable: false
+        null_percentage: 0
     weight: 66
diff --git a/src/types/Boolean.ts b/src/types/Boolean.ts
index e142a281083f74e6bca139fca055cf290a0d6799..856cb1a80bce900d988d6b58ded765359252b70e 100644
--- a/src/types/Boolean.ts
+++ b/src/types/Boolean.ts
@@ -1,4 +1,4 @@
-import { IDistribution } from "../distributions/IDistribution";
+import { DistributionOpts, IDistribution } from "../distributions/IDistribution";
 import UniformDistribution from "../distributions/UniformDistribution";
 import { IRange, Range } from "../Range";
 import Replacer from "../Replacer";
@@ -28,12 +28,12 @@ export class BooleanType extends AbstractTypeArray<boolean> {
     return BooleanType.instance;
   }
 
-  public generateArrayWithNull(size: number, nullPercentage: number): (boolean | null)[] {
+  public generateArrayWithNull(size: number, nullPercentage: number, opts: DistributionOpts): (boolean | null)[] {
     const booleanNullArray: (boolean | null)[] = Array.from({ length: size }, () =>
-      this._distribution.randomInt(this._range) === 1 ? true : false
+      this._distribution.randomInt(this._range, opts) === 1 ? true : false
     );
 
-    new Replacer(new UniformDistribution(this._distribution.seed), nullPercentage).replaceWithValue(
+    new Replacer<boolean, null>(new UniformDistribution(this._distribution.seed), nullPercentage).replaceWithValue(
       booleanNullArray,
       null
     );
@@ -41,7 +41,7 @@ export class BooleanType extends AbstractTypeArray<boolean> {
     return booleanNullArray;
   }
 
-  public generateArrayWithoutNull(size: number): boolean[] {
-    return Array.from({ length: size }, () => (this._distribution.randomInt(this._range) === 1 ? true : false));
+  public generateArrayWithoutNull(size: number, opts: DistributionOpts): boolean[] {
+    return Array.from({ length: size }, () => (this._distribution.randomInt(this._range, opts) === 1 ? true : false));
   }
 }
diff --git a/src/types/Decimal.ts b/src/types/Decimal.ts
index 044eab5844edd08051421d048eb7d4186e1cbb13..b2ebc5e7f34c61b2b74677054014e06e3d54126b 100644
--- a/src/types/Decimal.ts
+++ b/src/types/Decimal.ts
@@ -1,4 +1,4 @@
-import { IDistribution } from "../distributions/IDistribution";
+import { DistributionOpts, IDistribution } from "../distributions/IDistribution";
 import UniformDistribution from "../distributions/UniformDistribution";
 import { IRange, Range } from "../Range";
 import Replacer from "../Replacer";
@@ -40,14 +40,17 @@ export class DecimalType extends AbstractTypeArray<number> {
     return DecimalType.instance;
   }
 
-  public generateArrayWithNull(size: number, nullPercentage: number, unique: boolean): (number | null)[] {
-    const decimalArray: (number | null)[] = this._distribution.randomFloatArray(size, this._range, unique);
-    new Replacer(new UniformDistribution(this._distribution.seed), nullPercentage).replaceWithValue(decimalArray, null);
+  public generateArrayWithNull(size: number, nullPercentage: number, opts: DistributionOpts): (number | null)[] {
+    const decimalArray: (number | null)[] = this._distribution.randomFloatArray(size, this._range, opts);
+    new Replacer<number, null>(new UniformDistribution(this._distribution.seed), nullPercentage).replaceWithValue(
+      decimalArray,
+      null
+    );
 
     return decimalArray;
   }
 
-  public generateArrayWithoutNull(size: number, unique: boolean): number[] {
-    return this._distribution.randomFloatArray(size, this._range, unique);
+  public generateArrayWithoutNull(size: number, opts: DistributionOpts): number[] {
+    return this._distribution.randomFloatArray(size, this._range, opts);
   }
 }
diff --git a/src/types/IType.ts b/src/types/IType.ts
index ec58f9624e407bc5cd944dcaf71a7e77f166de15..ae7a6b38ce27520654499466e76387c47f028481 100644
--- a/src/types/IType.ts
+++ b/src/types/IType.ts
@@ -1,10 +1,10 @@
-import { IDistribution } from "../distributions/IDistribution";
+import { DistributionOpts, IDistribution } from "../distributions/IDistribution";
 
 export type PrimitiveTypes = string | number | boolean | null;
 
 export interface ITypeArray<T> {
-  generateArrayWithNull(size: number, nullPercentage: number, unique?: boolean): (T | null)[];
-  generateArrayWithoutNull(size: number, unique?: boolean): T[];
+  generateArrayWithNull(size: number, nullPercentage: number, opts?: DistributionOpts): (T | null)[];
+  generateArrayWithoutNull(size: number, opts?: DistributionOpts): T[];
 }
 
 export abstract class AbstractTypeArray<T> implements ITypeArray<T> {
@@ -13,6 +13,6 @@ export abstract class AbstractTypeArray<T> implements ITypeArray<T> {
   constructor(distribution: IDistribution) {
     this._distribution = distribution;
   }
-  abstract generateArrayWithNull(size: number, nullPercentage: number, unique?: boolean): (T | null)[];
-  abstract generateArrayWithoutNull(size: number, unique?: boolean): T[];
+  abstract generateArrayWithNull(size: number, nullPercentage: number, opts?: DistributionOpts): (T | null)[];
+  abstract generateArrayWithoutNull(size: number, opts?: DistributionOpts): T[];
 }
diff --git a/src/types/SignedInt.ts b/src/types/SignedInt.ts
index 322a587d870cec379df2fb10f31f89f0a863397e..d1f623299eaac81b5968865f87e2b1871b33d941 100644
--- a/src/types/SignedInt.ts
+++ b/src/types/SignedInt.ts
@@ -1,4 +1,4 @@
-import { IDistribution } from "../distributions/IDistribution";
+import { DistributionOpts, IDistribution } from "../distributions/IDistribution";
 import UniformDistribution from "../distributions/UniformDistribution";
 import { IRange, Range } from "../Range";
 import Replacer from "../Replacer";
@@ -39,9 +39,9 @@ export class SignedIntType extends AbstractTypeArray<number> {
     return SignedIntType.instance;
   }
 
-  public generateArrayWithNull(size: number, nullPercentage: number, unique: boolean): (number | null)[] {
-    const signedNullArray: (number | null)[] = this._distribution.randomIntArray(size, this._range, unique);
-    new Replacer(new UniformDistribution(this._distribution.seed), nullPercentage).replaceWithValue(
+  public generateArrayWithNull(size: number, nullPercentage: number, opts: DistributionOpts): (number | null)[] {
+    const signedNullArray: (number | null)[] = this._distribution.randomIntArray(size, this._range, opts);
+    new Replacer<number, null>(new UniformDistribution(this._distribution.seed), nullPercentage).replaceWithValue(
       signedNullArray,
       null
     );
@@ -49,7 +49,7 @@ export class SignedIntType extends AbstractTypeArray<number> {
     return signedNullArray;
   }
 
-  public generateArrayWithoutNull(size: number, unique: boolean): number[] {
-    return this._distribution.randomIntArray(size, this._range, unique);
+  public generateArrayWithoutNull(size: number, opts: DistributionOpts): number[] {
+    return this._distribution.randomIntArray(size, this._range, opts);
   }
 }
diff --git a/src/types/String.ts b/src/types/String.ts
index 6cb19d6dcc1bf0cfc6305840e3ae1c1ea5ff1603..71465e611e8c31145e7e152ea32f07088fa7d7b1 100644
--- a/src/types/String.ts
+++ b/src/types/String.ts
@@ -1,6 +1,6 @@
 import { Alphabet, IAlphabet } from "../Alphabet";
 import { Cutter, ICutter } from "../Cutter";
-import { IDistribution } from "../distributions/IDistribution";
+import { DistributionOpts, IDistribution } from "../distributions/IDistribution";
 import UniformDistribution from "../distributions/UniformDistribution";
 import { IRanges, Ranges } from "../Range";
 import Replacer from "../Replacer";
@@ -47,14 +47,17 @@ export class StringType extends AbstractTypeArray<string> {
     return StringType.instance;
   }
 
-  public generateArrayWithNull(size: number, nullPercentage: number, unique: boolean): (string | null)[] {
+  public generateArrayWithNull(size: number, nullPercentage: number, { unique }: DistributionOpts): (string | null)[] {
     const stringArray: (string | null)[] = this._wordCutter.generateWords(size, unique);
-    new Replacer(new UniformDistribution(this._distribution.seed), nullPercentage).replaceWithValue(stringArray, null);
+    new Replacer<string, null>(new UniformDistribution(this._distribution.seed), nullPercentage).replaceWithValue(
+      stringArray,
+      null
+    );
 
     return stringArray;
   }
 
-  public generateArrayWithoutNull(size: number, unique: boolean): string[] {
+  public generateArrayWithoutNull(size: number, { unique }: DistributionOpts): string[] {
     const stringArray: string[] = this._wordCutter.generateWords(size, unique);
 
     return stringArray;
diff --git a/src/types/UnsignedInt.ts b/src/types/UnsignedInt.ts
index 7f193fa04b337a3569a47633c5fca1fc47ea3747..59f4a65bc5e26f8944a7e98d1a10660e8972e603 100644
--- a/src/types/UnsignedInt.ts
+++ b/src/types/UnsignedInt.ts
@@ -1,4 +1,4 @@
-import { IDistribution } from "../distributions/IDistribution";
+import { DistributionOpts, IDistribution } from "../distributions/IDistribution";
 import UniformDistribution from "../distributions/UniformDistribution";
 import { IRange, Range } from "../Range";
 import Replacer from "../Replacer";
@@ -36,10 +36,10 @@ export class UnsignedIntType extends AbstractTypeArray<number> {
     return UnsignedIntType.instance;
   }
 
-  public generateArrayWithNull(size: number, nullPercentage: number, unique: boolean): (number | null)[] {
-    const unsignedNullArray: (number | null)[] = this._distribution.randomIntArray(size, this._range, unique);
+  public generateArrayWithNull(size: number, nullPercentage: number, opts: DistributionOpts): (number | null)[] {
+    const unsignedNullArray: (number | null)[] = this._distribution.randomIntArray(size, this._range, opts);
 
-    new Replacer(new UniformDistribution(this._distribution.seed), nullPercentage).replaceWithValue(
+    new Replacer<number, null>(new UniformDistribution(this._distribution.seed), nullPercentage).replaceWithValue(
       unsignedNullArray,
       null
     );
@@ -47,7 +47,7 @@ export class UnsignedIntType extends AbstractTypeArray<number> {
     return unsignedNullArray;
   }
 
-  public generateArrayWithoutNull(size: number, unique: boolean): number[] {
-    return this._distribution.randomIntArray(size, this._range, unique);
+  public generateArrayWithoutNull(size: number, opts: DistributionOpts): number[] {
+    return this._distribution.randomIntArray(size, this._range, opts);
   }
 }
diff --git a/test/integration/ReplaceWithNull.test.ts b/test/integration/ReplaceWithNull.test.ts
index 2594b630ecfa69ce2783fe0478c54299bec9d361..8a442704058a80bf1e6af8e8bd0a6f72ebefb738 100644
--- a/test/integration/ReplaceWithNull.test.ts
+++ b/test/integration/ReplaceWithNull.test.ts
@@ -4,6 +4,7 @@ import { expect } from "chai";
 
 import { suite, test } from "@testdeck/mocha";
 
+import { DistributionOpts } from "../../src/distributions/IDistribution";
 import NormalDistribution from "../../src/distributions/NormalDistribution";
 import UniformDistribution from "../../src/distributions/UniformDistribution";
 import Replacer from "../../src/Replacer";
@@ -16,20 +17,20 @@ class ReplaceWithNullTest {
   private seed: number;
   private arraySize: number;
   private nullPercentage: number;
-  private unique: boolean;
+  private opts: DistributionOpts;
 
   before() {
     this.seed = 12345678;
     this.arraySize = 100;
     this.nullPercentage = 50;
-    this.unique = false;
+    this.opts = { unique: false };
   }
 
   @test
   fillStringArrayOfCertainSizeWithNullElementsByUniformDistribution() {
     const numberArray: number[] = new UnsignedIntType(new NormalDistribution(this.seed)).generateArrayWithoutNull(
       this.arraySize,
-      this.unique
+      this.opts
     );
     this.replacer = new Replacer(new UniformDistribution(this.seed), this.nullPercentage);
     this.replacer.replaceWithValue(numberArray as (number | null)[], null);
@@ -47,7 +48,7 @@ class ReplaceWithNullTest {
   fillStringArrayOfCertainSizeWithNullElementsByNormalDistribution() {
     const numberArray: number[] = new UnsignedIntType(new NormalDistribution(this.seed)).generateArrayWithoutNull(
       this.arraySize,
-      this.unique
+      this.opts
     );
     this.replacer = new Replacer(new NormalDistribution(this.seed), this.nullPercentage);
     this.replacer.replaceWithValue(numberArray as (number | null)[], null);
diff --git a/test/k6/ScenarioParser.test.ts b/test/k6/ScenarioParser.test.ts
index 61ad94a367a97ba66fe400c7b550df9b828c3f61..dff31da2c58819eaecca408aad1c535d740ded29 100644
--- a/test/k6/ScenarioParser.test.ts
+++ b/test/k6/ScenarioParser.test.ts
@@ -3,49 +3,287 @@ import { describe, expect } from "https://jslib.k6.io/k6chaijs/4.3.4.3/index.js"
 
 import { Scenario, ScenarioParser } from "../../src/ScenarioParser";
 
-const parsedScenario: Scenario = new ScenarioParser("../test/k6/mockScenario.yml").parse();
 // prettier-ignore
 export default () => {
-  const scenarioPath: string = "../test/k6/mockScenario.yml";
-  describe("Parse main fields", () => {
-    expect(parsedScenario.name).to.equal("MOCK");
-    expect(parsedScenario.tables.length).to.equal(2);
-    expect(parsedScenario.queries.length).to.equal(2);
+  describe("Throw if scenario file is empty", () => {
+    const yaml: string = ``;
+    expect(()=>new ScenarioParser(yaml).parse()).to.throw(Error, "Missing scenario_name tag");
   });
 
-  describe("Parse tables_schema fields", () => {
-    expect(parsedScenario.tables[0].name).to.equal("mock_table_1");
-    expect(parsedScenario.tables[0].rowCount).to.equal(10);
-    expect(parsedScenario.tables[0].columns.length).to.equal(3);
-    expect(parsedScenario.tables[0].primaryKey).to.equal("unsigned_col");
-    expect(parsedScenario.tables[0].distributionKey).to.equal("unsigned_col");
-    expect(parsedScenario.tables[0].timeout).to.equal(3.0);
-    expect(parsedScenario.tables[1].name).to.equal("mock_table_2");
-    expect(parsedScenario.tables[1].rowCount).to.equal(5);
-    expect(parsedScenario.tables[1].columns.length).to.equal(1);
-    expect(parsedScenario.tables[1].primaryKey).to.equal("integer_col");
-    expect(parsedScenario.tables[1].distributionKey).to.equal("integer_col");
-    expect(parsedScenario.tables[1].timeout).to.equal(3.0);
-  });
+  describe("Validate fields", ()=>{
+    describe("Throw: missing field", ()=>{
+      const yaml: stirng = `
+        scenario_name: MOCK
+        
+        tables_schema:
+          - name: mock_table_1
+            row_count: 10
+            columns:
+              - name: unsigned_col
+                type: Unsigned
+                distribution: Normal
+                range: [0, 100]
+                is_nullable: false
+                null_percentage: 0
+            primary_key: unsigned_col
+            distribution_key: unsigned_col
+            timeout: 3.0
+        
+        # Template SQL queries with parameters and weights
+        queries:
+          - sql: select * from "mock_table_1"
+            params: []
+            weight: 50`
+      expect(()=>new ScenarioParser(yaml).parse()).to.throw(Error, "Table 1, Column 1: Missing unique field");
+    });
 
-  describe("Parse columns fields", () => {
-    expect(parsedScenario.tables[0].columns[0].name).to.equal("unsigned_col");
-    expect(parsedScenario.tables[0].columns[0].type).to.equal("Unsigned");
-    expect(parsedScenario.tables[0].columns[0].distribution).to.equal("Normal");
-    expect(parsedScenario.tables[0].columns[0].range).to.deep.equal([0,100]);
-    expect(parsedScenario.tables[0].columns[0].isNullable).to.equal(false);
-    expect(parsedScenario.tables[0].columns[0].nullPercentage).to.equal(0);
-    expect(parsedScenario.tables[0].columns[0].unique).to.equal(true);
-    expect(parsedScenario.tables[0].columns[1].name).to.equal("string_col");
-    expect(parsedScenario.tables[0].columns[1].alphabet).to.deep.equal(["en"]);
-  });
+    describe("Throw: missing field value", ()=>{
+      const yaml: stirng = `
+      scenario_name: MOCK
+      
+      tables_schema:
+        - name: mock_table_1
+          row_count: 10
+          columns:
+            - name: unsigned_col
+              type: Unsigned
+              distribution: Normal
+              range: [0, 100]
+              is_nullable: false
+              null_percentage: 0
+              unique:
+          primary_key: unsigned_col
+          distribution_key: unsigned_col
+          timeout: 3.0
+      
+      # Template SQL queries with parameters and weights
+      queries:
+        - sql: select * from "mock_table_1"
+          params: []
+          weight: 50`
+    expect(()=>new ScenarioParser(yaml).parse()).to.throw(Error, "Table 1, Column 1: Missing unique value");
+    });
 
-  describe("Parse queries fields", () => {
-    expect(parsedScenario.queries[0].sql).to.equal(`select * from "mock_table_1"`);
-    expect(parsedScenario.queries[0].params).to.deep.equal([]);
-    expect(parsedScenario.queries[0].weight).to.equal(50);
-    expect(parsedScenario.queries[1].sql).to.equal(`select count("unsigned_col") from "mock_table_1" where "boolean_col" = ?`);
-    expect(parsedScenario.queries[1].params[0]).to.deep.equal(true);
-    expect(parsedScenario.queries[1].weight).to.equal(100);
+    describe("Throw: inpropriate field value type", ()=>{
+      const yaml: stirng = `
+        scenario_name: MOCK
+        
+        tables_schema:
+          - name: mock_table_1
+            row_count: 10
+            columns:
+              - name: unsigned_col
+                type: Unsigned
+                distribution: Normal
+                range: [0, 100]
+                is_nullable: false
+                null_percentage: 0
+                unique: "true"
+            primary_key: unsigned_col
+            distribution_key: unsigned_col
+            timeout: 3.0
+        
+        # Template SQL queries with parameters and weights
+        queries:
+          - sql: select * from "mock_table_1"
+            params: []
+            weight: 50`
+      expect(()=>new ScenarioParser(yaml).parse()).to.throw(Error, "Table 1, Column 1: unique field is not a boolean");
+      });
+      
+      describe("Throw: wrong query params field value", ()=>{
+        const yaml: stirng = `
+          scenario_name: MOCK
+          
+          tables_schema:
+            - name: mock_table_1
+              row_count: 10
+              columns:
+                - name: unsigned_col
+                  type: Unsigned
+                  distribution: Normal
+                  range: [0, 100]
+                  is_nullable: false
+                  null_percentage: 0
+                  unique: true
+              primary_key: unsigned_col
+              distribution_key: unsigned_col
+              timeout: 3.0
+          
+          # Template SQL queries with parameters and weights
+          queries:
+            - sql: select * from "mock_table_1"
+              params: 12
+              weight: 50`
+        expect(()=>new ScenarioParser(yaml).parse()).to.throw(Error, "Query 1: params field is not a object");
+      });
+
+      describe("Throw: wrong use of query params field", ()=>{
+        const yaml: stirng = `
+          scenario_name: MOCK
+          
+          tables_schema:
+            - name: mock_table_1
+              row_count: 10
+              columns:
+                - name: unsigned_col
+                  type: Unsigned
+                  distribution: Normal
+                  range: [0, 100]
+                  is_nullable: false
+                  null_percentage: 0
+                  unique: true
+              primary_key: unsigned_col
+              distribution_key: unsigned_col
+              timeout: 3.0
+          
+          # Template SQL queries with parameters and weights
+          queries:
+            - sql: select * from "mock_table_1"
+              params: [12]
+              weight: 50`
+        expect(()=>new ScenarioParser(yaml).parse()).to.throw(Error, "Query 1: params field must contain predefined value or type fields");
+      });
+      
+      describe("Throw: incomplete query params field value", ()=>{
+        const yaml: stirng = `
+          scenario_name: MOCK
+          
+          tables_schema:
+            - name: mock_table_1
+              row_count: 10
+              columns:
+                - name: unsigned_col
+                  type: Unsigned
+                  distribution: Normal
+                  range: [0, 100]
+                  is_nullable: false
+                  null_percentage: 0
+                  unique: true
+              primary_key: unsigned_col
+              distribution_key: unsigned_col
+              timeout: 3.0
+          
+          # Template SQL queries with parameters and weights
+          queries:
+            - sql: select * from "mock_table_1"
+              params:
+                - type: Unsigned
+              weight: 50`
+        expect(()=>new ScenarioParser(yaml).parse()).to.throw();
+      });
   });
+
+  describe("Parse full scenario file", () => {
+    const yaml: stirng = `
+    scenario_name: MOCK
+    
+    tables_schema:
+      - name: mock_table_1
+        row_count: 10
+        columns:
+          - name: unsigned_col
+            type: Unsigned
+            distribution: Normal
+            range: [0, 100]
+            is_nullable: false
+            null_percentage: 0
+            unique: true
+          - name: string_col
+            type: String
+            distribution: Uniform
+            range: [4, 7]
+            alphabet: ["en"]
+            is_nullable: false
+            null_percentage: 0
+            unique: false
+          - name: boolean_col
+            type: Boolean
+            distribution: Zipf
+            distribution_param: 1.3
+            is_nullable: false
+            null_percentage: 0
+        primary_key: unsigned_col
+        distribution_key: unsigned_col
+        timeout: 3.0
+      - name: mock_table_2
+        row_count: 5
+        columns:
+          - name: integer_col
+            type: Integer
+            distribution: Normal
+            range: [0, 100]
+            is_nullable: false
+            null_percentage: 0
+            unique: true
+        primary_key: integer_col
+        distribution_key: integer_col
+        timeout: 3.0
+    
+    # Template SQL queries with parameters and weights
+    queries:
+      - sql: select * from "mock_table_1"
+        params: []
+        weight: 50
+      - sql: select count("unsigned_col") from "mock_table_1" where "boolean_col" = ?
+        params: 
+          - value: true
+        weight: 100
+      - sql: select count("unsigned_col") from "mock_table_1" where "boolean_col" = ?
+        params: 
+          - type: Unsigned
+            distribution: Zipf
+            distribution_param: 1.3
+            range: [0, 10]
+            is_nullable: false
+            null_percentage: 0
+        weight: 150`
+    const parsedScenario: Scenario = new ScenarioParser(yaml).parse();
+    
+    describe("Parse main fields", () => {
+      expect(parsedScenario.name).to.equal("MOCK");
+      expect(parsedScenario.tables.length).to.equal(2);
+      expect(parsedScenario.queries.length).to.equal(3);
+    });
+
+    describe("Parse tables_schema fields", () => {
+      expect(parsedScenario.tables[0].name).to.equal("mock_table_1");
+      expect(parsedScenario.tables[0].rowCount).to.equal(10);
+      expect(parsedScenario.tables[0].columns.length).to.equal(3);
+      expect(parsedScenario.tables[0].primaryKey).to.equal("unsigned_col");
+      expect(parsedScenario.tables[0].distributionKey).to.equal("unsigned_col");
+      expect(parsedScenario.tables[0].timeout).to.equal(3.0);
+      expect(parsedScenario.tables[1].name).to.equal("mock_table_2");
+      expect(parsedScenario.tables[1].rowCount).to.equal(5);
+      expect(parsedScenario.tables[1].columns.length).to.equal(1);
+      expect(parsedScenario.tables[1].primaryKey).to.equal("integer_col");
+      expect(parsedScenario.tables[1].distributionKey).to.equal("integer_col");
+      expect(parsedScenario.tables[1].timeout).to.equal(3.0);
+    });
+
+    describe("Parse columns fields", () => {
+      expect(parsedScenario.tables[0].columns[0].name).to.equal("unsigned_col");
+      expect(parsedScenario.tables[0].columns[0].type).to.equal("Unsigned");
+      expect(parsedScenario.tables[0].columns[0].distribution).to.equal("Normal");
+      expect(parsedScenario.tables[0].columns[0].range).to.deep.equal([0,100]);
+      expect(parsedScenario.tables[0].columns[0].isNullable).to.equal(false);
+      expect(parsedScenario.tables[0].columns[0].nullPercentage).to.equal(0);
+      expect(parsedScenario.tables[0].columns[0].distributionOpts.unique).to.equal(true);
+      expect(parsedScenario.tables[0].columns[1].name).to.equal("string_col");
+      expect(parsedScenario.tables[0].columns[1].alphabet).to.deep.equal(["en"]);
+      expect(parsedScenario.tables[0].columns[2].distributionOpts.parameter).to.equal(1.3);
+    });
+
+    describe("Parse queries fields", () => {
+      expect(parsedScenario.queries[0].sql).to.equal(`select * from "mock_table_1"`);
+      expect(parsedScenario.queries[0].params).to.deep.equal([]);
+      expect(parsedScenario.queries[0].weight).to.equal(50);
+      expect(parsedScenario.queries[1].sql).to.equal(`select count("unsigned_col") from "mock_table_1" where "boolean_col" = ?`);
+      expect(parsedScenario.queries[1].params[0]).to.deep.equal(true);
+      expect(parsedScenario.queries[1].weight).to.equal(100);
+      expect(parsedScenario.queries[2].params[0].type).to.equal("Unsigned");
+      expect(parsedScenario.queries[2].params[0].distribution).to.equal("Zipf");
+      expect(parsedScenario.queries[2].params[0].distributionOpts.parameter).to.equal(1.3);
+    });
+});
 };
diff --git a/test/k6/Singleton.test.ts b/test/k6/Singleton.test.ts
index 49fcd5c2f705223b027756f7bf6e68049b4423fe..fdb4e0bba1c153af7621dddfda0d1d0c344ca8a2 100644
--- a/test/k6/Singleton.test.ts
+++ b/test/k6/Singleton.test.ts
@@ -9,30 +9,30 @@ export default () => {
   const seed: number = 123456789;
 
   describe("Generate different data for 2 similar columns", () => {
-    const stringCol1: StringColumn = new StringColumn("", "String", "NORMAL", [1, 2], ["en"], false, 0, false);
+    const stringCol1: StringColumn = new StringColumn("", "String", "NORMAL", {unique: false}, [1, 2], ["en"], false, 0);
     const genStringCol1: string[] = stringCol1.generateData(seed, size, true);
 
-    const stringCol2: StringColumn = new StringColumn("", "String", "NORMAL", [1, 2], ["en"], false, 0, false);
+    const stringCol2: StringColumn = new StringColumn("", "String", "NORMAL", {unique: false}, [1, 2], ["en"], false, 0);
     const genStringCol2: string[] = stringCol2.generateData(seed, size, true);
     
     expect(genStringCol1).to.not.deep.equal(genStringCol2);
   });
 
   describe("Generate same data for singleton (tableCol) and obeject (sql parameter)", () => {
-    const stringCol1: DecimalColumn = new DecimalColumn("", "Decimal", "NORMAL", [1, 15], false, 0, false);
+    const stringCol1: DecimalColumn = new DecimalColumn("", "Decimal", "NORMAL", {unique: false}, [1, 15], false, 0);
     const genStringCol1: number[] = stringCol1.generateData(seed, size, true);
 
-    const stringCol2: DecimalColumn = new DecimalColumn("", "Decimal", "NORMAL", [1, 15], false, 0, false);
+    const stringCol2: DecimalColumn = new DecimalColumn("", "Decimal", "NORMAL", {unique: false}, [1, 15], false, 0);
     const genStringCol2: number[] = stringCol2.generateData(seed, size, false);
     
     expect(genStringCol1).to.deep.equal(genStringCol2);
   });
 
   describe("Generate same data for 2 sql parameters", () => {
-    const stringCol1: StringColumn = new StringColumn("", "", "NORMAL", [3, 7], ["en"], false, 0, false);
+    const stringCol1: StringColumn = new StringColumn("", "", "NORMAL", {unique: false},[3, 7], ["en"], false, 0);
     const genStringCol1: string[] = stringCol1.generateData(seed, size, false);
 
-    const stringCol2: StringColumn = new StringColumn("", "", "NORMAL", [3, 7], ["en"], false, 0, false);
+    const stringCol2: StringColumn = new StringColumn("", "", "NORMAL", {unique: false}, [3, 7], ["en"], false, 0);
     const genStringCol2: string[] = stringCol2.generateData(seed, size, false);
     
     expect(genStringCol1).to.deep.equal(genStringCol2);
diff --git a/test/k6/TypesGeneration.test.ts b/test/k6/TypesGeneration.test.ts
index 248e4c80ffc549c38448d9e951819055060bec04..8d0c8b137f4e629463e8114f5efd11e79e508278 100644
--- a/test/k6/TypesGeneration.test.ts
+++ b/test/k6/TypesGeneration.test.ts
@@ -14,54 +14,54 @@ export default () => {
   const seed: number = 123456789;
 
   describe("Generate String array", () => {
-    const stringType = new StringType(new NormalDistribution(seed), [3, 7], ["en", "ru"]).generateArrayWithoutNull(size, true);
+    const stringType = new StringType(new NormalDistribution(seed), [3, 7], ["en", "ru"]).generateArrayWithoutNull(size, {unique: true});
     const expectedStringType = ["pTrй","iйuЖ","zAqОЧ","лЩРФД","Зzнд","ЛРБpdmЦ","жАiv","iЪЩп","ХSСвИ","ШБЧyЙЛ"];
     expect(stringType).to.deep.equal(expectedStringType);
     
-    const stringTypeNull = new StringType(new NormalDistribution(seed), [3, 7], ["en", "ru"]).generateArrayWithNull(size, nullPerc, true);
+    const stringTypeNull = new StringType(new NormalDistribution(seed), [3, 7], ["en", "ru"]).generateArrayWithNull(size, nullPerc, {unique: true});
     const expectedStringTypeNull = [null,"iйuЖ","zAqОЧ",null,null,"ЛРБpdmЦ",null,null,"ХSСвИ","ШБЧyЙЛ"];
     expect(stringTypeNull).to.deep.equal(expectedStringTypeNull);
   });
 
   describe("Generate UnsignedInt array", () => {
-    const unsignedIntType = new UnsignedIntType(new NormalDistribution(seed), [100, 300]).generateArrayWithoutNull(size, false);
+    const unsignedIntType = new UnsignedIntType(new NormalDistribution(seed), [100, 300]).generateArrayWithoutNull(size, {unique: false});
     const expectedUnsignedIntType = [141,172,133,175,261,142,160,262,180,200];
     expect(unsignedIntType).to.deep.equal(expectedUnsignedIntType);
     
-    const unsignedIntTypeNull = new UnsignedIntType(new NormalDistribution(seed)).generateArrayWithNull(size, nullPerc, false);
+    const unsignedIntTypeNull = new UnsignedIntType(new NormalDistribution(seed)).generateArrayWithNull(size, nullPerc, {unique: false});
     const expectedUnsignedIntTypeNull = [null,3239988727117702,1487186952157000,null,null,1869619023842354,null,null,3587111689209931,4507687566378977];
     expect(unsignedIntTypeNull).to.deep.equal(expectedUnsignedIntTypeNull);
   
   });
 
   describe("Generate SignedInt array", () => {
-    const signedIntType = new SignedIntType(new NormalDistribution(seed), [-100, 100]).generateArrayWithoutNull(size, false);
+    const signedIntType = new SignedIntType(new NormalDistribution(seed), [-100, 100]).generateArrayWithoutNull(size, {unique: false});
     const expectedSignedIntType =  [-59,-28,-67,-25,61,-58,-40,62,-20,0];
     expect(signedIntType).to.deep.equal(expectedSignedIntType);
     
-    const signedIntTypeNull = new SignedIntType(new NormalDistribution(seed)).generateArrayWithNull(size, nullPerc, false);
+    const signedIntTypeNull = new SignedIntType(new NormalDistribution(seed)).generateArrayWithNull(size, nullPerc, {unique: false});
     const expectedSignedIntTypeNull = [null,-2527221800505587,-6032825350426992,null,null,-5267961207056283,null,null,-1832975876321130,8175878016963];
     expect(signedIntTypeNull).to.deep.equal(expectedSignedIntTypeNull);
   
   });
 
   describe("Generate Decimal array", () =>{
-    const decimalType = new DecimalType(new NormalDistribution(seed), [-10.5, 60.25]).generateArrayWithoutNull(size, false);
+    const decimalType = new DecimalType(new NormalDistribution(seed), [-10.5, 60.25]).generateArrayWithoutNull(size, {unique: false});
     const expectedDecimalType =  [3.8574782908463803,14.949553846932087,1.1815975631632014,15.947041879489474,46.45032735690995,4.185535669394966,10.626441929377277,46.79418443234036,17.676144974035047,24.907110057374144];
     expect(decimalType).to.deep.equal(expectedDecimalType);
     
-    const decimalTypeNull = new DecimalType(new NormalDistribution(seed)).generateArrayWithNull(size, nullPerc, false);
+    const decimalTypeNull = new DecimalType(new NormalDistribution(seed)).generateArrayWithNull(size, nullPerc, {unique: false});
     const expectedDecimalTypeNull =  [null,-2527221800505587,-6032825350426992,null,null,-5267961207056283,null,null,-1832975876321130,8175878016963.115];
     expect(decimalTypeNull).to.deep.equal(expectedDecimalTypeNull);
   
   });
 
   describe("Generate Boolean array", () => {
-    const booleanType = new BooleanType(new NormalDistribution(seed)).generateArrayWithoutNull(size);
+    const booleanType = new BooleanType(new NormalDistribution(seed)).generateArrayWithoutNull(size, {});
     const expectedBooleanType =  [false,false,false,false,true,false,false,true,false,true];
     expect(booleanType).to.deep.equal(expectedBooleanType);
     
-    const booleanTypeNull = new BooleanType(new NormalDistribution(seed)).generateArrayWithNull(size, nullPerc);
+    const booleanTypeNull = new BooleanType(new NormalDistribution(seed)).generateArrayWithNull(size, nullPerc, {});
     const expectedBooleanTypeNull =  [null,false,false,null,null,false,null,null,false,true];
     expect(booleanTypeNull).to.deep.equal(expectedBooleanTypeNull);
   
diff --git a/test/k6/mockScenario.yml b/test/k6/mockScenario.yml
deleted file mode 100644
index a98b90997a7e6e64b11af4303759ec33700ce1d1..0000000000000000000000000000000000000000
--- a/test/k6/mockScenario.yml
+++ /dev/null
@@ -1,53 +0,0 @@
-scenario_name: MOCK
-
-# The tables under test.
-tables_schema:
-  - name: mock_table_1
-    row_count: 10
-    columns:
-      - name: unsigned_col
-        type: Unsigned
-        distribution: Normal
-        range: [0, 100]
-        is_nullable: false
-        null_percentage: 0
-        unique: true
-      - name: string_col
-        type: String
-        distribution: Uniform
-        range: [4, 7]
-        alphabet: ["en"]
-        is_nullable: false
-        null_percentage: 0
-        unique: false
-      - name: boolean_col
-        type: Boolean
-        distribution: Normal
-        is_nullable: false
-        null_percentage: 0
-    primary_key: unsigned_col
-    distribution_key: unsigned_col
-    timeout: 3.0
-  - name: mock_table_2
-    row_count: 5
-    columns:
-      - name: integer_col
-        type: Integer
-        distribution: Normal
-        range: [0, 100]
-        is_nullable: false
-        null_percentage: 0
-        unique: true
-    primary_key: integer_col
-    distribution_key: integer_col
-    timeout: 3.0
-
-# Template SQL queries with parameters and weights
-queries:
-  - sql: select * from "mock_table_1"
-    params: []
-    weight: 50
-  - sql: select count("unsigned_col") from "mock_table_1" where "boolean_col" = ?
-    params: 
-      - value: true
-    weight: 100
diff --git a/test/unit/BooleanType.test.ts b/test/unit/BooleanType.test.ts
index 30f80b3c2ca18bc2725e1caa45c2d1d3aec80053..6d585459fdc2098db80b771946096c8e290486b7 100644
--- a/test/unit/BooleanType.test.ts
+++ b/test/unit/BooleanType.test.ts
@@ -4,6 +4,7 @@ import { expect } from "chai";
 
 import { suite, test } from "@testdeck/mocha";
 
+import { DistributionOpts } from "../../src/distributions/IDistribution";
 import { BooleanType } from "../../src/types/Boolean";
 import { MockDistribution } from "./Mocks";
 
@@ -14,6 +15,7 @@ class BooleanGenerationTest {
   private arraySize: number;
   private nullPercentage: number;
   private mockDist: MockDistribution;
+  private distOpts: DistributionOpts;
 
   before() {
     this.arraySize = 10;
@@ -24,7 +26,8 @@ class BooleanGenerationTest {
 
   @test
   generateBooleanArrayOfCertainSizeWithoutNull() {
-    const booleanArray: boolean[] = this.type.generateArrayWithoutNull(this.arraySize);
+    this.distOpts = {};
+    const booleanArray: boolean[] = this.type.generateArrayWithoutNull(this.arraySize, this.distOpts);
     expect(booleanArray).not.to.be.empty;
     expect(booleanArray.length).to.be.equal(this.arraySize);
     for (let i: number = 0; i < this.arraySize; i++) {
@@ -34,7 +37,8 @@ class BooleanGenerationTest {
 
   @test
   generateBooleanArrayOfCertainSizeWithtNull() {
-    const booleanArray: boolean[] = this.type.generateArrayWithNull(this.arraySize, this.nullPercentage);
+    this.distOpts = {};
+    const booleanArray: boolean[] = this.type.generateArrayWithNull(this.arraySize, this.nullPercentage, this.distOpts);
     expect(booleanArray).not.to.be.empty;
     expect(booleanArray.length).to.be.equal(this.arraySize);
     let nullCount: number = 0;
diff --git a/test/unit/DecimalType.test.ts b/test/unit/DecimalType.test.ts
index 94e38549c9deeebad28c98d527dfab080f9cb5b9..621c550ecdc9f6432f67ef2ee71917c33e511832 100644
--- a/test/unit/DecimalType.test.ts
+++ b/test/unit/DecimalType.test.ts
@@ -4,6 +4,7 @@ import { expect } from "chai";
 
 import { suite, test } from "@testdeck/mocha";
 
+import { DistributionOpts } from "../../src/distributions/IDistribution";
 import { DecimalType } from "../../src/types/Decimal";
 import { MockDistribution } from "./Mocks";
 
@@ -17,6 +18,7 @@ class DecimalGenerationTest {
   private arraySize: number;
   private nullPercentage: number;
   private mockDist: MockDistribution;
+  private distOpts: DistributionOpts;
   private minBound: number;
   private maxBound: number;
 
@@ -42,8 +44,8 @@ class DecimalGenerationTest {
 
   @test
   generateUniqueDecimalArrayOfCertainSizeWithoutNull() {
-    const unique: boolean = true;
-    const decimalArray: number[] = this.type.generateArrayWithoutNull(this.arraySize, unique);
+    this.distOpts = { unique: true };
+    const decimalArray: number[] = this.type.generateArrayWithoutNull(this.arraySize, this.distOpts);
     expect(decimalArray).not.to.be.empty;
     expect(decimalArray.length).to.be.equal(this.arraySize);
     for (let i: number = 0; i < this.arraySize; i++) {
@@ -54,11 +56,11 @@ class DecimalGenerationTest {
 
   @test
   generateUniqueDecimalArrayOfCertainSizeWithNull() {
-    const unique: boolean = true;
+    this.distOpts = { unique: true };
     const decimalArray: (number | null)[] = this.type.generateArrayWithNull(
       this.arraySize,
       this.nullPercentage,
-      unique
+      this.distOpts
     );
     expect(decimalArray).not.to.be.empty;
     expect(decimalArray.length).to.be.equal(this.arraySize);
diff --git a/test/unit/NormalDistribution.test.ts b/test/unit/NormalDistribution.test.ts
index 052f9dac7083c2cc2e08b3ec6f6cf04de8f032aa..be2dcb502e2e3b0d119fe8b468d88941a0db4a54 100644
--- a/test/unit/NormalDistribution.test.ts
+++ b/test/unit/NormalDistribution.test.ts
@@ -24,7 +24,7 @@ class NormalDistributionTest {
     for (const count of sampleCount) {
       // eslint-disable-next-line
       const uniqueCount = {};
-      const generatedSequence: number[] = this.distribution.randomIntArray(count, customRange, false);
+      const generatedSequence: number[] = this.distribution.randomIntArray(count, customRange, { unique: false });
       generatedSequence.forEach((value) => {
         expect(value).to.be.within(customRange.left, customRange.right);
         if (uniqueCount[value]) {
@@ -42,7 +42,7 @@ class NormalDistributionTest {
   generateRandomIntegerInRangeOfSameValue() {
     const customRange: MockRange<number> = new MockRange<number>(1, 1);
     const sampleCount: number = 50;
-    const generatedSequence: number[] = this.distribution.randomIntArray(sampleCount, customRange, false);
+    const generatedSequence: number[] = this.distribution.randomIntArray(sampleCount, customRange, { unique: false });
     generatedSequence.forEach((value) => {
       expect(value).to.be.equal(1);
     });
@@ -52,7 +52,7 @@ class NormalDistributionTest {
   generateArrayOfUniqueIntegersInRange() {
     const customRange: MockRange<number> = new MockRange<number>(0, 11);
     const sampleCount: number = 12;
-    const generatedSequence: number[] = this.distribution.randomIntArray(sampleCount, customRange, true);
+    const generatedSequence: number[] = this.distribution.randomIntArray(sampleCount, customRange, { unique: true });
     const expectedSequence: number[] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11];
     expect(generatedSequence.sort((a, b) => a - b)).to.be.deep.equal(expectedSequence);
   }
@@ -61,7 +61,7 @@ class NormalDistributionTest {
   generateArrayOfIntegersInRange() {
     const customRange: MockRange<number> = new MockRange<number>(-20, 100);
     const sampleCount: number = 100;
-    const generatedSequence: number[] = this.distribution.randomIntArray(sampleCount, customRange, false);
+    const generatedSequence: number[] = this.distribution.randomIntArray(sampleCount, customRange, { unique: false });
     for (const value of generatedSequence) {
       expect(value).to.be.within(customRange.left, customRange.right);
     }
@@ -71,7 +71,7 @@ class NormalDistributionTest {
   generateArrayOfFloatsInRange() {
     const customRange: MockRange<number> = new MockRange<number>(-20, 100);
     const sampleCount: number = 100;
-    const generatedSequence: number[] = this.distribution.randomFloatArray(sampleCount, customRange, false);
+    const generatedSequence: number[] = this.distribution.randomFloatArray(sampleCount, customRange, { unique: false });
     for (const value of generatedSequence) {
       expect(value).to.be.within(customRange.left, customRange.right);
     }
diff --git a/test/unit/SignedIntType.test.ts b/test/unit/SignedIntType.test.ts
index 60f5b341ebfb10fbc6d7045a617b9f35ddd64e27..4fd46a6910d963d47fc72b111c9d4bb407bd50f6 100644
--- a/test/unit/SignedIntType.test.ts
+++ b/test/unit/SignedIntType.test.ts
@@ -4,6 +4,7 @@ import { expect } from "chai";
 
 import { suite, test } from "@testdeck/mocha";
 
+import { DistributionOpts } from "../../src/distributions/IDistribution";
 import { SignedIntType } from "../../src/types/SignedInt";
 import { MockDistribution } from "./Mocks";
 
@@ -17,6 +18,7 @@ class SignedGenerationTest {
   private arraySize: number;
   private nullPercentage: number;
   private mockDist: MockDistribution;
+  private distOpts: DistributionOpts;
   private minBound: number;
   private maxBound: number;
 
@@ -41,8 +43,8 @@ class SignedGenerationTest {
 
   @test
   generateUniqueSignedArrayOfCertainSizeWithoutNull() {
-    const unique: boolean = true;
-    const signedArray: number[] = this.type.generateArrayWithoutNull(this.arraySize, unique);
+    this.distOpts = { unique: true };
+    const signedArray: number[] = this.type.generateArrayWithoutNull(this.arraySize, this.distOpts);
     expect(signedArray).not.to.be.empty;
     expect(signedArray.length).to.be.equal(this.arraySize);
     for (let i: number = 0; i < this.arraySize; i++) {
@@ -53,8 +55,8 @@ class SignedGenerationTest {
 
   @test
   generateSignedArrayOfCertainSizeWithoutNull() {
-    const unique: boolean = false;
-    const signedArray: number[] = this.type.generateArrayWithoutNull(this.arraySize, unique);
+    this.distOpts = { unique: false };
+    const signedArray: number[] = this.type.generateArrayWithoutNull(this.arraySize, this.distOpts);
     expect(signedArray).not.to.be.empty;
     expect(signedArray.length).to.be.equal(this.arraySize);
     for (let i: number = 0; i < this.arraySize; i++) {
@@ -65,8 +67,12 @@ class SignedGenerationTest {
 
   @test
   generateSignedArrayOfCertainSizeWithNull() {
-    const unique: boolean = true;
-    const signedArray: (number | null)[] = this.type.generateArrayWithNull(this.arraySize, this.nullPercentage, unique);
+    this.distOpts = { unique: true };
+    const signedArray: (number | null)[] = this.type.generateArrayWithNull(
+      this.arraySize,
+      this.nullPercentage,
+      this.distOpts
+    );
     expect(signedArray).not.to.be.empty;
     expect(signedArray.length).to.be.equal(this.arraySize);
     let nullCount: number = 0;
diff --git a/test/unit/StringType.test.ts b/test/unit/StringType.test.ts
index 23909dce73128582598248cd4cfeaa00ff34d00c..30f84b06ff2f10dfa51e1b732d24d6cf1414343d 100644
--- a/test/unit/StringType.test.ts
+++ b/test/unit/StringType.test.ts
@@ -4,6 +4,7 @@ import { expect } from "chai";
 
 import { suite, test } from "@testdeck/mocha";
 
+import { DistributionOpts } from "../../src/distributions/IDistribution";
 import { StringType } from "../../src/types/String";
 import { MockDistribution } from "./Mocks";
 
@@ -12,12 +13,12 @@ import { MockDistribution } from "./Mocks";
 class StringGenerationTest {
   private type: StringType;
   private mockDist: MockDistribution;
+  private distOpts: DistributionOpts;
   private arraySize: number;
   private nullPercentage: number;
   private minLength: number;
   private maxLength: number;
   private chars: string[];
-  private unique: boolean;
 
   before() {
     this.arraySize = 5;
@@ -34,8 +35,8 @@ class StringGenerationTest {
 
   @test
   generateUniqueStringArrayOfCertainSizeWithoutNull() {
-    this.unique = true;
-    const stringArray: string[] = this.type.generateArrayWithoutNull(this.arraySize, this.unique);
+    this.distOpts = { unique: true };
+    const stringArray: string[] = this.type.generateArrayWithoutNull(this.arraySize, this.distOpts);
     expect(stringArray).not.to.be.empty;
     expect(stringArray.length).to.be.equal(this.arraySize);
     for (let i: number = 0; i < this.arraySize; i++) {
@@ -46,8 +47,8 @@ class StringGenerationTest {
 
   @test
   generateStringArrayOfCertainSizeWithoutNull() {
-    this.unique = false;
-    const stringArray: string[] = this.type.generateArrayWithoutNull(this.arraySize, this.unique);
+    this.distOpts = { unique: false };
+    const stringArray: string[] = this.type.generateArrayWithoutNull(this.arraySize, this.distOpts);
     expect(stringArray).not.to.be.empty;
     expect(stringArray.length).to.be.equal(this.arraySize);
     for (let i: number = 0; i < this.arraySize; i++) {
@@ -58,8 +59,8 @@ class StringGenerationTest {
 
   @test
   generateStringArrayOfCertainSizeWithNull() {
-    this.unique = false;
-    const stringArray: string[] = this.type.generateArrayWithNull(this.arraySize, this.nullPercentage, this.unique);
+    this.distOpts = { unique: false };
+    const stringArray: string[] = this.type.generateArrayWithNull(this.arraySize, this.nullPercentage, this.distOpts);
     expect(stringArray).not.to.be.empty;
     expect(stringArray.length).to.be.equal(this.arraySize);
     let nullCount: number = 0;
diff --git a/test/unit/UniformDistribution.test.ts b/test/unit/UniformDistribution.test.ts
index b1b5d39b687074c94fea30c58cafb954fca2f30f..73b421443a6b5020602852ba259eb25041e88d21 100644
--- a/test/unit/UniformDistribution.test.ts
+++ b/test/unit/UniformDistribution.test.ts
@@ -24,7 +24,7 @@ class UniformDistributionTest {
     for (const count of sampleCount) {
       // eslint-disable-next-line
       const uniqueCount = {};
-      const generatedSequence: number[] = this.distribution.randomIntArray(count, customRange, false);
+      const generatedSequence: number[] = this.distribution.randomIntArray(count, customRange, { unique: false });
       generatedSequence.forEach((value) => {
         expect(value).to.be.within(customRange.left, customRange.right);
         if (uniqueCount[value]) {
@@ -42,7 +42,7 @@ class UniformDistributionTest {
   generateRandomIntegerInRangeOfSameValue() {
     const customRange: MockRange<number> = new MockRange<number>(1, 1);
     const sampleCount: number = 50;
-    const generatedSequence: number[] = this.distribution.randomIntArray(sampleCount, customRange, false);
+    const generatedSequence: number[] = this.distribution.randomIntArray(sampleCount, customRange, { unique: false });
     generatedSequence.forEach((value) => {
       expect(value).to.be.equal(1);
     });
@@ -52,7 +52,7 @@ class UniformDistributionTest {
   generateArrayOfUniqueIntegersInRange() {
     const customRange: MockRange<number> = new MockRange<number>(0, 11);
     const sampleCount: number = 12;
-    const generatedSequence: number[] = this.distribution.randomIntArray(sampleCount, customRange, true);
+    const generatedSequence: number[] = this.distribution.randomIntArray(sampleCount, customRange, { unique: true });
     const expectedSequence: number[] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11];
     expect(generatedSequence.sort((a, b) => a - b)).to.be.deep.equal(expectedSequence);
   }
@@ -61,7 +61,7 @@ class UniformDistributionTest {
   generateArrayOfIntegersInRange() {
     const customRange: MockRange<number> = new MockRange<number>(-20, 100);
     const sampleCount: number = 100;
-    const generatedSequence: number[] = this.distribution.randomIntArray(sampleCount, customRange, false);
+    const generatedSequence: number[] = this.distribution.randomIntArray(sampleCount, customRange, { unique: false });
     for (const value of generatedSequence) {
       expect(value).to.be.within(customRange.left, customRange.right);
     }
@@ -71,7 +71,7 @@ class UniformDistributionTest {
   generateArrayOfFloatsInRange() {
     const customRange: MockRange<number> = new MockRange<number>(-20, 100);
     const sampleCount: number = 100;
-    const generatedSequence: number[] = this.distribution.randomFloatArray(sampleCount, customRange, false);
+    const generatedSequence: number[] = this.distribution.randomFloatArray(sampleCount, customRange, { unique: false });
     for (const value of generatedSequence) {
       expect(value).to.be.within(customRange.left, customRange.right);
     }
diff --git a/test/unit/UnsignedIntType.test.ts b/test/unit/UnsignedIntType.test.ts
index 398c92aa0b8163f491f91a660bb470edcfc93fa4..2c21a1b23d733d48d0f668cf0caa1a3768a0963d 100644
--- a/test/unit/UnsignedIntType.test.ts
+++ b/test/unit/UnsignedIntType.test.ts
@@ -4,6 +4,7 @@ import { expect } from "chai";
 
 import { suite, test } from "@testdeck/mocha";
 
+import { DistributionOpts } from "../../src/distributions/IDistribution";
 import { UnsignedIntType } from "../../src/types/UnsignedInt";
 import { MockDistribution } from "./Mocks";
 
@@ -15,9 +16,9 @@ const WRONG_ARGUMENT: string =
 class UnsignedGenerationTest {
   private type: UnsignedIntType;
   private mockDist: MockDistribution;
+  private distOpts: DistributionOpts;
   private arraySize: number;
   private nullPercentage: number;
-  private unique: boolean;
   private minBound: number;
   private maxBound: number;
 
@@ -50,8 +51,8 @@ class UnsignedGenerationTest {
 
   @test
   generateUniqueUnsignedArrayOfCertainSizeWithoutNull() {
-    this.unique = true;
-    const unsignedArray: number[] = this.type.generateArrayWithoutNull(this.arraySize, this.unique);
+    this.distOpts = { unique: true };
+    const unsignedArray: number[] = this.type.generateArrayWithoutNull(this.arraySize, this.distOpts);
     expect(unsignedArray).not.to.be.empty;
     expect(unsignedArray.length).to.be.equal(this.arraySize);
     for (let i: number = 0; i < this.arraySize; i++) {
@@ -62,8 +63,8 @@ class UnsignedGenerationTest {
 
   @test
   generateUnsignedArrayOfCertainSizeWithoutNull() {
-    this.unique = false;
-    const unsignedArray: number[] = this.type.generateArrayWithoutNull(this.arraySize, this.unique);
+    this.distOpts = { unique: false };
+    const unsignedArray: number[] = this.type.generateArrayWithoutNull(this.arraySize, this.distOpts);
     expect(unsignedArray).not.to.be.empty;
     expect(unsignedArray.length).to.be.equal(this.arraySize);
     for (let i: number = 0; i < this.arraySize; i++) {
@@ -74,11 +75,11 @@ class UnsignedGenerationTest {
 
   @test
   generateUnsignedArrayOfCertainSizeWithNull() {
-    this.unique = false;
+    this.distOpts = { unique: false };
     const unsignedArray: (number | null)[] = this.type.generateArrayWithNull(
       this.arraySize,
       this.nullPercentage,
-      this.unique
+      this.distOpts
     );
     expect(unsignedArray).not.to.be.empty;
     expect(unsignedArray.length).to.be.equal(this.arraySize);
diff --git a/test/unit/ZipfDistribution.test.ts b/test/unit/ZipfDistribution.test.ts
new file mode 100644
index 0000000000000000000000000000000000000000..8ad2cc91938bf968810dd78aaf283e031ce73f27
--- /dev/null
+++ b/test/unit/ZipfDistribution.test.ts
@@ -0,0 +1,67 @@
+import "mocha";
+
+import { expect } from "chai";
+
+import { suite, test } from "@testdeck/mocha";
+
+import ZipfDistribution from "../../src/distributions/ZipfDistribution";
+import { MockRange } from "./Mocks";
+
+@suite
+// eslint-disable-next-line
+class ZipfDistributionTest {
+  private seed: number;
+  private distribution: ZipfDistribution;
+  private min: number;
+  private max: number;
+  private zipfian: number;
+
+  before() {
+    this.seed = 123456789;
+    this.zipfian = 1.1;
+  }
+
+  @test
+  throwIfIncorrectZipfianProvided() {
+    this.distribution = new ZipfDistribution(this.seed);
+    const sampleCount: number = 100;
+    this.min = 10;
+    this.max = 20;
+    this.zipfian = 1;
+    expect(() =>
+      this.distribution.randomIntArray(sampleCount, new MockRange<number>(this.min, this.max), {
+        parameter: this.zipfian
+      })
+    ).to.throw(Error, "ZipfDistribution : randomFloat: Please ensure, that zipfian value is in range [1.1, 1000.0]");
+
+    this.zipfian = 1001;
+    expect(() =>
+      this.distribution.randomIntArray(sampleCount, new MockRange<number>(this.min, this.max), {
+        parameter: this.zipfian
+      })
+    ).to.throw(Error, "ZipfDistribution : randomFloat: Please ensure, that zipfian value is in range [1.1, 1000.0]");
+  }
+
+  @test
+  generateRandomIntArrayWithZipfianCorrectly() {
+    this.distribution = new ZipfDistribution(this.seed);
+    const sampleCount: number = 100;
+    const uniqueCount: object = {};
+    this.min = 10;
+    this.max = 20;
+    const gen1: number[] = this.distribution.randomIntArray(sampleCount, new MockRange<number>(this.min, this.max), {
+      parameter: this.zipfian
+    });
+
+    gen1.forEach((value: number) => {
+      if (uniqueCount[value]) {
+        uniqueCount[value] += 1;
+      } else {
+        uniqueCount[value] = 1;
+      }
+    });
+    for (let i: number = this.min; i <= this.max; i++) {
+      expect(uniqueCount[i]).to.be.greaterThan(0);
+    }
+  }
+}
diff --git a/tsconfig.json b/tsconfig.json
index e48b2a1f262c6c4d73eaa7e06de82691960a837f..17fedec2e071e08493a0c0935298041d12c5b1eb 100644
--- a/tsconfig.json
+++ b/tsconfig.json
@@ -22,7 +22,8 @@
     "experimentalDecorators": true,
     "emitDecoratorMetadata": true,
     "skipLibCheck": true,
-    "strictNullChecks": true
+    "strictNullChecks": true,
+    "declaration": true
   },
-  "include": ["k6_modules", "src", "test", "third_party", "example"]
+  "include": ["k6_modules", "src", "test", "third_party"]
 }