1.5.2 • Published 11 months ago

@saperiuminc/zwarm-client v1.5.2

Weekly downloads
-
License
ISC
Repository
github
Last release
11 months ago

zwarm-client

Zombie Swarm e2e/load testing Client for zwarm, inspired by k6 and modelled after Mocha. This load testing tool makes end-to-end performance testing easy and productive for development teams which uses Puppeteer to simulate "virtual users" via headless browser manipulation.

Installation

$ npm install -g @saperiuminc/zwarm-client

Running zwarm-client

// example-vin-decoder.js
it('Test 1', async() => {
    const page = await $browser.newPage();
    await page.goto('http://randomvin.com/getvin.php?type=real');
    const vin = await page.evaluate(() => document.body.innerText);
    await $log(`${$iteration}(${$VU}): ${vin}`);
    return await $sleep(1000);
});

Running the above sample will produce a json-formatted output similar below:

# Run a test
$ zwarm-client run example-vin-decoder.js some-zwarm-server.com:3030
1(1): 1FAHP3F27CL221337
{
  pass: true,
  swarms: 1,
  walkers: 1,
  steps: 1,
  durationIn: { millis: 1527, seconds: 1.53, minutes: 0.03 },
  iterations: { min: 1, max: 1, avg: 1 },
  stats: {
    default: {
      tests: {
        'Test 1': {
          runs: 1,
          stats: { avg: 1406, _avgInc: 1, min: 1406, max: 1406 }
        }
      },
      errors: []
    }
  },
  timings: {
    'Test 1': {
      count: 1,
      min: 1406,
      max: 1406,
      mean: 1406,
      median: 1406,
      p90: 1406,
      p95: 1406,
      rates: { min: null, max: null, mean: null }
    }
  },
  checks: {}
}

# Add virtual users
$ zwarm-client run example-vin-decoder.js some-zwarm-server.com:3030 --iteration 2 --vus 2
1(1): JM1BJ227430649560
1(2): 1GYEE63A540146652
2(1): 2T1BU4EE3CC780594
2(2): KMHWF25V2YA162674
{
  pass: true,
  swarms: 1,
  walkers: 2,
  steps: 1,
  durationIn: { millis: 3027, seconds: 3.03, minutes: 0.05 },
  iterations: { min: 2, max: 2, avg: 2 },
  stats: {
    default: {
      tests: {
        'Test 1': {
          runs: 4,
          stats: { avg: 1351.25, _avgInc: 2, min: 1245, max: 1429 }
        }
      },
      errors: []
    }
  },
  timings: {
    'Test 1': {
      count: 4,
      min: 1245,
      max: 1429,
      mean: 1351.25,
      median: 1365.5,
      p90: 1429,
      p95: 1429,
      rates: { min: 2, max: 2, mean: 2 }
    }
  },
  checks: {}
}

# Increase the test duration
$ zwarm-client run example-vin-decoder.js some-zwarm-server.com:3030 --duration 5
1(1): 1G1AL55FX67787179
2(1): 2T3DK4DV5AW035669
3(1): 1C4SDJETXCC202739
4(1): 1J4GW48N23C615618
{
  pass: true,
  swarms: 1,
  walkers: 1,
  steps: 1,
  durationIn: { millis: 5551, seconds: 5.55, minutes: 0.09 },
  iterations: { min: 4, max: 4, avg: 4 },
  stats: {
    default: {
      tests: {
        'Test 1': {
          runs: 4,
          stats: { avg: 1302.5, _avgInc: 1, min: 1215, max: 1488 }
        }
      },
      errors: []
    }
  },
  timings: {
    'Test 1': {
      count: 4,
      min: 1215,
      max: 1488,
      mean: 1302.5,
      median: 1253.5,
      p90: 1488,
      p95: 1488,
      rates: { min: 1, max: 1, mean: 1 }
    }
  },
  checks: {}
}

