Testing Socket.io

Overview

Socket.io is a popular library for building real-time event-based applications. This page covers Socket.io testing functionality in Artillery provided by the built-in Socket.io engine.

Enabling Socket.io support

To use the Socket.io engine in an Artillery scenario, set the engine attribute of a scenario definition to socketio.

scenarios:
    - name: My Socketio test
      engine: socketio # Enable the Socket.io engine
      flow:
          - emit:
              channel: "echo"
              data: "Hello world!"

Socket.io-specific configuration

Socket.io-specific configuration options that may be set in the config section of a test script.

Query

Query parameters can be specified as a string or as a dictionary:

config:
  target: "https://myapp.staging:3002"
  socketio:
    query: "user_id=0xc0ffee&color=blue"

or:

config:
  target: "https://myapp.staging:3002"
  socketio:
    query:
      user_id: "0xc0fee"
      color: "blue"

Path

A custom path may be set.

In this example the virtual users will connect to the admin namespace with the custom path mypath.

config:
  target: "https://myapp.staging:3002/admin"
  socketio:
    path: "/mypath"

Extra headers

Extra headers may be passed with extraHeaders option:

config:
  target: "https://myapp.staging:3002/admin"
  socketio:
    extraHeaders:
      x-client-id: abc

Note: This only works if the default polling transport is used. When other transports are used, extra headers won’t be taken into account by the server.

Transports

You can skip long-polling and specify that a websocket transport be used straightaway:

config:
  target: "https://myapp.staging:3002/admin"
  socketio:
    transports: ["websocket"]

Scenario actions and configuration

The Socket.io engine allows for HTTP actions actions to be used in scenarios alongside emit, which is the main Socket.io action. Looping with loop and pausing execution with think is also supported, see Testing HTTP for details.

emit

Sending Data

The emit action supports the following basic attributes:

  1. channel - the name of the Socket.io channel to emit to
  2. data - the data to emit (as a string). Note that multiple arguments for emit are not supported yet.
  3. namespace - optional namespace to use for this emit

Acknowledgements & Response Validation

Additionally, if you need to wait for an Socket.io acknowledgement response, or validate a response, the following attributes may also be used:

  1. response - optional object if you want to wait for a response:
    • channel - the name of the channel where the response is received.
    • data - the data to verify is in the response
  2. acknowledge - optional object if you want to wait for an acknowledgement

Notes:

  • If you emit to a specific namespace, the response data is expected within the same namespace.
  • Validating an acknowledgement response may be done by setting one of the following attributes on acknowledge:
    1. data - match the response exactly to the value provided
    2. match - match the response with a JSONPath expression; the value of match is expected to be an object with two attributes: json (to specify the part of the response to compare) and value (to specify the expected value)

Example

scenarios:
  - engine: "socketio"
    flow:
      # Emit a message and validate the acknowledgement.
      # We expect the second data argument to be an object,
      # with an "answer" attribute which equals 42:
      - emit:
          channel: "echo"
          data: "ping"
          acknowledge:
            match:
              json: "$.1.answer"
              value: 42
      # Emit a message, and validate the response coming back:
      - emit:
          channel: "echo"
          data: "world"
          response:
            channel: "echoed"
            data: "world"
      - think: 1
      # Emit a message and proceed onto the next step:
      - emit:
          channel: "echo"
          data: "do not care about the response"
      - emit:
          channel: "echo"
          data: "still do not care about the response"
      - think: 1
      - emit:
          channel: "echo"
          data: "emit data to namespace /nsp1"
          namespace: "/nsp1"
      - emit:
          channel: "echo"
          data: "emit data to namespace /nsp2"
          namespace: "/nsp2"
      - think: 1
      - emit:
          channel: "echo"
          data: "hello"
          namespace: "/nsp1"
          response:
            channel: "echoed"
            data: "hello in /nsp1"

Mixing in HTTP Actions

HTTP and Socket.io actions can be combined in the same scenario (a common scenario when testing servers based on Express.js):

  config:
    target: "http://127.0.0.1:9092"
    phases:
      - duration: 10
        arrivalRate: 1
  scenarios:
    - engine: "socketio"
      flow:
        - get:
            url: "/test"
        - emit:
            channel: "echo"
            data: "hello"
            response:
              channel: "echoed"
              data: "hello"
        - emit:
            channel: "echo"
            data: "world"
            response:
              channel: "echoed"
              data: "world"
        - think: 1
        - emit:
            channel: "echo"
            data: "do not care about the response"
        - emit:
            channel: "echo"
            data: "still do not care about the response"
        - think: 1

Connecting Without Sending Any Data

You can use think to emulate clients connecting to the app and listening without sending anything themselves.

config:
  target: "http://127.0.0.1:9092"
  phases:
    - duration: 3600
      arrivalRate: 5
scenarios:
  - engine: "socketio"
    flow:
      - think: 600 # do nothing for 10m and disconnect