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.


Important - Socket.IO server versions

The official Socket.IO engine for Artillery uses the v2.x client, which may not work if you’re using Socket.IO v3.x and above on the server. Please see the v2.x to v3.x migration guide for more details.

We are working on adding support for Socket.IO v3.x in Artillery. In the meantime, if you need v3.x support, please use artillery-engine-socketio-v3.

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 Socket.IO test
engine: socketio # Enable the Socket.IO engine
flow:
- emit:
channel: "echo"
data: "Hello world!"

Socket.IO-specific configuration

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"
config:
target: "https://myapp.staging:3002"
socketio:
query:
user_id: "0xc0fee"
color: "blue"

Path

A custom path may be set with the path option.

In the following 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"

The extraHeaders option only works if the default polling transport is used. When using other transports, extra headers won't be taken into account by the server.

WebSocket transports only

You can skip long-polling by using the transports option to specify WebSocket transport:

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 attributes:

  1. channel - The name of the Socket.IO channel to emit an event.
  2. data - The data to emit as a string.
  3. namespace - Optional namespace to use for emitting the event.

Multiple arguments for the emit actions are not supported yet.

Acknowledgements & Response Validation

Additionally, if you need to wait for an Socket.IO acknowledgement response or validate a response, you can also use the following attributes:

  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.

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:

  • data - Match the response exactly to the value provided.
  • match - Match the response with a JSONPath expression. This attribute expects an object with two attributes:
    • json - The part of the response to compare.
    • value - The expected value.

Examples

Emit a single event:

config:
target: "https://socketio.test/"
phases:
- duration: 60
arrivalRate: 25

scenarios:
- name: "Emit an event"
engine: socketio
flow:
- emit:
channel: "echo"
data: "Hello from Artillery"

Emit an event and validate a response:

config:
target: "https://socketio.test/"
phases:
- duration: 60
arrivalRate: 25

scenarios:
- name: "Emit an event"
engine: socketio
flow:
- emit:
channel: "echo"
data: "Hello from Artillery"
response:
channel: "echoResponse"
data: "Hello from Artillery"

Emit an event and validate an acknowledgement:

config:
target: "https://socketio.test/"
phases:
- duration: 60
arrivalRate: 25

scenarios:
- name: "Emit and validate acknowledgement"
engine: socketio
flow:
- emit:
channel: "userDetails"
acknowledge:
match:
json: "$.0.name"
value: "Artillery"

Emit data to a namespace:

config:
target: "https://socketio.test/"
phases:
- duration: 60
arrivalRate: 25

scenarios:
- name: "Emit to /namespace1"
engine: socketio
emit:
namespace: "/namespace1"
channel: "echo"
data: "Emitting data to namespace"

Mixing in HTTP Actions

A single scenario can combine both HTTP and Socket.IO actions.

The following example is a common scenario when testing servers based on Express.js:

config:
target: "http://lab.artillery.io"
phases:
- duration: 10
arrivalRate: 1

scenarios:
- engine: "socketio"
flow:
- get:
url: "/movies/10"
capture:
- json: "$.title"
as: "title"
- json: "$.genre"
as: "genre"
- log: "Emitting captured values: {{ title }}, {{ genre }}"
- emit:
channel: "echo"
data: "{{ title }}"
# validate the received response
response:
channel: "echoResponse"
data: "{{ title }}"
- emit:
channel: "echo"
data: "{{ genre }}"
response:
channel: "echoResponse"
data: "{{ genre }}"
- 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

Try it live!

Connecting Without Sending Any Data

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

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

Debugging

If you’re having issues getting your test scenarios to complete successfully, you can print out helpful debugging messages using the DEBUG environment variable.

Print errors

Set DEBUG=socketio when running your tests to view any errors that occurred during the test run.

DEBUG=socketio artillery run my-script.yaml