-
Notifications
You must be signed in to change notification settings - Fork 223
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
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
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.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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 👍🏻There was a problem hiding this comment.
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 thewindow
usage I referred to:k6-docs/docs/sources/next/using-k6-browser/metrics.md
Line 143 in 423ec4b