Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Publish v0.50.x documentation #1533

Merged
merged 1 commit into from
Mar 25, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
1 change: 1 addition & 0 deletions docs/sources/.eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,5 +40,6 @@ module.exports = {
__ENV: 'readonly',
__ITER: 'readonly',
open: 'readonly',
window: 'readonly',
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you share the error you get that this is fixing?

Copy link
Member Author

@oleiade oleiade Mar 25, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It addresses stuff like the following: https://github.com/grafana/k6-docs/pull/1533/files#diff-8c065fb2955bda9e9152922061225c2e47321ad1fd0229e2953087a6ae35685bR143

This file is full of them. I looked into the docs, and couldn't find any mention of window related to the browser module; that would explain where it comes from at least. Eslint complains this is unimported, so my "carpet bombing" solution was to essentially tell it to ignore it, I'm open to any alternative 👍🏻

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because the PR is huge, GitHub struggles to open the link I pasted ☝🏻 on my side. Here's the current next folder version of the window usage I referred to:

window.performance.measure('total-action-time', 'page-visit', 'action-completed')

},
};
105 changes: 105 additions & 0 deletions docs/sources/v0.50.x/_index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
---
aliases:
- /docs/k6/
description: 'The k6 documentation covers everything you need to know about k6 OSS, load testing, and performance testing.'
menuTitle: Grafana k6
title: Grafana k6 documentation
weight: -10
---

# Grafana k6 documentation

This documentation will help you go from a total beginner to a seasoned k6 expert!

## Get started

<div class="nav-cards">
<a href={{< relref "./get-started/installation" >}} class="nav-cards__item nav-cards__item--guide">
<h4>🚀 Installation</h4>
<p>Get up and running in no-time, using either a package manager, standalone installer or the official Docker image.</p>
</a>
<a href={{< relref "./get-started/running-k6" >}} class="nav-cards__item nav-cards__item--guide">
<h4>🏎️💨 Running k6</h4>
<p>Write and execute your first load test locally using JavaScript and the k6 API, adding multiple virtual users, checks and ramping stages.</p>
</a>
<a href={{< relref "./get-started/results-output" >}} class="nav-cards__item nav-cards__item--guide">
<h4>⏱ Results output</h4>
<p>Learn how to leverage the results output to gain actionable insight about your application's performance.</p>
</a>
</div>

## What is k6?

Grafana k6 is an open-source load testing tool that makes performance testing easy and productive for engineering teams.
k6 is free, developer-centric, and extensible.

Using k6, you can test the reliability and performance of your systems and catch performance regressions and problems earlier.
k6 will help you to build resilient and performant applications that scale.