Zwarm works with the concept of "virtual users (VUs)", which run the loadtest scripts. VUs are essentially parallel process and/or machines while scripts are written in Javascript and can be broken into smaller pieces or make reusable pieces.

Using Steps options

Instead of typing --vus 2 or --duration 5 each time to run the script, another option is to add a "steps/stage" option in the Javascript file:

// example-http-decoder.js
$options.steps = [{
    vus: ($options.vus * 2),
    duration: $options.duration,
    iteration: 2,
    stages: {
        randomvin: 0.5,
        vpic: 0.5
    }
}];

describe('Multi stage/http demo', function() {
    it('Test random VIN', 'randomvin', async() => {
        const response = await $http.get('http://randomvin.com/getvin.php?type=real');
        const vin = response.data;
        await $log(`VIN ${$iteration}(${$VU}): ${vin}`);
        return await $sleep(500);
    });

    it('Test NHTSA VPIC', 'vpic', async() => {
        let response = await $http.get('http://randomvin.com/getvin.php?type=real');
        const vin = response.data;
        response = await $http.get(`https://vpic.nhtsa.dot.gov/api/vehicles/decodevinvalues/${vin}?format=json`);
        const vpicResult = response.data;
        const vehicle = (vpicResult.Results.length > 0 ? vpicResult.Results[0] : {});
        await $log(`VPIC ${$iteration}(${$VU}): ${vehicle.ModelYear} ${vehicle.Make} ${vehicle.Model} ${vehicle.Trim ? (vehicle.Trim + ' ') : ''}- ${vin}`);
        return await $sleep(500);
    }); 
});

Then, run the script without those command-line options:

$ zwarm-client run example-http-decoder.js some-zwarm-server.com:3030
VIN 1(1): 19XFB2F56CE034717
VPIC 1(2): 2015 JEEP Grand Cherokee Limited - 1C4RJFBG8FC699161
VIN 2(1): KM8SNDHF5EU057574
VPIC 2(2): 2007 HONDA Accord HYBRID NAVI - JHMCN36567C003754
{
  pass: true,
  swarms: 1,
  walkers: 2,
  steps: 1,
  durationIn: { millis: 2412, seconds: 2.41, minutes: 0.04 },
  iterations: { min: 2, max: 2, avg: 2 },
  stats: {
    'Multi stage/http demo': {
      tests: {
        'Test NHTSA VPIC': {
          runs: 2,
          stats: { avg: 1092, _avgInc: 1, min: 1073, max: 1111 }
        },
        'Test random VIN': {
          runs: 2,
          stats: { avg: 841, _avgInc: 1, min: 813, max: 869 }
        }
      },
      errors: []
    }
  },
  timings: {
    'Test random VIN': {
      count: 2,
      min: 813,
      max: 869,
      mean: 841,
      median: 841,
      p90: 869,
      p95: 869,
      rates: { min: 2, max: 2, mean: 2 }
    },
    'Test NHTSA VPIC': {
      count: 2,
      min: 1073,
      max: 1111,
      mean: 1092,
      median: 1092,
      p90: 1111,
      p95: 1111,
      rates: { min: 1, max: 1, mean: 1 }
    }
  },
  checks: {}
}

See Samples folder for more advanced usage

Command-Line

Like most command-line application, help command just display information about zwarm-client basic commands and options:

$ zwarm-client --help
Usage: zwarm-client <command> [options]

Commands:
  zwarm-client run <script> <address>  run e2e/loadtest script
  zwarm-client info <address>          returns server info

Options:
      --help     Show help                                             [boolean]
      --version  Show version number                                   [boolean]
  -v, --verbose  Run with verbose logging                              [boolean]

Zombie Swarm e2e/loadtest Client- copyright 2023

run command

Runs the loadtest script on a particular server/address. See Load Test scripts for further reference.

$ zwarm-client run --help
zwarm-client run <script> <address>

