Skip to content

Commit 07d4a74

Browse files
committed
Create v1.2.x release
1 parent cdafc65 commit 07d4a74

File tree

920 files changed

+72294
-0
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

920 files changed

+72294
-0
lines changed

docs/sources/k6/v1.2.x/_index.md

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
---
2+
aliases:
3+
- /docs/k6/
4+
description: 'The k6 documentation covers everything you need to know about k6 OSS, load testing, and performance testing.'
5+
menuTitle: Grafana k6
6+
title: Grafana k6
7+
weight: -10
8+
hero:
9+
title: Grafana k6
10+
level: 1
11+
image: /media/docs/k6/GrafanaLogo_k6_orange_icon.svg
12+
width: 100
13+
height: 100
14+
description: Grafana k6 is an open-source, developer-friendly, and extensible load testing tool. k6 allows you to prevent performance issues and proactively improve reliability.
15+
cards:
16+
title_class: pt-0 lh-1
17+
items:
18+
- title: Run your first k6 test
19+
href: ./get-started/
20+
description: Learn how to install the k6 CLI, run your first k6 test, and view metric results in the terminal.
21+
height: 24
22+
- title: Using k6
23+
href: ./using-k6/
24+
description: Learn about k6 options and concepts such as thresholds, metrics, lifecycle hooks, and more.
25+
height: 24
26+
- title: Testing guides
27+
href: ./testing-guides/
28+
description: Discover how to plan and define your performance testing strategy with these guides.
29+
height: 24
30+
- title: k6 JavaScript API
31+
href: ./javascript-api/
32+
description: Explore the k6 APIs through their documentation and examples.
33+
height: 24
34+
- title: Explore k6 extensions
35+
href: ./extensions/
36+
description: Have a particular testing need? Find k6 extensions that extend the native k6 functionality.
37+
height: 24
38+
- title: k6 script examples
39+
href: ./examples/
40+
description: Learn how to write test scripts with this list of common k6 examples.
41+
height: 24
42+
- title: Grafana Cloud k6
43+
href: https://grafana.com/docs/grafana-cloud/testing/k6/
44+
description: Leverage the k6 OSS capabilities in Grafana Cloud, with built-in dashboards, insights into your application performance, and the ability to bring together teams in one place to resolve issues faster.
45+
height: 24
46+
- title: k6 Studio
47+
href: https://grafana.com/docs/k6-studio/
48+
description: Use the k6 Studio desktop application to quickly generate test scripts using a visual interface.
49+
height: 24
50+
---
51+
52+
{{< docs/hero-simple key="hero" >}}
53+
54+
---
55+
56+
## Overview
57+
58+
Using k6, you can test the reliability and performance of your application and infrastructure.
59+
60+
k6 helps engineering teams prevent errors and SLO breaches, enabling them to build resilient and high-performing applications that scale.
61+
62+
Engineering teams, including Developers, QA Engineers, SDETs, and SREs, commonly use k6 for:
63+
64+
- **Load and performance testing**
65+
66+
k6 is optimized for minimal resource consumption and designed for running high-load performance tests such as
67+
[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), or [soak tests](https://grafana.com/docs/k6/<K6_VERSION>/testing-guides/test-types/soak-testing).
68+
69+
- **Browser performance testing**
70+
71+
Through the [k6 browser API](https://grafana.com/docs/k6/<K6_VERSION>/using-k6-browser), you can run browser-based performance tests and collect browser metrics to identify performance issues related to browsers. Additionally, you can mix browser tests with other performance tests to get a comprehensive view of your website's performance.
72+
73+
- **Performance and synthetic monitoring**
74+
75+
You can schedule tests to run with minimal load very frequently, continuously validating the performance and availability of your production environment. For this, you can also use [Grafana Cloud Synthetic Monitoring](https://grafana.com/docs/grafana-cloud/testing/synthetic-monitoring/create-checks/checks/k6/), which supports running k6 scripts.
76+
77+
- **Automation of performance tests**
78+
79+
k6 integrates seamlessly with CI/CD and automation tools, enabling engineering teams to [automate performance testing](https://grafana.com/docs/k6/<K6_VERSION>/testing-guides/automated-performance-testing/) as part of their development and release cycle.
80+
81+
- **Chaos and resilience testing**
82+
83+
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>/testing-guides/injecting-faults-with-xk6-disruptor/xk6-disruptor).
84+
85+
- **Infrastructure testing**
86+
87+
With [k6 extensions](https://grafana.com/docs/k6/<K6_VERSION>/extensions/), you can add support to k6 for new protocols or use a particular client to directly test individual systems within your infrastructure.
88+
89+
Watch the video below to learn more about k6 and why it could be the missing puzzle in your Grafana stack.
90+
91+
{{< youtube id="1mtYVDA2_iQ" >}}
92+
93+
## Explore
94+
95+
{{< card-grid key="cards" type="simple" >}}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
---
2+
title: Examples
3+
weight: 800
4+
---
5+
6+
# Examples
7+
8+
<!-- TODO: Add content -->
9+
10+
{{< section >}}
Lines changed: 267 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,267 @@
1+
---
2+
title: 'API CRUD Operations'
3+
description: 'This example covers the usage of k6 to test a REST API CRUD operations.'
4+
weight: 10
5+
---
6+
7+
# API CRUD Operations
8+
9+
The examples showcase the testing of CRUD operations on a REST API.
10+
11+
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:
12+
13+
- _Create_: HTTP `POST` operation to create a new resource.
14+
- _Read_: HTTP `GET` to retrieve a resource.
15+
- _Update_: HTTP `PUT`or `PATCH` to change an existing resource.
16+
- _Delete_: HTTP `DELETE` to remove a resource.
17+
18+
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)).
19+
20+
## Test steps
21+
22+
In the [setup() stage](https://grafana.com/docs/k6/<K6_VERSION>/using-k6/test-lifecycle#setup-and-teardown-stages) we create a user for [QuickPizza](https://quickpizza.grafana.com). We then retrieve and return a bearer token to authenticate the next CRUD requests.
23+
24+
The steps implemented in the [VU stage](https://grafana.com/docs/k6/<K6_VERSION>/using-k6/test-lifecycle#the-vu-stage) are as follows:
25+
26+
1. _Create_ a new resource, a pizza rating.
27+
2. _Read_ the list of ratings.
28+
3. _Update_ the rating's stars (e.g. to 5 stars) and _read_ the rating to confirm the update operation.
29+
4. _Delete_ the rating resource.
30+
31+
## Core k6 APIs example
32+
33+
{{< code >}}
34+
35+
```javascript
36+
import http from 'k6/http';
37+
import { check, group, fail } from 'k6';
38+
39+
export const options = {
40+
vus: 1,
41+
iterations: 1,
42+
};
43+
44+
// Create a random string of given length
45+
function randomString(length, charset = '') {
46+
if (!charset) charset = 'abcdefghijklmnopqrstuvwxyz';
47+
let res = '';
48+
while (length--) res += charset[(Math.random() * charset.length) | 0];
49+
return res;
50+
}
51+
52+
const USERNAME = `${randomString(10)}@example.com`; // Set your own email or `${randomString(10)}@example.com`;
53+
const PASSWORD = 'secret';
54+
55+
const BASE_URL = 'https://quickpizza.grafana.com';
56+
57+
// Register a new user and retrieve authentication token for subsequent API requests
58+
export function setup() {
59+
const res = http.post(
60+
`${BASE_URL}/api/users`,
61+
JSON.stringify({
62+
username: USERNAME,
63+
password: PASSWORD,
64+
})
65+
);
66+
67+
check(res, { 'created user': (r) => r.status === 201 });
68+
69+
const loginRes = http.post(
70+
`${BASE_URL}/api/users/token/login`,
71+
JSON.stringify({
72+
username: USERNAME,
73+
password: PASSWORD,
74+
})
75+
);
76+
77+
const authToken = loginRes.json('token');
78+
check(authToken, { 'logged in successfully': () => authToken.length > 0 });
79+
80+
return authToken;
81+
}
82+
83+
export default function (authToken) {
84+
// set the authorization header on the session for the subsequent requests
85+
const requestConfigWithTag = (tag) => ({
86+
headers: {
87+
Authorization: `Bearer ${authToken}`,
88+
},
89+
tags: Object.assign(
90+
{},
91+
{
92+
name: 'PrivateRatings',
93+
},
94+
tag
95+
),
96+
});
97+
98+
let URL = `${BASE_URL}/api/ratings`;
99+
100+
group('01. Create a new rating', () => {
101+
const payload = {
102+
stars: 2,
103+
pizza_id: 1, // Pizza ID 1 already exists in the database.
104+
};
105+
106+
const res = http.post(URL, JSON.stringify(payload), requestConfigWithTag({ name: 'Create' }));
107+
108+
if (check(res, { 'Rating created correctly': (r) => r.status === 201 })) {
109+
URL = `${URL}/${res.json('id')}`;
110+
} else {
111+
console.log(`Unable to create rating ${res.status} ${res.body}`);
112+
return;
113+
}
114+
});
115+
116+
group('02. Fetch my ratings', () => {
117+
const res = http.get(`${BASE_URL}/api/ratings`, requestConfigWithTag({ name: 'Fetch' }));
118+
check(res, { 'retrieve ratings status': (r) => r.status === 200 });
119+
check(res.json(), { 'retrieved ratings list': (r) => r.ratings.length > 0 });
120+
});
121+
122+
group('03. Update the rating', () => {
123+
const payload = { stars: 5 };
124+
const res = http.put(URL, JSON.stringify(payload), requestConfigWithTag({ name: 'Update' }));
125+
const isSuccessfulUpdate = check(res, {
126+
'Update worked': () => res.status === 200,
127+
'Updated stars number is correct': () => res.json('stars') === 5,
128+
});
129+
130+
if (!isSuccessfulUpdate) {
131+
console.log(`Unable to update the rating ${res.status} ${res.body}`);
132+
return;
133+
}
134+
});
135+
136+
group('04. Delete the rating', () => {
137+
const delRes = http.del(URL, null, requestConfigWithTag({ name: 'Delete' }));
138+
139+
const isSuccessfulDelete = check(null, {
140+
'Rating was deleted correctly': () => delRes.status === 204,
141+
});
142+
143+
if (!isSuccessfulDelete) {
144+
console.log('Rating was not deleted properly');
145+
return;
146+
}
147+
});
148+
}
149+
```
150+
151+
{{< /code >}}
152+
153+
## httpx and k6chaijs example
154+
155+
{{< code >}}
156+
157+
```javascript
158+
import { describe, expect } from 'https://jslib.k6.io/k6chaijs/4.3.4.3/index.js';
159+
import { Httpx } from 'https://jslib.k6.io/httpx/0.1.0/index.js';
160+
import {
161+
randomIntBetween,
162+
randomItem,
163+
randomString,
164+
} from 'https://jslib.k6.io/k6-utils/1.2.0/index.js';
165+
166+
export const options = {
167+
// for the example, let's run only 1 VU with 1 iteration
168+
vus: 1,
169+
iterations: 1,
170+
};
171+
172+
const USERNAME = `user${randomIntBetween(1, 100000)}@example.com`; // Set your own email;
173+
const PASSWORD = 'secret';
174+
175+
const session = new Httpx({ baseURL: 'https://quickpizza.grafana.com' });
176+
177+
// Register a new user and retrieve authentication token for subsequent API requests
178+
export function setup() {
179+
let authToken = null;
180+
181+
describe(`setup - create a test user ${USERNAME}`, () => {
182+
const resp = session.post(
183+
`/api/users`,
184+
JSON.stringify({
185+
username: USERNAME,
186+
password: PASSWORD,
187+
})
188+
);
189+
190+
expect(resp.status, 'User create status').to.equal(201);
191+
expect(resp, 'User create valid json response').to.have.validJsonBody();
192+
});
193+
194+
describe(`setup - Authenticate the new user ${USERNAME}`, () => {
195+
const resp = session.post(
196+
`/api/users/token/login`,
197+
JSON.stringify({
198+
username: USERNAME,
199+
password: PASSWORD,
200+
})
201+
);
202+
203+
expect(resp.status, 'Authenticate status').to.equal(200);
204+
expect(resp, 'Authenticate valid json response').to.have.validJsonBody();
205+
authToken = resp.json('token');
206+
expect(authToken, 'Authentication token').to.be.a('string');
207+
});
208+
209+
return authToken;
210+
}
211+
212+
export default function (authToken) {
213+
// set the authorization header on the session for the subsequent requests
214+
session.addHeader('Authorization', `Bearer ${authToken}`);
215+
216+
describe('01. Create a new rating', (t) => {
217+
const payload = {
218+
stars: 2,
219+
pizza_id: 1, // Pizza ID 1 already exists in the database
220+
};
221+
222+
session.addTag('name', 'Create');
223+
const resp = session.post(`/api/ratings`, JSON.stringify(payload));
224+
225+
expect(resp.status, 'Rating creation status').to.equal(201);
226+
expect(resp, 'Rating creation valid json response').to.have.validJsonBody();
227+
228+
session.newRatingId = resp.json('id');
229+
});
230+
231+
describe('02. Fetch my ratings', (t) => {
232+
session.clearTag('name');
233+
const resp = session.get('/api/ratings');
234+
235+
expect(resp.status, 'Fetch ratings status').to.equal(200);
236+
expect(resp, 'Fetch ratings valid json response').to.have.validJsonBody();
237+
expect(resp.json('ratings').length, 'Number of ratings').to.be.above(0);
238+
});
239+
240+
describe('03. Update the rating', (t) => {
241+
const payload = {
242+
stars: 5,
243+
};
244+
245+
const resp = session.patch(`/api/ratings/${session.newRatingId}`, JSON.stringify(payload));
246+
247+
expect(resp.status, 'Rating patch status').to.equal(200);
248+
expect(resp, 'Fetch rating valid json response').to.have.validJsonBody();
249+
expect(resp.json('stars'), 'Stars').to.equal(payload.stars);
250+
251+
// read rating again to verify the update worked
252+
const resp1 = session.get(`/api/ratings/${session.newRatingId}`);
253+
254+
expect(resp1.status, 'Fetch rating status').to.equal(200);
255+
expect(resp1, 'Fetch rating valid json response').to.have.validJsonBody();
256+
expect(resp1.json('stars'), 'Stars').to.equal(payload.stars);
257+
});
258+
259+
describe('04. Delete the rating', (t) => {
260+
const resp = session.delete(`/api/ratings/${session.newRatingId}`);
261+
262+
expect(resp.status, 'Rating delete status').to.equal(204);
263+
});
264+
}
265+
```
266+
267+
{{< /code >}}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
---
2+
aliases:
3+
- ./bundling-and-transpilation # docs/k6/<K6_VERSION>/examples/bundling-and-transpilation
4+
title: 'Bundling and transpiling'
5+
description: |
6+
Refer to the JavaScript and TypeScript compatibility mode page for more details on how to use TypeScript with k6
7+
weight: 18
8+
---
9+
10+
# Bundling and transpiling
11+
12+
For more details about bundling and transpiling, refer to [JavaScript and TypeScript compatibility mode](https://grafana.com/docs/k6/<K6_VERSION>/using-k6/javascript-typescript-compatibility-mode/).

0 commit comments

Comments
 (0)