grafana / xk6-browser

k6 extension that adds support for browser automation and end-to-end web testing via the Chrome Devtools Protocol
https://grafana.com/docs/k6/latest/javascript-api/k6-experimental/browser/
GNU Affero General Public License v3.0
328 stars 42 forks source link

get the request information in brownser mode #1081

Open Rbsn-joses opened 9 months ago

Rbsn-joses commented 9 months ago

I would like to know if there is any way to include which requests were made in the test process, I know that status codes are generated for requests made during the test, is there a way to get more information such as endpoints? like we use inspect on google?

saudixit commented 8 months ago

We are also looking for same possibility to access the requests which are being triggered should be available to access through either browser API or methods. i have tried below options already while running k6 browser performance test

Approach 1 : by using waitForEvent(event[, optionsOrPredicate])

As per documentation by k6 Currently this argument is disregarded, and waitForEvent will always wait for 'close' or 'page' events. No more event tracking possible with this approach.

Approach 2 : using PerformanceObserver.

// Create a PerformanceObserver to monitor network requests 

const observer = new PerformanceObserver(logNetworkRequests); 

// Specify the entry types to observe (in this case, 'resource' entries for network requests) observer.observe({ entryTypes: ['resource'] });

observer.observe({ entryTypes: ['resource'] }); 
// Log the current network requests 
logNetworkRequests(performance.getEntriesByType('resource')); 
// Add an event listener for user interactions (e.g., click, keypress) 
document.addEventListener('click', handleUserInteraction);

This approach didn't work because k6 doesn't provide access to window object and Performance Observer is available in the window object

is there any other way through which i can collect all the network requests which are triggered during the browser performance test

Rbsn-joses commented 8 months ago

In this case, how does k6 get the status code and the method used in requests at the time of testing? I thought you already accessed the browser's API to get this information.

ankur22 commented 8 months ago

Hi @Rbsn-joses and @saudixit,

I answered a similar question here, although this feels slightly different.

It sounds like you want your test script to be able to wait and action on all http requests that chrome makes when it navigates to a page during the test runtime. So you're not interested in the measurement values at the end of the test run (e.g. request duration). Is this correct?

I'd like to understand your requirements so we can see what's possible, could you answer these questions:

  1. When do you expect the event to fire?
  2. What information do you need in these events?
  3. What action will your script make when these events are fired?
Rbsn-joses commented 8 months ago

Hello, in this case I wanted k6 to send as metrics, which endpoints or requests were made and which responses they returned, so that, when there is an error status code, it alerts which endpoint also gave the error, it would make it easier when it comes to deal with problems in production, because the script would be to simulate user navigation to test whether all the application's functionalities are responding correctly. An example, use k6 on the login screen and log in as a test, then the metrics are sent to Grafana, method done, http return and which request was made

ankur22 commented 8 months ago

Hi @Rbsn-joses,

So it sounds like you're interested in the implicit http requests your website under test makes when your test navigates to the page, correct? What type of test are running? It doesn't sound like you are doing load test, but maybe an end-to-end test (smoke test)?

I wanted k6 to send as metrics, which endpoints or requests were made and which responses they returned, so that, when there is an error status code, it alerts which endpoint also gave the error

The browser module measures the following for each http request that chrome makes (implicit requests) after navigating to a page and while the test runs on the page:

You need to be explicit in what you are measuring and what the expectations are, and then work with thresholds. An example is a test where it will fail if the thresholds aren't met for the global measurement of all http requests and specific implicit requests too:

import { browser } from 'k6/x/browser';

export const options = {
  scenarios: {
    ui: {
      executor: 'shared-iterations',
      options: {
        browser: {
            type: 'chromium',
        },
      },
    },
  },
  thresholds: {
    'browser_http_req_duration': ['p(90) < 500'],
    'browser_http_req_failed': ['rate == 0'],
    'browser_http_req_duration{url:https://test.k6.io/static/css/site.css}': ['p(90) < 100'],
    'browser_http_req_failed{url:https://test.k6.io/static/css/site.css}': ['rate == 0'],
    'browser_http_req_duration{url:https://test.k6.io/static/js/prisms.js}': ['p(90) < 400'],
    'browser_http_req_failed{url:https://test.k6.io/static/js/prisms.js}': ['rate == 0'],
    'browser_http_req_duration{url:https://test.k6.io/static/favicon.ico}': ['p(90) < 400'],
    'browser_http_req_failed{url:https://test.k6.io/static/favicon.ico}': ['rate == 0'],
  }
}

export default async function() {
  const context = browser.newContext();
  const page = context.newPage();

  try {
    await page.goto('https://test.k6.io/', { waitUntil: 'networkidle' });
  } finally {
    page.close();
  }
}

An example, use k6 on the login screen and log in as a test, then the metrics are sent to Grafana, method done, http return and which request was made

I believe this is possible already, what's missing?

Lerdson commented 8 months ago

@ankur22

Your comment snippet deals with the high level statistics of web traffic but I believe I can justify the low level access requested here.

I'm currently working with a customer on a react project that makes many requests via JS throughout the user journey. To accurately test the load a single user would put on the application, testing on the browser level would be most appropriate, lest we create inaccurate fixed sets of requests open to falling out of sync with the actual application behaviour.

Testing on the browser level is much more resource intensive than on the protocol level. However we can achieve an excellent balance of both worlds by basing our protocol level tests off the back of results from a real browser traversing the application.

If it were possible to generate a request history (maybe a HAR file, maybe not) then we could run an initial browser test to create an accurate user load recording and then follow up with protocol level tests using the data we've just generated. When our application starts querying more/different endpoints we can trivially re-run the browser test and then run many iterations of protocol tests based off that data. No manual intervention from a human creating a new recording, no load tests falling out of sync with actual application demands, and the ability to scale tests much more without the overhead of a real browser doing it.

The way I look at things, we developers are not omniscient when it comes to how users use our creation, so it's always best to go about things the most flexible way possible. Creating a callback system for acting on requests and responses as they occur would be a great way of achieving it. I'm sure I've seen such a feature in the playwright API, so perhaps this request really comes down to finishing off the mimicking of those advanced features within K6 browser.

mdcruz commented 8 months ago

Hi @Lerdson!

One of our k6 champions did a talk this year where he demonstrated using Playwright's recorder functionality, converting it to a k6 browser test, as well as using the recorder to generate a HAR file and then using the community tool, har-to-k6 to convert the HAR file into a k6 protocol test.

You can find the recording here https://grafana.com/about/events/grafanacon/2023/session/automated-performance-modeling-with-nasa-open-mct-grafana-cloud-k6/ (timestamp is 15:20 onwards). Would this be something that can help with your scenario?

Let us know please if this fits what you are looking for 💜

Lerdson commented 8 months ago

Hi @mdcruz

Thanks for that. I hadn't thought of mixing playwright and k6 and that should work nicely. The API similarities between k6 and playwright should make that quite easy indeed.

What I would say is just for the purpose of issue tracking for k6 is it seems so very close to filling this need by itself. Relying on playwright for e2e would seem to invalidate some of the implied goals of k6 as a hybrid load testing/e2e multitool.

I'm not entirely certain the features I mentioned are totally inline with the OP's intentions so perhaps I should open a separate issue just to track the absence of a very handy feature?