k6 is developed by [Grafana Labs](https://grafana.com/) and the community.

Watch the video below to learn more about k6 and why it could be the missing puzzle in your Grafana stack.

{{< youtube id="1mtYVDA2_iQ" >}}

## Key features

k6 is packed with features, which you can learn all about in the documentation.
Key features include:

- [CLI tool](https://grafana.com/docs/k6/<K6_VERSION>/using-k6/k6-options/how-to) with developer-friendly APIs.
- Scripting in JavaScript ES2015/ES6 - with support for [local and remote modules](https://grafana.com/docs/k6/<K6_VERSION>/using-k6/modules)
- [Checks](https://grafana.com/docs/k6/<K6_VERSION>/using-k6/checks) and [Thresholds](https://grafana.com/docs/k6/<K6_VERSION>/using-k6/thresholds) - for goal-oriented, automation-friendly load testing

## Use cases

k6 users are typically Developers, QA Engineers, SDETs, and SREs.
They use k6 for testing the performance and reliability of APIs, microservices, and websites.
Common k6 use cases are:

- **Load testing**

k6 is optimized for minimal resource consumption and designed for running high load tests
([spike](https://grafana.com/docs/k6/<K6_VERSION>/testing-guides/test-types/spike-testing), [stress](https://grafana.com/docs/k6/<K6_VERSION>/testing-guides/test-types/stress-testing), [soak tests](https://grafana.com/docs/k6/<K6_VERSION>/testing-guides/test-types/soak-testing)).

- **Browser testing**

Through [k6 browser](https://grafana.com/docs/k6/<K6_VERSION>/using-k6-browser), you can run browser-based performance testing and catch issues related to browsers only which can be skipped entirely from the protocol level.

- **Chaos and resilience testing**

You can use k6 to simulate traffic as part of your chaos experiments, trigger them from your k6 tests or inject different types of faults in Kubernetes with [xk6-disruptor](https://grafana.com/docs/k6/<K6_VERSION>/javascript-api/xk6-disruptor).

- **Performance and synthetic monitoring**

With k6, you can automate and schedule to trigger tests very frequently with a small load to continuously validate the performance and availability of your production environment.

## Load Testing Manifesto

Our load testing manifesto is the result of having spent years hip deep in the trenches, doing performance- and load testing.
We’ve created it to be used as guidance, helping you in getting your performance testing on the right track!

- [Simple testing is better than no testing](https://k6.io/our-beliefs/#simple-testing-is-better-than-no-testing)
- [Load testing should be goal oriented](https://k6.io/our-beliefs/#load-testing-should-be-goal-oriented)
- [Load testing by developers](https://k6.io/our-beliefs/#load-testing-by-developers)
- [Developer experience is super important](https://k6.io/our-beliefs/#developer-experience-is-super-important)
- [Load test in a pre-production environment](https://k6.io/our-beliefs/#load-test-in-a-pre-production-environment)

## What k6 does not

k6 is a high-performing load testing tool, scriptable in JavaScript. The architectural design to have these capabilities brings some trade-offs:

- **Does not run natively in a browser**

By default, k6 does not render web pages the same way a browser does.
Browsers can consume significant system resources.
Skipping the browser allows running more load within a single machine.

However, with [k6 browser](https://grafana.com/docs/k6/<K6_VERSION>/using-k6-browser), you can interact with real browsers and collect frontend metrics as part of your k6 tests.

- **Does not run in NodeJS**

JavaScript is not generally well suited for high performance.
To achieve maximum performance, the tool itself is written in Go, embedding a JavaScript runtime allowing for easy test scripting.

If you want to import npm modules or libraries using NodeJS APIs, you can [bundle npm modules with webpack](https://grafana.com/docs/k6/<K6_VERSION>/using-k6/modules#bundling-node-modules) and import them in your tests.
10 changes: 10 additions & 0 deletions docs/sources/v0.50.x/examples/_index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
---
title: Examples
weight: 11
---

# Examples

<!-- TODO: Add content -->

{{< section >}}
261 changes: 261 additions & 0 deletions docs/sources/v0.50.x/examples/api-crud-operations.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,261 @@
---
title: 'API CRUD Operations'
description: 'This example covers the usage of k6 to test a REST API CRUD operations.'
weight: 10
---

# API CRUD Operations

The examples showcase the testing of CRUD operations on a REST API.

CRUD refers to the basic operations in a database: Create, Read, Update, and Delete. We can map these operations to HTTP methods in REST APIs:

- _Create_: HTTP `POST` operation to create a new resource.
- _Read_: HTTP `GET` to retrieve a resource.
- _Update_: HTTP `PUT`or `PATCH` to change an existing resource.
- _Delete_: HTTP `DELETE` to remove a resource.

This document has two examples, one that uses the core k6 APIs (`k6/http` and `checks`) and another to show the more recent APIs [`httpx`](https://grafana.com/docs/k6/<K6_VERSION>/javascript-api/jslib/httpx) and [`k6chaijs`](https://grafana.com/docs/k6/<K6_VERSION>/javascript-api/jslib/k6chaijs)).

## Test steps

In the [setup() stage](https://grafana.com/docs/k6/<K6_VERSION>/using-k6/test-lifecycle#setup-and-teardown-stages) we create a user for the [k6 HTTP REST API](https://test-api.k6.io/). We then retrieve and return a bearer token to authenticate the next CRUD requests.

The steps implemented in the [VU stage](https://grafana.com/docs/k6/<K6_VERSION>/using-k6/test-lifecycle#the-vu-stage) are as follows:

1. _Create_ a new resource, a "croc".
2. _Read_ the list of "crocs".
3. _Update_ the name of the "croc" and _read_ the "croc" to confirm the update operation.
4. _Delete_ the "croc" resource.

## Core k6 APIs example

{{< code >}}

```javascript
import http from 'k6/http';
import { check, group, fail } from 'k6';

export const options = {
vus: 1,
iterations: 1,
};

// Create a random string of given length
function randomString(length, charset = '') {
if (!charset) charset = 'abcdefghijklmnopqrstuvwxyz';
let res = '';
while (length--) res += charset[(Math.random() * charset.length) | 0];
return res;
}

const USERNAME = `${randomString(10)}@example.com`; // Set your own email or `${randomString(10)}@example.com`;
const PASSWORD = 'superCroc2019';

const BASE_URL = 'https://test-api.k6.io';

// Register a new user and retrieve authentication token for subsequent API requests
export function setup() {
const res = http.post(`${BASE_URL}/user/register/`, {
first_name: 'Crocodile',
last_name: 'Owner',
username: USERNAME,
password: PASSWORD,
});

check(res, { 'created user': (r) => r.status === 201 });

const loginRes = http.post(`${BASE_URL}/auth/token/login/`, {
username: USERNAME,
password: PASSWORD,
});

const authToken = loginRes.json('access');
check(authToken, { 'logged in successfully': () => authToken !== '' });

return authToken;
}

export default (authToken) => {
// set the authorization header on the session for the subsequent requests
const requestConfigWithTag = (tag) => ({
headers: {
Authorization: `Bearer ${authToken}`,
},
tags: Object.assign(
{},
{
name: 'PrivateCrocs',
},
tag
),
});

let URL = `${BASE_URL}/my/crocodiles/`;

group('01. Create a new crocodile', () => {
const payload = {
name: `Name ${randomString(10)}`,
sex: 'F',
date_of_birth: '2023-05-11',
};

const res = http.post(URL, payload, requestConfigWithTag({ name: 'Create' }));

if (check(res, { 'Croc created correctly': (r) => r.status === 201 })) {
URL = `${URL}${res.json('id')}/`;
} else {
console.log(`Unable to create a Croc ${res.status} ${res.body}`);
return;
}
});

group('02. Fetch private crocs', () => {
const res = http.get(`${BASE_URL}/my/crocodiles/`, requestConfigWithTag({ name: 'Fetch' }));
check(res, { 'retrieved crocs status': (r) => r.status === 200 });
check(res.json(), { 'retrieved crocs list': (r) => r.length > 0 });
});

group('03. Update the croc', () => {
const payload = { name: 'New name' };
const res = http.patch(URL, payload, requestConfigWithTag({ name: 'Update' }));
const isSuccessfulUpdate = check(res, {
'Update worked': () => res.status === 200,
'Updated name is correct': () => res.json('name') === 'New name',
});

if (!isSuccessfulUpdate) {
console.log(`Unable to update the croc ${res.status} ${res.body}`);
return;
}
});

group('04. Delete the croc', () => {
const delRes = http.del(URL, null, requestConfigWithTag({ name: 'Delete' }));

const isSuccessfulDelete = check(null, {
'Croc was deleted correctly': () => delRes.status === 204,
});

if (!isSuccessfulDelete) {
console.log(`Croc was not deleted properly`);
return;
}
});
};
```

{{< /code >}}

## httpx and k6chaijs example

{{< code >}}

```javascript
import { describe, expect } from 'https://jslib.k6.io/k6chaijs/4.3.4.3/index.js';
import { Httpx } from 'https://jslib.k6.io/httpx/0.1.0/index.js';
import {
randomIntBetween,
randomItem,
randomString,
} from 'https://jslib.k6.io/k6-utils/1.2.0/index.js';

export const options = {
// for the example, let's run only 1 VU with 1 iteration
vus: 1,
iterations: 1,
};

const USERNAME = `user${randomIntBetween(1, 100000)}@example.com`; // Set your own email;
const PASSWORD = 'superCroc2019';

const session = new Httpx({ baseURL: 'https://test-api.k6.io' });

// Register a new user and retrieve authentication token for subsequent API requests
export function setup() {
let authToken = null;

describe(`setup - create a test user ${USERNAME}`, () => {
const resp = session.post(`/user/register/`, {
first_name: 'Crocodile',
last_name: 'Owner',
username: USERNAME,
password: PASSWORD,
});

expect(resp.status, 'User create status').to.equal(201);
expect(resp, 'User create valid json response').to.have.validJsonBody();
});

describe(`setup - Authenticate the new user ${USERNAME}`, () => {
const resp = session.post(`/auth/token/login/`, {
username: USERNAME,
password: PASSWORD,
});

expect(resp.status, 'Authenticate status').to.equal(200);
expect(resp, 'Authenticate valid json response').to.have.validJsonBody();
authToken = resp.json('access');
expect(authToken, 'Authentication token').to.be.a('string');
});

return authToken;
}

export default function (authToken) {
// set the authorization header on the session for the subsequent requests
session.addHeader('Authorization', `Bearer ${authToken}`);

describe('01. Create a new crocodile', (t) => {
const payload = {
name: `Croc name ${randomString(10)}`,
sex: randomItem(['M', 'F']),
date_of_birth: '2023-05-11',
};

session.addTag('name', 'Create');
const resp = session.post(`/my/crocodiles/`, payload);

expect(resp.status, 'Croc creation status').to.equal(201);
expect(resp, 'Croc creation valid json response').to.have.validJsonBody();

session.newCrocId = resp.json('id');
});

describe('02. Fetch private crocs', (t) => {
session.clearTag('name');
const resp = session.get('/my/crocodiles/');

expect(resp.status, 'Fetch croc status').to.equal(200);
expect(resp, 'Fetch croc valid json response').to.have.validJsonBody();
expect(resp.json().length, 'Number of crocs').to.be.above(0);
});

describe('03. Update the croc', (t) => {
const payload = {
name: `New croc name ${randomString(10)}`,
};

const resp = session.patch(`/my/crocodiles/${session.newCrocId}/`, payload);

expect(resp.status, 'Croc patch status').to.equal(200);
expect(resp, 'Fetch croc valid json response').to.have.validJsonBody();
expect(resp.json('name'), 'Croc name').to.equal(payload.name);

// read "croc" again to verify the update worked
const resp1 = session.get(`/my/crocodiles/${session.newCrocId}/`);

expect(resp1.status, 'Croc fetch status').to.equal(200);
expect(resp1, 'Fetch croc valid json response').to.have.validJsonBody();
expect(resp1.json('name'), 'Croc name').to.equal(payload.name);
});

describe('04. Delete the croc', (t) => {
const resp = session.delete(`/my/crocodiles/${session.newCrocId}/`);

expect(resp.status, 'Croc delete status').to.equal(204);
});
}
```

{{< /code >}}
10 changes: 10 additions & 0 deletions docs/sources/v0.50.x/examples/bundling-and-transpilation.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
---
title: 'Bundling and transpilation'
redirect: 'https://github.com/k6io/k6-es6/'
description: |
Reference project demonstrating how to use webpack and babel to bundle
node modules or transpile code to ES5.1+ for usage in k6 tests.
weight: 18
---

# Bundling and transpilation
Loading
Loading