paint-brush
How I started doing load testing on GraphQL without writing a single Queryby@estrada9166
2,583 reads
2,583 reads

How I started doing load testing on GraphQL without writing a single Query

by Alejandro EstradaDecember 4th, 2018
Read on Terminal Reader
Read this story w/o Javascript
tldt arrow

Too Long; Didn't Read

Some time ago I was working on a GraphQL project that includes activities and each activity can have some comments with the info of the user that created the comment. The first thing that you might think is that it is a problem of query n + 1 , and yes; it is!

Company Mentioned

Mention Thumbnail

Coin Mentioned

Mention Thumbnail
featured image - How I started doing load testing on GraphQL without writing a single Query
Alejandro Estrada HackerNoon profile picture

Some time ago I was working on a GraphQL project that includes activities and each activity can have some comments with the info of the user that created the comment. The first thing that you might think is that it is a problem of query n + 1 , and yes; it is!

I decided to implement dataloaders but for some reason, there was an error on the implementation, so it wasn’t caching the query and the result was a lot of request to the database. After finding that issue I implemented it on the right way reducing the queries to the database from 46 to 6.

That’s why I decided to create an open source tool that will help me create queries and make load tests just passing my GraphQL schema.

How it works:

easygraphql-load-tester can be used on two ways for the moment; the first one is using .artillery() with a artillery setup, or the second one is .createQuery() that'll create the queries, so you can use with your favorite load tester.

How to use it?

  • Import easygraphql-load-tester package.
  • Read the schema.
  • Initialize the tester, and pass the schema as the first argument.
  • If there are multiples schemas pass an array with the schemas an argument.
  • The second argument are the arguments on the queries, only if there are some of them.
  • Note: If an argument is an array it should be passed as an string, e.g: '["name", "name 2"]'

One schema file

'use strict'

const EasyGraphQLTester = require('easygraphql-load-tester')
const fs = require('fs')
const path = require('path')

const userSchema = fs.readFileSync(path.join(__dirname, 'user.gql'), 'utf8')

const loadTester = new EasyGraphQLLoadTester(userSchema)

Multiples schemas files

'use strict'

const EasyGraphQLTester = require('easygraphql-load-tester')
const fs = require('fs')
const path = require('path')

const userSchema = fs.readFileSync(path.join(__dirname, 'user.gql'), 'utf8')
const familySchema = fs.readFileSync(path.join(__dirname, 'family.gql'), 'utf8')

const loadTester = new EasyGraphQLLoadTester([userSchema, familySchema])

Artillery

To use with artillery, you must have it installed, in case you don’t have it just run:

$ npm install artillery -g

index.js

You should configure your index.js file:

'use strict'

const EasyGraphQLTester = require('easygraphql-load-tester')
const fs = require('fs')
const path = require('path')

const userSchema = fs.readFileSync(path.join(__dirname, 'schema', 'user.gql'), 'utf8')
const familySchema = fs.readFileSync(path.join(__dirname, 'schema', 'family.gql'), 'utf8')

const args = {
  getMeByTestResult: {
    result: 4
  },
  search: {
    id: '1'
  }
}

const loadTester = new EasyGraphQLLoadTester([userSchema, familySchema], args)

const testCases = loadTester.artillery()

module.exports = {
  testCases
}

artillery.yml

The artillery file should have this minimum configuration, you can add yours in case it is needed:

config:
    target: "http://localhost:5000/"
    phases:
      - duration: 5
        arrivalRate: 1
    processor: "./index.js"
  scenarios:
    - name: "GraphQL Query load test"
      flow:
        - function: "testCases"
        - loop:
            - post:
                url: "/"
                json:
                  query: "{{ $loopElement.query }}"
            - log: "----------------------------------"
            - log: "Query: {{ $loopElement.name }}"
          over: cases

In this case the server is running on http://localhost:5000/

How to run it

To run you load test, just run:

$ artillery run artillery.yml

Result

The result is going to be something like this if you apply the basic configuration

All virtual users finished
 Summary report @ 15:03:05(-0500) 2018-11-17
   Scenarios launched:  5
   Scenarios completed: 5
   Requests completed:  40
   RPS sent: 8.95
   Request latency:
     min: 1.2
     max: 13
     median: 2
     p95: 6
     p99: 13
   Scenario counts:
     GraphQL Query load test: 5 (100%)
   Codes:
     200: 40

load testing

one of the queries created

  • if the argument is an array it should be passed as a comment like on the example '["test", “test2”]'.

If you like this package don’t forget to give a ⭐️ on GitHub.

Repo: https://github.com/EasyGraphQL/easygraphql-load-tester

npm: https://www.npmjs.com/package/easygraphql-load-tester

More easygraphql projects: https://github.com/EasyGraphQL

Website: https://easygraphql.com/