- node
kubectl
logged into a Kubernetes cluster.- Each scaler test might define additional requirements. For example,
azure-queue.test.ts
requires an env varAZURE_STORAGE_CONNECTION_STRING
npm install
npm test --verbose
npx ava scalers/prometheus.test.ts
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 tokeda
namespace in the cluster, and updates the image tokedacore/keda:main
.After
setup.test.ts
is done, we expect to have a cluster with KEDA setup in namespacekeda
. This is done through apretest
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 insetup.test.ts
.
- 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 ....');
});
- You can see
azure-queue.test.ts
for a full example. - Ava has more options for asserting and writing tests. The docs are very good. https://github.com/avajs/ava/blob/main/docs/01-writing-tests.md
- debugging: when debugging, you can force only 1 test to run by adding
only
to the test definition.
test.serial.only('this will be the only test to run', t => { });