Skip to content

Latest commit

 

History

History
 
 

tests

Prerequisites

  • node
  • kubectl logged into a Kubernetes cluster.
  • Each scaler test might define additional requirements. For example, azure-queue.test.ts requires an env var AZURE_STORAGE_CONNECTION_STRING

Running tests:

npm install
npm test --verbose

Run one test file:

npx ava scalers/prometheus.test.ts

E2E test setup

The test script will run 3 phases:

  • Setup: this is done in setup.test.ts. If you're adding any tests for KEDA install/setup process add it to this file.setup.test.ts deploys KEDA to keda namespace in the cluster, and updates the image to kedacore/keda:main.

    After setup.test.ts is done, we expect to have a cluster with KEDA setup in namespace keda. This is done through a pretest hook in npm. See "scripts" in package.json.

  • Tests: Currently there are only scaler tests in tests/scalers. All files run in parallel, but tests within the file can run either in parallel or in series. More about tests below.

  • Global clean up: this is done in cleanup.test.ts. This step cleans resources created in setup.test.ts.

Adding tests:

  • Tests are written in TypeScript using ava framework. See ava docs here
  • Each scaler tests should be in a file. e.g: azure-queue.tests.ts, kafka.tests.ts, etc
  • All files in scalers/**.ts are run in parallel by default. Make sure your tests don't affect the global state of the cluster in a way that can break other tests.
  • Each test file is expected to do it's own setup and clean up for its resources.
// import test from ava framework
import test from 'ava';

test.before(t => {
    // this runs once before all tests.
    // do setup here. e.g:
    //  - Create a namespace for your tests using the function createNamespace(namespace: string) available in helpers file
    //  - Create deployment (using kubectl or kubernetes node-client)
    //  - Setup event source (deploy redis, or configure azure storage, etc)
    //  - etc
});


// `test 1` and `test 2` will run in parallel.
test('test 1', t => { });
test('test 2', t => { });

// `test 3` will run first, then `test 4`.
// Tests will run in the order they are defined in.
// All serial tests will run first before parallel tests above
test.serial('test 3', t => { });
test.serial('test 4', t => { });

// Tests are expected to finish synchronously, or using async/await
// if you need to use callbacks, then add `.cb` and call `t.end()` when done.
test('test 6', t => { });
test('test 7', async t => { });
test.cb('test 8', t => { t.end() });

test.after.always.cb('clean up always after all tests', t => {
    // Clean up after your test here. without `always` this will only run if all tests are successful.
    t.end();
});

⚠⚠ Important: ⚠⚠ Even thought the cleaning of the resources is expected inside each e2e test file, all test namespaces are cleaned up to ensure not having dangling resources after global e2e execution finishes. For not breaking this behavior, it's mandatory the usage of the function createNamespace(namespace: string) instead of creating them manually.

  • Example test: for example if I want to add a test for redis
import * as sh from 'shelljs';
import test from 'ava';
import { createNamespace } from './helpers';

// you can include template in the file or in another file.
const deployYaml = `apiVersion: apps/v1
kind: Deployment
metadata:
  name: test-deployment
  labels:
    app: test-deployment
spec:
  replicas: 0
  ...
  ...
  `

test.before('install redis and create deployment' t => {
    if (!sh.which('helm')) {
        t.fail('redis tests require helm');
    }

    sh.exec('helm install redis ......'); // install redis to the cluster
    createNamespace("redis-test-deployment")
    sh.exec('kubectl apply -f ....'); // create your deployment
});

test.serial('deployment should scale when adding items in redis list', t => {
    // use node redis client to add stuff to redis.
    // maybe sleep or poll the replica count
    const replicaCount = sh.exec(`kubectl get deployment.apps/test-deployment .. -o jsonpath="{.spec.replicas}"`).stdout;
    t.is('10', replicaCount, 'expecting replica count to be 10');
});

test.after.always('remove redis and my deployment', t => {
    sh.exec('kubectl delete ....');
});
test.serial.only('this will be the only test to run', t => { });