-
Notifications
You must be signed in to change notification settings - Fork 223
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #1533 from grafana/release-v0.50.0
Publish v0.50.x documentation
- Loading branch information
Showing
624 changed files
with
50,890 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -40,5 +40,6 @@ module.exports = { | |
__ENV: 'readonly', | ||
__ITER: 'readonly', | ||
open: 'readonly', | ||
window: 'readonly', | ||
}, | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
--- | ||
title: Examples | ||
weight: 11 | ||
--- | ||
|
||
# Examples | ||
|
||
<!-- TODO: Add content --> | ||
|
||
{{< section >}} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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
10
docs/sources/v0.50.x/examples/bundling-and-transpilation.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
Oops, something went wrong.