artilleryio / artillery

The complete load testing platform. Everything you need for production-grade load tests. Serverless & distributed. Load test with Playwright. Load test HTTP APIs, GraphQL, WebSocket, and more. Use any Node.js module.
https://www.artillery.io
Mozilla Public License 2.0
8.04k stars 511 forks source link

Error when trying to use a before hook with a separated config file #2312

Closed servohatred closed 11 months ago

servohatred commented 11 months ago

I am trying to create function that grabs an auth token using playwright (there is no other way than using the UI) and then injects the session into all the subsecuent scenarios , but it's seems to be failing. I am using this project as a reference https://github.com/KatKmiotek/playwright_artillery_template/blob/main/scenarios/browser_add_to_cart.yml and also this post https://github.com/artilleryio/artillery/discussions/2279. Version info:

VERSION INFO:
Artillery: 2.0.0-38
Node.js:   v20.3.1
OS:        win32

Running this command:

artillery run  -c artillery/config.yaml artillery/scenarios/myscenario.yaml

I expected to see this happen:

all the subsecuent playwright tests to be able to access to the storage state

Instead, this happened: "Before" hook function is executed normally but this happens when it accesses the first scenario in the scenario file

/ TypeError: fn is not a function
    at Array.scenario (C:\Users\myuser\node_modules\artillery-engine-playwright\index.js:200:15)
    at runNextTicks (node:internal/process/task_queues:60:5)
    at process.processImmediate (node:internal/timers:449:9)

Files being used: artillery/config.yaml

config:
  target: "www.test.com"
  processor: "../tests/setup.js"

artillery/scenarios/myscenario.yaml

config:
  target: "www.test.com"
  engines:
    playwright:
      contextOptions:
        storageState: "fixtures/sessions/session.json"
      launchOptions:
        headless: false
  processor: "../tests/scenario.js"
  phases:
        - duration: 1
          arrivalRate: 1
          maxVusers: 1
before:
  flow:
      - function: "getStorageState"

scenarios:
  - name: 'number 1'
    engine: playwright
    flowFunction: "scenarioFn"
    flow: []
    weight: 1

../tests/setup.js

const playwright = require('playwright');

async function getStorageState(context, ee, next) {
// logic to login and write the storage state
  });
  next();
}

module.exports = {
       getStorageState
};

../tests/scenario.js

async function scenarioFn(page, context) {
 // mytest using injected storage state in browser context
}
module.exports = { scenarioFn};
bernardobridge commented 11 months ago

Hi @servohatred 👋,

The reason that's erroring is because it can't find your scenarioFn function. Because you're using -c artillery/config.yaml, your config artillery/config.yaml is overriding the config in artillery/scenarios/myscenario.yaml. Therefore it's looking for the processor in ../tests/setup.js, in which there is no scenarioFn.

Artillery will just use regular NodeJS imports, so all you have to do is make sure to have a single processor file which exports all the functions you need to use. You can still split your code in multiple .js files, if you want, but you have to make sure that the processor function is exporting.

In your case, I'd suggest changing your ../tests/scenario.js file to:

const { getStorageState } = require('PATH_TO_SETUP_FILE');

async function scenarioFn(page, context) {
 // mytest using injected storage state in browser context
}

module.exports = { scenarioFn, getStorageState };

And then dropping your additional config (artillery/config.yaml), so simply run: artillery run artillery/scenarios/myscenario.yaml

Hope that helps!

servohatred commented 11 months ago

Thank you for this, tried this and worked