run e2e/loadtest script

Positionals:
  script   e2e/loadtest script                                        [required]
  address  zombie swarm URL/address                                   [required]

Options:
      --help       Show help                                           [boolean]
      --version    Show version number                                 [boolean]
  -v, --verbose    Run with verbose logging                            [boolean]
      --vus        no. of virtual zombies to rise          [number] [default: 1]
      --duration   how long the zombies will attack (in seconds)
                                                          [number] [default: 30]
      --iteration  how many zombies will attack                         [number]
  -e, --env        environment name=value variables to pass on zwarm     [array]
  -f, --file       upload and/or map files to swarm server <src>[:<dest>][array]

info command

Returns the nos. of swarms/zombies available, including current attacks/walkers. | Name | Description | | --- | --- | | swarms | No. of virtual machines registered on the zwarm server/coordinator | | zombies | Available no. of "virtual users (VUs)" that attack | | attacks | Current no. of "running" loadtest scripts | | walkers | Current no. of zombies or "virtual users (VUs)" attacking |

$ zwarm-client info --help
zwarm-client info <address>

returns server info

Positionals:
  address  zombie swarm URL/address                                   [required]

Options:
      --help     Show help                                             [boolean]
      --version  Show version number                                   [boolean]
  -v, --verbose  Run with verbose logging                              [boolean]

Load Test scripts

The basic construct of zwarm loadtest scripts are similar to Mocha tests supporting the following testing api:

  • Can have 0 or N suites (or describe calls)
  • Support 1 or N tests (or it calls)
  • Can have optional before/after and beforeEach/afterEach calls
  • Support for callback-based approach and/or promises/async/await style of operations

    Limitations:

  • No multi-level or hierarchical suites

  • Only support built-in modules or objects (no require support)
  • No assertion modules

Built-in modules:

All built-in objects and functions are prefixed with $ character to differentiate zwarm system vs. script variables.

it('Test 1', async() => {
    const page = await $browser.newPage();
    await page.goto('http://randomvin.com/getvin.php?type=real');
    const vin = await page.evaluate(() => document.body.innerText);
    await $log(`${$iteration}(${$VU}): ${vin}`);
    return await $sleep(1000);
});

On this example, $browser, $iteration and $VU are built-in objects while $log and $sleep are built-in functions.

NameDescriptionDefault
$options.vusTarget count of zombies/walkers that will attack1
$options.durationDuration (in seconds) for how long the attack will last30
$options.iterationTarget count of how many times a test will be run (NOTE: duration is prioritized over iteration)optional
$options.stepsSeries of ramp up/down stages containing target VUs, duration or iterationoptional
$options.thresholdsSeries of acceptable timing thresholdsoptional
$browserAn instance of Puppeteer browser objectBrowser class
$httpAn instance of HTTP client for browseraxios
$socketioA subscribe-able client instance of an in-page socket.io parsersocket.io-parser
$wsA websocket object listener using event emittersCDP Session
$VUAssigned unique no. for a "virtual user (VU)"1..N
$VUmetaA hash key/value pair that can be set and retrieve between suites/testshash object
$iterationCurrent iteration of a test in the suite1..N
$stepCurrent step for a multi-stage run0..N
$nop()A simple do nothing async operation()
$log(...)Log and store events up to the server/coordinator(text)
$timing(...)Add an e2e timing for a particular stat/value(stat, value)
$check(...)Conduct threshold check/verification for a particular condition(key, condition)
$setVUmeta(...)Set a "virtual user (VU)" key/value pair(VU, key, value)
$loadJson(...)Special JSON file loader (returns a JSON object)(filePath) => object

TODO:

  • Advanced samples/documentation
  • Experimental features using socket.io protocol between server/coordinator and swarm/zombies

License

MIT

1.5.2

11 months ago

1.5.1

11 months ago

1.5.0

11 months ago

1.4.4

1 year ago