Skip to content

Commit

Permalink
Module 3 review (#18)
Browse files Browse the repository at this point in the history
- Fix minor format issues, typos, and broken links.
- Refactor the location for module III section 08. It makes it easier to navigate.
- Apply suggestions from Matt's review

Co-authored-by: Matt Dodson <47385188+MattDodsonEnglish@users.noreply.github.com>
  • Loading branch information
immavalls and MattDodsonEnglish authored Dec 30, 2022
1 parent 341d392 commit e4853c5
Show file tree
Hide file tree
Showing 20 changed files with 144 additions and 119 deletions.
20 changes: 11 additions & 9 deletions Modules/III-k6-Intermediate/02-Dynamic-correlation-in-k6.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,18 @@ In the previous section, you learned [different approaches to debugging a script

## What is correlation?

Correlation is the process of extracting a value from a previous HTTP response and using that value in the next HTTP request.
Data correlation is the process of extracting a value from a previous HTTP response and using that value in the next HTTP request.

The request flow of a user accessing an application might look like this:
- Step 1. HTTP GET request for *My Messages* page.
- Step 2. HTTP POST request with username and password

In the previous section, the script attempted to log in immediately (skipping Step 1 and going straight to Step 2), but after applying some debugging techniques, you discovered that the response code is an HTTP 403 Forbidden, with `error: invalid csrf token` in the response body.
In the [previous section](./01-How-to-debug-k6-load-testing-scripts.md), the script attempted to log in immediately (skipping Step 1 and going straight to Step 2), but after applying some debugging techniques, you discovered that the response code is an HTTP 403 Forbidden, with `error: invalid csrf token` in the response body.

To correct this error and accurately mimic user behavior, the script must:
- Save the response to the request in Step 1.
- Extract the csrf token from Step 1.
- Pass the csrf token when requesting Step 2.
- Extract the [Cross-Site Request Forgery (CSFR)](https://owasp.org/www-community/attacks/csrf) token from Step 1.
- Pass the CSFR token when requesting Step 2.

Since the script starts with Step 2, you need to add another request for Step 1.

Expand Down Expand Up @@ -135,7 +135,7 @@ default ✓ [======================================] 1 VUs 00m00.6s/10m0s 1/1
iterations.....................: 1 1.646844/s
```
Now we're getting somewhere! The entire HTML body of the response is saved in the variable `response`.
Now we're getting somewhere! The entire HTML body of the response is saved in the variable [`response`](https://k6.io/docs/javascript-api/k6-http/response/).
## Extracting the value from the response
Expand Down Expand Up @@ -173,7 +173,9 @@ If you're stuck, compare your script against the script at the end of this secti
You suspect there may be a dynamic value that you need to correlate from a previous response and send with your request. What's the best way to confirm this suspicion?
A: Use DevTools to look at the network traffic as you perform the action, then look at the parameters being passed with the successful request.
B: Record the script and run it using k6.
C: Add a check for the word `csrftoken` to see if there are any being returned in the response.
### Question 2
Expand All @@ -187,19 +189,18 @@ check(response, {
})
```
B: `let rand = Math.floor(Math.random() * 2);`
C: `--http-debug=full`
Answer: C
C: `--http-debug=full`
### Question 3
Why might replaying a recorded script yield errors?
A: Some steps may require dynamic values extracted from earlier responses.
B: There were no checks defined in the script.
C: Running with multiple users may exert unnecessary load on the application server.
Answer: A
C: Running with multiple users may exert unnecessary load on the application server.
## The script
```js
Expand Down Expand Up @@ -236,3 +237,4 @@ export default function() {
1. A. DevTools is a great way to run through the request and response pairs of a web application, step by step. B would likely not give much useful information beyond errors, and C is too specific-- there are other dynamic parameters beyond tokens that may cause errors if not properly handled.
2. C. Using the `http-debug` flag may be useful because it prints out all the response and request information. If there is too much information to be useful, consider using DevTools or [a proxy](https://k6.io/blog/k6-load-testing-debugging-using-a-web-proxy/) instead.
3. A.
6 changes: 3 additions & 3 deletions Modules/III-k6-Intermediate/03-Workload-modeling.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,9 @@ Test parameters are values that affect how your load-testing script is executed.
- Number of iterations
- Load profile, including stages during the test

Each of these parameters influence the amount and type of load that is simulated.
Each of these parameters influences the amount and type of load that is simulated.

Check out [k6 Load Test Options](../II-k6-Foundations/06-k6-Load-Test-Options.md) for more information on these parameters, or [Setting load profiles with executors](08-Setting-load-profiles-with-executors/Setting-load-profiles-with-executors.md) for instructions on how to implement these in k6.
Check out [k6 Load Test Options](../II-k6-Foundations/06-k6-Load-Test-Options.md) for more information on these parameters, or [Setting load profiles with executors](08-Setting-load-profiles-with-executors.md) for instructions on how to implement these in k6.

### Think time and pacing

Expand All @@ -48,7 +48,7 @@ See [Adding think time using sleep](../II-k6-Foundations/05-Adding-think-time-us

In web applications, static resources refer to images, client-side scripts, fonts, and other files embedded onto a page. If you want your script to access that page, you have to decide whether you want the script to also download those resources.

Downloading static resources makes the script more realistic if you want to simulate an end-user behavior, because web browsers automatically download them. However, if you want to download only the HTML of the page (for example, perhaps because the images are served by a [CDN](Performance-Testing-Terminology.md#CDN) that you don't want to test), it may be more prudent *not* to download the static resources.
Downloading static resources makes the script more realistic if you want to simulate an end-user behavior, because web browsers automatically download them. However, if you want to download only the HTML of the page (for example, perhaps because the images are served by a CDN (Content Delivery Network) that you don't want to test), it may be more prudent *not* to download the static resources.

### Parallel requests

Expand Down
12 changes: 9 additions & 3 deletions Modules/III-k6-Intermediate/04-Adding-test-data.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ After defining arrays, you can generate a random number to randomly pick a value

```js
// Get random username and password from array
let rand = Math.floor(Math.random() * 2);
let rand = Math.floor(Math.random() * usernameArr.length);
let username = usernameArr[rand];
let password = passwordArr[rand];
console.log('username: ' + username, ' / password: ' + password);
Expand All @@ -41,7 +41,7 @@ An array is best used for very short lists of text, as in this example, or for d

## CSV Files

CSV files are lists of information that made up of _comma-separated values_ and are saved separately from the script.
CSV files are lists of information that are made up of _comma-separated values_ and are saved separately from the script.

Below is an example CSV file named `users.csv` containing usernames and passwords:
```plain
Expand Down Expand Up @@ -86,7 +86,7 @@ Below is a JSON file called `users.json`:
You can then use it in your k6 script like this:

```js
const jsonData = JSON.parse(open('./data/users.json')).users;
const jsonData = JSON.parse(open('./users.json')).users;

export default function () {
let rand = Math.floor(Math.random() * jsonData.length);
Expand Down Expand Up @@ -134,23 +134,29 @@ Test data can also refer to files that need to be uploaded as part of the scenar
In which of the following situations would it be advisable to add test data to your load testing scripts?

A: Your application locks out a user account after three logins in a short amount of time.

B: You want to see how the application behaves when the same user refreshes a page repeatedly.

C: Both A and B.

### Question 2

You have a CSV file with 100 MB of personal information that you'd like to use as test data. Which of the following approaches is the best one to use?

A: SharedArray

B: Simple array

C: JSON files because the CSV is better converted into JSON

### Question 3

All the examples on this page include a `Math.random()` function to randomly select an element from the data file. In which situations might you want to remove this randomization?

A: When you want to prevent server-side caching.

B: When you want to guarantee that each element of test data has been sequentially utilized by the script.

C: When you want to make your tests as realistic as possible.

### Answers
Expand Down
17 changes: 11 additions & 6 deletions Modules/III-k6-Intermediate/05-Parallel-requests-in-k6.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ This screenshot shows the Network panel in Chrome DevTools while a site is loade

The orange arrow points to three parallel requests. This indicates that the client (in this case, the browser) sent three different HTTP requests at the same time.

Parallel requests influence load testing results because it increases test throughput. Increased test throughput affects load testing in two ways:
Parallel requests influence load testing results because they increase test throughput. Increased test throughput affects load testing in two ways:
- First, sending requests in parallel takes less time than sending them sequentially, so the load generator may experience higher resource utilization over a shorted amount of time.
- Second, parallel requests also get to the application server faster, which could increase resource utilization on the server side as well.

Expand Down Expand Up @@ -38,16 +38,15 @@ export default function () {
['GET', domain + '/'],
['GET', domain + '/static/css/site.css'],
['GET', domain + '/static/js/prisms.js'],
['GET', domain + '/static.favicon.ico'],
['GET', domain + '/static/img/logo.png'],
['GET', domain + '/static/favicon.ico']
])
check(responses[0], {
'Homepage successfully loaded': (r) => r.body.includes("Collection of simple web-pages suitable for load testing"),
});
}
```

The script above sends five requests in parallel, all of which are embedded into the homepage. Each of the responses is saved as an array in the variable `responses`, and the check verifies that the very first element of that array, `responses[0]`, the homepage, contains text that proves that the script successfully retrieved the HTML body.
The script above sends four requests in parallel, all of which are embedded into the homepage. Each of the responses is saved as an array in the variable `responses`, and the check verifies that the very first element of that array, `responses[0]`, the homepage, contains text that proves that the script successfully retrieved the HTML body.

You can batch requests even if they are not all HTTP GET requests. For example, you could use HTTP GET and HTTP POST requests in the same batch. You can find [more information here](https://k6.io/docs/javascript-api/k6-http/batch-requests/).

Expand All @@ -58,27 +57,33 @@ You can batch requests even if they are not all HTTP GET requests. For example,
Which of the following statements is true?

A: Whether or not to use parallel requests depends on your test scenario.

B: Using parallel requests is always recommended as a performance testing best practice.

C: Parallel requests should always be used for testing websites.

### Question 2

Which of the following might be a side effect of you including parallel requests in your script?

A: Your load generator sends fewer requests when some are batched.

B: Your load test's executed requests per second (rps) will increase.

C: The application server caches batched requests and performance is improved.

### Question 3

When might you _not_ want to use parallel requests?

A: When you want to increase the amount of requests your test is sending
A: When you want to increase the number of requests your test is sending

B: When you have requests using multiple types of HTTP methods

C: When you're testing API endpoints

### Answers

1. A. Parallel requests are sometimes, but not always, useful. For example, they are useful if you're trying to simulate a user accessing a web app on a browser, but not so useful if you're trying to mimic sequential requests to an API endpoint.
2. B. All other things being equal, increasing the parallelism of your requests will increase the throughput (rps) of your test.
3. A. The key here is your objective, not *what* you're testing. If you want to increase your test throughput (the amount of requests sent by k6), parallel requests *would* be a valid way to do that. Whether you're using multiple HTTP methods or testing API endpoints is beside the point.
3. A. The key here is your objective, not *what* you're testing. If you want to increase your test throughput (the number of requests sent by k6), parallel requests *would* be a valid way to do that. Whether you're using multiple HTTP methods or testing API endpoints is beside the point.
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
If you've written a load testing script before, you might be familiar with the term [transaction](Modules/Performance-Testing-Terminology.md#Transaction). A transaction in load testing is a request or group of requests that correspond to a single action by the user.
# Organizing Code in k6 by transaction groups and tags

If you've written a load testing script before, you might be familiar with the term transaction. A transaction in load testing is a request or group of requests that correspond to a single action by the user.

For example, you might have a transaction called `01_Go_to_homepage` that consists of a user going to your website main page for the first time. That transaction would then include GET requests for the main HTML, in addition to embedded resources like scripts, images, and fonts.

Expand Down Expand Up @@ -243,7 +245,9 @@ Modular scripting involves breaking apart your k6 test script into multiple scri
Which technique is the best to use as a load testing transaction?

A: Groups

B: Tags

C: URL grouping

### Question 2
Expand Down Expand Up @@ -277,15 +281,19 @@ export default function () {
What is the value of the `name` tag for the HTTP request?

A: `Homepage`

B: `HTML`

C: `http://ecommerce.k6.io/`

### Question 3

Which of the following is an advantage of using functions to organize your k6 test script?

A: Functions aggregate all the metrics within a function and report them under a single name.

B: Functions give you the freedom to create test scenarios that correspond to user journeys for your application.

C: Functions tag all requests with the function name so you can filter by function in the test results.

### Answers
Expand Down
36 changes: 20 additions & 16 deletions Modules/III-k6-Intermediate/07-Setup-and-Teardown-functions.md
Original file line number Diff line number Diff line change
Expand Up @@ -110,22 +110,6 @@ Here are some things that you may want to do during setup:

Anything returned in the setup function will be saved and can be passed on to the default and teardown functions like this:

```js
export function setup() {
return { v: 1 };
}

export default function (data) {
console.log(JSON.stringify(data));
}

export function teardown(data) {
if (data.v != 1) {
throw new Error('incorrect data: ' + JSON.stringify(data));
}
}
```

The full k6 API is available during setup, including making HTTP requests.

### Teardown
Expand All @@ -138,13 +122,33 @@ export function teardown() {

The teardown function is similar to the setup function in that it runs only once per test (not per VU), but it runs at the _end_ of the test. Any teardown code will be the last to be executed by k6 before test results are generated.

If the `setup()` function ends abnormally, the `teardown()` function isn't called. Consider adding logic to the setup for proper cleanup if necessary.

Here are some things you might want to do during teardown:
- Logging out any active users
- Deleting test data generated during test execution
- Putting the test environment back to the state it was in before the test

The full k6 API is available during teardown, including making HTTP requests.

```js
export function setup() {
return { v: 1 };
}

export default function (data) {
console.log(JSON.stringify(data));
}

export function teardown(data) {
if (data.v != 1) {
throw new Error('incorrect data: ' + JSON.stringify(data));
}
}
```

Check the [test lifecycle documentation](https://k6.io/docs/using-k6/test-lifecycle/) for more details.

## Setup and teardown while debugging

You may want to skip setup and teardown in some situations, such as when you're debugging your script or running a small shakeout test that doesn't require data generation.
Expand Down
Loading

0 comments on commit e4853c5

Please sign in to comment.