Giter Club home page Giter Club logo

easygraphql-load-tester's Introduction

easygraphql-load-tester
easygraphql-load-tester

easygraphql-load-tester is a node library created to make load testing on GraphQL based on the schema; it'll create a bunch of queries, that are going to be the ones used to test your server.

Installation

To install the package on your project just run on the root of your project

$ npm install easygraphql-load-tester --saved-dev

$ yarn add easygraphql-load-tester -D

easygraphql-load-tester

Supported packages

  1. Using .artillery() with a artillery setup.
  2. Using .k6() with a k6 setup.
  3. Using .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.
    • Note: In order to use multiples schema files, the queries and mutations must be extended. +
  • The second argument is the arguments on the queries, only if there are some of them.

One schema file

'use strict'

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

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

const loadTester = new LoadTesting(userSchema)

Multiples schemas files

'use strict'

const LoadTesting = 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 loadTester = new LoadTesting([userSchema, familySchema])

Using GraphQL.js

'use strict'

const { GraphQLSchema, GraphQLObjectType, GraphQLString } = require('graphql')
const LoadTesting = require('easygraphql-load-tester')

const schema = new GraphQLSchema({
  query: new GraphQLObjectType({
    name: 'RootQueryType',
    fields: {
      hello: {
        type: GraphQLString,
        resolve() {
          return 'world'
        },
      },
    },
  }),
})

const loadTester = new LoadTesting(schema)

Artillery

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

$ npm install artillery --saved-dev

index.js

You should configure your index.js file:

'use strict'

const fs = require('fs')
const path = require('path')
const LoadTesting = require('../../lib')

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

const args = {
  getFamilyInfoByIsLocal: {
    isLocal: true,
    test: ['a', 'b'],
    age: 10,
    name: 'test',
  },
  searchUser: {
    name: 'demo',
  },
  createUser: {
    name: 'demo',
  },
  createCity: {
    input: {
      name: 'demo',
      country: 'Demo',
    },
  },
}

const easyGraphQLLoadTester = new LoadTesting(familySchema, args)

const customQueries = [
  `
    query SEARCH_USER($name: String!) {
      searchUser(name: $name) {
        name
      }
    }
  `,
]

const testCases = easyGraphQLLoadTester.artillery({
  customQueries,
  onlyCustomQueries: true,
  queryFile: true,
  withMutations: true,
})

module.exports = {
  testCases,
}

Artillery options

type ArtilleryOptions = {
  customQueries?: string[]
  onlyCustomQueries?: boolean
  selectedQueries?: string[]
  queryFile?: boolean
  queryFilePath?: string
  withMutations?: boolean
}

This is optional, you can leave the second argument empty, if you don't want to pass any options

Custom queries

You can pass custom queries to test on your load test. To create them, create an array of strings (queries). You can use variables, and it's going to use the variables defined on the arguments used to initialize LoadTesting or, you can pass the value of the argument searchUser(name: "demo") {...}

const customQueries = [
  `
    query SEARCH_USER($name: String!) {
      searchUser(name: $name) {
        name
      }
    }
  `,
]

Only custom queries

If this is set to true it's going to use the custom queries passed.

Selected queries

You can select a list of the queries you want to test, to do this, you must create an array of strings with the name of the queries to test; this is optional, if you don't create it, all the queries are going to be tested.

const selectedQueries = ['getFamilyInfo', 'searchUser']

Query file

You can select, if you want to save a json file with all the queries that where tested, to do it, on the options pass queryFile: true, if you don't pass anything it is not going to be saved.

Query file path

You can select the path that you want to use to save the query file, if it's not set it'll use by default path.resolve()

Mutations

You can use easygraphql-load-tester to test your mutations as well; to do it, on the options pass withMutations: true, if you don't pass anything it is only going to test the queries. If you set withMutations: true, don't forget to add the input values on the args

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 }}'
                variables: '{{ $loopElement.variables }}'
          - log: '----------------------------------'
          - log: 'Sent a request to the {{ $loopElement.operation }}: {{ $loopElement.name }}'
          - log: 'And variables {{ $loopElement.variables }}'
        over: cases

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

How to run it

To run your load test, add this script on your package.json:

"scripts": {
  "easygraphql-load-tester": "artillery run artillery.yml"
}

and then run on the terminal

$ npm run easygraphql-load-tester

In this case the artillery file is called artillery, but you can name yours with your favorite name and run artillery run <MY_FILE_NAME>.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

k6

To use with k6, you must have it installed on your computer, in case you don't have it, visit the installation guide

index.js

You should configure your index.js file:

'use strict'

const fs = require('fs')
const path = require('path')
const LoadTesting = require('../../lib')

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

const args = {
  getFamilyInfoByIsLocal: {
    isLocal: true,
    test: ['a', 'b'],
    age: 10,
    name: 'test',
  },
  searchUser: {
    name: 'demo',
  },
}

const easyGraphQLLoadTester = new LoadTesting(familySchema, args)

const queries = [
  `
    query SEARCH_USER($name: String!) {
      searchUser(name: $name) {
        name
      }
    }
  `,
]

easyGraphQLLoadTester.k6('k6.js', {
  customQueries: queries,
  selectedQueries: ['getFamilyInfo', 'searchUser'],
  vus: 10,
  duration: '10s',
  queryFile: true,
  out: ['json=my_test_result.json'],
})

The first argument is the name of the k6 configuration file

K6 options

type K6Options = {
  customQueries?: string[]
  onlyCustomQueries?: boolean
  selectedQueries?: string[]
  queryFile?: boolean
  queryFilePath?: string
  withMutations?: boolean
  vus?: number
  duration?: string
  iterations?: number
  out?: string[]
}

This is optional, you can leave the second argument empty, if you don't want to pass any options

Custom queries

You can pass custom queries to test on your load test. To create them, create an array of strings (queries). You can use variables, and it's going to use the variables defined on the arguments used to initialize LoadTesting or, you can pass the value of the argument searchUser(name: "demo") {...}

const customQueries = [
  `
    query SEARCH_USER($name: String!) {
      searchUser(name: $name) {
        name
      }
    }
  `,
]

Only custom queries

If this is set to true it's going to use the custom queries passed.

Selected queries

You can select a list of the queries you want to test, to do this, you must create an array of strings with the name of the queries to test; this is optional, if you don't create it, all the queries are going to be tested.

const selectedQueries = ['getFamilyInfo', 'searchUser']

Query file

You can select, if you want to save a json file with all the queries that where tested, to do it, on the options pass queryFile: true, if you don't pass anything it is not going to be saved.

Mutations

You can use easygraphql-load-tester to test your mutations as well; to do it, on the options pass withMutations: true, if you don't pass anything it is only going to test the queries. If you set withMutations: true, don't forget to add the input values on the args

Virtual users

You can select how many virtual users do you want for your tests, just pass to the options vus: <NUMBER_OF_VUS>.

Duration

You can select the duration for your tests, just pass to the options duration: '<DURATION>s'. It should be a string with units of the time e.g. s

Iterations

You can select the number of iterations to run by passing iterations: <ITERATIONS>. It should be an integer.

Out

You can also make k6 output detailed statistics in JSON format by using the --out/-o option for k6 run. More info

k6.js

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

Note: dont' change the name and the route of the queries ./easygraphql-load-tester-queries.json

import http from 'k6/http'

const queries = JSON.parse(open('./easygraphql-load-tester-queries.json'))

export default function() {
  for (const query of queries) {
    const url = 'http://localhost:5000/'
    const payload = JSON.stringify({
      query: query.query,
      variables: query.variables,
    })
    const params = { headers: { 'Content-Type': 'application/json' } }
    http.post(url, payload, params)
  }
}

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

How to run it

To run your load test, add this script on your package.json:

"scripts": {
  "easygraphql-load-tester": "node index.js"
}

and then run on the terminal

$ npm run easygraphql-load-tester

How to use it with your actual queries

  1. Install in your project merge-graphql-schemas
  2. Import all your queries:
    const queries = fileLoader(path.join(__dirname, '..', '**/*.graphql'))
  3. Pass them as customQueries in the options, with onlyCustomQueries: true as well.
  4. Set in the args the values to used on the variables of the queries/mutations.

Success cases

If you want to share your success case using easygraphql-load-tester feel free to create a PR so the community can learn from your story.

Importance of using dataloaders

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.

Results without dataloaders

All virtual users finished
Summary report @ 10:07:55(-0500) 2018-11-23
  Scenarios launched:  5
  Scenarios completed: 5
  Requests completed:  295
  RPS sent: 36.88
  Request latency:
    min: 1.6
    max: 470.9
    median: 32.9
    p95: 233.2
    p99: 410.8
  Scenario counts:
    GraphQL Query load test: 5 (100%)
  Codes:
    200: 295

Results with dataloaders

All virtual users finished
Summary report @ 10:09:09(-0500) 2018-11-23
  Scenarios launched:  5
  Scenarios completed: 5
  Requests completed:  295
  RPS sent: 65.85
  Request latency:
    min: 1.5
    max: 71.9
    median: 3.3
    p95: 19.4
    p99: 36.2
  Scenario counts:
    GraphQL Query load test: 5 (100%)
  Codes:
    200: 295

Examples

You can check the example

License

The MIT License

Copyright (c) 2018 EasyGraphQL

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

easygraphql-load-tester's People

Contributors

abramenal avatar cameron-russell avatar cavalcantigor avatar estrada9166 avatar glen-moonpig avatar greenkeeper[bot] avatar lanzanka avatar moulie415 avatar nicodn avatar simonireilly avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

easygraphql-load-tester's Issues

example error

I am trying to run example artillery for testing and got this error.

Error: ENOENT: no such file or directory, open 'C:\Users....\AppData\Local\Temp\1583298473867/package.json'

Seem like path format error, how do i fix this?

Support multi queries in single file

Is it possibile to put multple queries and/ora mutation and fragments in a single file without create one file per query and then replicate fragments?

Error: All query arguments must be defined

Maybe I'm missing something, I'm trying to test subscriptions the are linked to specific mutations. Here's the code:

'use strict'

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

const rtSchema = fs.readFileSync(path.join(__dirname, 'schema.graphql'), 'utf8')

const args = {
  updateReviews: {
    input: {
      id: '3'
    }
  },
  createMessage: {
    message: 'test'
  }
}

const easyGraphQLLoadTester = new EasyGraphQLLoadTester(rtSchema, args)

const testCases = easyGraphQLLoadTester.artillery({
  withMutations: true
})

module.exports = {
  testCases
}

And I'm getting this error:

> npm run easygraphql-load-tester

> [email protected] easygraphql-load-tester /Users/edlima/Code/loadtester
> artillery run artillery.yml

.   /Users/edlima/Code/loadtester/node_modules/easygraphql-load-tester/utils/util.js:70
    throw new Error('All query arguments must be defined')
    ^

Error: All query arguments must be defined
    at createQueryArguments (/Users/xxxxx/Code/loadtester/node_modules/easygraphql-load-tester/utils/util.js:70:11)
    at create (/Users/xxxxx/Code/loadtester/node_modules/easygraphql-load-tester/utils/index.js:13:25)
    at schema.(anonymous function).fields.forEach.query (/Users/xxxxx/Code/loadtester/node_modules/easygraphql-load-tester/lib/loadTesting.js:25:30)
    at Array.forEach (<anonymous>)
    at LoadTesting.createQuery (/Users/xxxxx/Code/loadtester/node_modules/easygraphql-load-tester/lib/loadTesting.js:24:31)
    at LoadTesting.artillery (/Users/xxxxx/Code/loadtester/node_modules/easygraphql-load-tester/lib/loadTesting.js:47:26)
    at Object.<anonymous> (/Users/xxxxx/Code/loadtester/index.js:22:41)
    at Module._compile (internal/modules/cjs/loader.js:689:30)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:700:10)
    at Module.load (internal/modules/cjs/loader.js:599:32)
npm ERR! code ELIFECYCLE
npm ERR! errno 1
npm ERR! [email protected] easygraphql-load-tester: `artillery run artillery.yml`
npm ERR! Exit status 1

Any ideas?

Framework does not request all the fields in all the queries

So, this took me a bit of time to dig into, and I doubt it's intended behavior (if it is, please tell me).

Say I have this query defined in my schema:

jobs(
   // Args ommited here
): JobPaginatedResults!

And we have the following type:

type JobPaginatedResults {
  pagination: Pagination
  results: [Job]
}

From my understanding, this library should be requesting all those fields (everything inside Pagination, and in Job), however it's doing something different.

It's actually building two distinct queries - the first one only has the Pagination fields, and the second has both Pagination and Job.

I think this is caused by lines 53-60 in index.js:

nestedType.fields.forEach((field) => {
  const createdField = getField(field, schema)
  fields.push(createdField)

  const queryToTest = createQueryToTest(fields, queryHeader, isMutation)

  queriesToTest.push(queryToTest)
})

So, when it gets to the first iteration, it pushes Pagination into the fields list, and builds a query for just Pagination. The next iteration, it adds Results into the fields list, and builds another query - for both fields.

As a workaround, I have made the following modification:

nestedType.fields.forEach((field) => {
  const createdField = getField(field, schema)
  fields.push(createdField)
})

const queryToTest = createQueryToTest(fields, queryHeader, isMutation)

queriesToTest.push(queryToTest)

Now it only actually builds one query, using both the fields. This seems like the correct behavior. What do you think? Should I submit a PR? I'm currently using a fork I made. Does my explanation make sense, or is it confusing (Sorry if that's the case, but I can try and explain better)?

Framework is automatically adding arguments with value 'undefined'

I have a query, where all the arguments are optional. The easygraphql-load-tester library isn't complaining about this, but it is automatically adding all of those arguments with value undefined.

For example if I have this schema:

query GetJobs(
    $updatedAfter: ISO8601DateTime
    $search: String
    $createdBefore: ISO8601DateTime
) {
  // Response details omitted here
}

It should work even if I omit all those args, none of them are mandatory. This is an extract of my config.json file:

"args": {
  "jobs": {},
}

Yet when I actually look at the query was sent, it's including all those arguments as 'undefined':

{
  jobs(
    createdBefore: "undefined",
    search: "undefined",
    updatedAfter: "undefined"
  ) {
    // response details omitted here
  }
}

This results in errors:

"Argument 'createdBefore' on Field 'jobs' has an invalid value. Expected type 'ISO8601DateTime'.",
"Argument 'updatedAfter' on Field 'jobs' has an invalid value. Expected type 'ISO8601DateTime'."

As a workaround, I have patched the chunk of code that builds the queryArgs:

    if (
      userArg != undefined &&
      userArg != 'undefined'
    ) {
      queryArgs.push(`${arg.name}: ${userArg}`)
    }

I don't want to push the arg if its value is set to undefined or "undefined".

What do you think about this? Should we try and bring this change into the library via a PR? Is there a better way to solve the problem, or has nobody else found it to be an issue?

0 requests completed

config:
target: "http://localhost:8080/v1/graphql"
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: "Sent a request to the Query: {{ $loopElement.name }}"
over: cases

'use strict'

const EasyGraphQLLoadTester = require('easygraphql-load-tester')
var fs = require('fs')
var path = require('path')
var schema = fs.readFileSync(path.join(__dirname, 'test', 'schema.graphql'), 'utf8')

const queries = [
{
name: 'mission(id: "9D1B7E0")',
query: { mission(id: "9D1B7E0") { name } }
}
]

const args = {
mission: {
id: '9D1B7E0'
}
}

var loadTester = new EasyGraphQLLoadTester(schema, args)

const options = {
selectedQueries: ['mission'],
}
var testCases = loadTester.artillery(options)

module.exports = {
testCases
}

When I run the command, I get the following:

npm run easygraphql-load-tester

easygraphql-load-tester
artillery run artillery.yml

Started phase 0, duration: 5s @ 12:09:57(-0400) 2021-03-23
Report @ 12:10:02(-0400) 2021-03-23
Elapsed time: 6 seconds
Scenarios launched: 5
Scenarios completed: 5
Requests completed: 0
Mean response/sec: NaN
Response time (msec):
min: NaN
max: NaN
median: NaN
p95: NaN
p99: NaN

All virtual users finished
Summary report @ 12:10:02(-0400) 2021-03-23
Scenarios launched: 5
Scenarios completed: 5
Requests completed: 0
Mean response/sec: NaN
Response time (msec):
min: NaN
max: NaN
median: NaN
p95: NaN
p99: NaN
Scenario counts:
GraphQL Query load test: 5 (100%)

Am I missing something?

Action required: Greenkeeper could not be activated 🚨

🚨 You need to enable Continuous Integration on Greenkeeper branches of this repository. 🚨

To enable Greenkeeper, you need to make sure that a commit status is reported on all branches. This is required by Greenkeeper because it uses your CI build statuses to figure out when to notify you about breaking changes.

Since we didn’t receive a CI status on the greenkeeper/initial branch, it’s possible that you don’t have CI set up yet. We recommend using Travis CI, but Greenkeeper will work with every other CI service as well.

If you have already set up a CI for this repository, you might need to check how it’s configured. Make sure it is set to run on all new branches. If you don’t want it to run on absolutely every branch, you can whitelist branches starting with greenkeeper/.

Once you have installed and configured CI on this repository correctly, you’ll need to re-trigger Greenkeeper’s initial pull request. To do this, please click the 'fix repo' button on account.greenkeeper.io.

Error when calling `.artillery()` in sample

index.js

'use strict' 

const { GraphQLSchema, GraphQLObjectType, GraphQLString } = require('graphql')
const EasyGraphQLLoadTester = require('easygraphql-load-tester')

const schema = new GraphQLSchema({
  query: new GraphQLObjectType({
    name: 'RootQueryType',
    fields: {
      hello: {
        type: GraphQLString,
        resolve() {
          return 'world';
        }
      }
    }
  })
});

const loadTester = new EasyGraphQLLoadTester(schema)
const testCases = loadTester.artillery()

module.exports = {
  testCases
}

artillery.yml

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: "Sent a request to the Query: {{ $loopElement.name }}"
          over: cases

package.json

  "scripts": {
    "artillery": "artillery run artillery.yml"
  },

Error message:

matt-devbox@mattdevbox-VirtualBox:~/Code/server-monitoring/load$ npm run artillery

> [email protected] artillery /home/matt-devbox/Code/server-monitoring/load
> artillery run artillery.yml

.   /home/matt-devbox/Code/server-monitoring/load/node_modules/easygraphql-load-tester/lib/index.js:145
                _this.schema[schemaDefinition.definition].fields.forEach(function (query) {
                                                          ^

TypeError: Cannot read property 'fields' of undefined
    at /home/matt-devbox/Code/server-monitoring/load/node_modules/easygraphql-load-tester/lib/index.js:145:59
    at Array.forEach (<anonymous>)
    at LoadTesting.module.exports.LoadTesting.createQueries (/home/matt-devbox/Code/server-monitoring/load/node_modules/easygraphql-load-tester/lib/index.js:144:31)
    at LoadTesting.module.exports.LoadTesting.artillery (/home/matt-devbox/Code/server-monitoring/load/node_modules/easygraphql-load-tester/lib/index.js:35:28)
    at Object.<anonymous> (/home/matt-devbox/Code/server-monitoring/load/index.js:21:30)
    at Module._compile (internal/modules/cjs/loader.js:778:30)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:789:10)
    at Module.load (internal/modules/cjs/loader.js:653:32)
    at tryModuleLoad (internal/modules/cjs/loader.js:593:12)
    at Function.Module._load (internal/modules/cjs/loader.js:585:3)

Cannot provide null values for optional arguments

Given a query with nullable args, such as

{
  # both args optional
  stuff(a: String b:String): Stuff
}

I should able to provide either a, b, or neither as arguments, but instead receive an error stating, for example, All query arguments must be defined - missing a.

It doesn't seem to make sense to assert these arguments unless GraphQL schema requires them.

Thanks!

Please provide a GraphQL mutation example

Hi @estrada9166!

I was able to configure the queries and so far is working great! Now I would like to use it with a mutation. I'm passing the mutation name in the selectedQueries array field, but it just ignores it. Could you please provide an example of how to setup a mutation? Thanks!

An in-range update of @typescript-eslint/parser is breaking the build 🚨

The devDependency @typescript-eslint/parser was updated from 2.19.0 to 2.19.1.

🚨 View failing branch.

This version is covered by your current version range and after updating it in your project the build failed.

@typescript-eslint/parser is a devDependency of this project. It might not break your production code or affect downstream projects, but probably breaks your build or test tools, which may prevent deploying or publishing.

Status Details
  • Tests: There are 1 failures, 0 warnings, and 0 notices.

Release Notes for v2.19.1

2.19.1 (2020-02-10)

Bug Fixes

  • eslint-plugin: [unbound-method] blacklist a few unbound natives (#1562) (4670aab)
  • typescript-estree: ts returning wrong file with project references (#1575) (4c12dac)
Commits

The new version differs by 5 commits.

  • 1c8f0df chore: publish v2.19.1
  • 4c12dac fix(typescript-estree): ts returning wrong file with project references (#1575)
  • e9cf734 docs(eslint-plugin): fix typo in readme
  • 10d86b1 docs(eslint-plugin): [no-dupe-class-members] fix typo (#1566)
  • 4670aab fix(eslint-plugin): [unbound-method] blacklist a few unbound natives (#1562)

See the full diff

FAQ and help

There is a collection of frequently asked questions. If those don’t help, you can always ask the humans behind Greenkeeper.


Your Greenkeeper Bot 🌴

query test is testing query with all possible combinations not JUST the return value I requested.

Hi,
I am using spacex as my target: https://api.spacex.land/graphql/

I am testing with the query:
const queries = [
query SEARCH_MISSION($id: ID!) { mission(id: $id) { name } },
]

in my schema, this query exists: mission(id: ID!): Mission

Im passing in multiple args:
const args = {
mission: [
{
id: '9D1B7E0'
},
{
id: 'F4F83DE'
}

 ]

}

and I am setting the artillery options as:
const options = {
selectedQueries: ['mission'],
queryFile:true
}

The testCases are running. But, when I look at the queryFile, I see that the mission query is being tested with all of the different combinations for return values (check below). If you go to the spacex playground, you can see that under the mission query, description is the first return value, then id, then manufacturers and then name. However, in my custom query I asked for only name to be returned.

{
    "name": "mission with arguments: { id: $id }",
    "query": "\n    query MISSION($id: ID!) {\n        mission(id: $id) {\n      description id manufacturers name\n    }\n      }\n    ",
    "operation": "Query",
    "variables": {
        "id": "9D1B7E0"
    }
},
{
    "name": "mission with arguments: { id: $id }",
    "query": "\n    query MISSION($id: ID!) {\n        mission(id: $id) {\n      description id manufacturers name\n    }\n      }\n    ",
    "operation": "Query",
    "variables": {
        "id": "F4F83DE"
    }
},
{
    "name": "mission with arguments: { id: $id }",
    "query": "\n    query MISSION($id: ID!) {\n        mission(id: $id) {\n      description id manufacturers name twitter\n    }\n      }\n    ",
    "operation": "Query",
    "variables": {
        "id": "9D1B7E0"
    }
},
{
    "name": "mission with arguments: { id: $id }",
    "query": "\n    query MISSION($id: ID!) {\n        mission(id: $id) {\n      description id manufacturers name twitter\n    }\n      }\n    ",
    "operation": "Query",
    "variables": {
        "id": "F4F83DE"
    }
},
{
    "name": "mission with arguments: { id: $id }",
    "query": "\n    query MISSION($id: ID!) {\n        mission(id: $id) {\n      description id manufacturers name twitter website\n    }\n      }\n    ",
    "operation": "Query",
    "variables": {
        "id": "9D1B7E0"
    }
},
{
    "name": "mission with arguments: { id: $id }",
    "query": "\n    query MISSION($id: ID!) {\n        mission(id: $id) {\n      description id manufacturers name twitter website\n    }\n      }\n    ",
    "operation": "Query",
    "variables": {
        "id": "F4F83DE"
    }
},

Is it possible to test subscription performance?

Sorry, not an issue but was curious whether it's possible to test subscription performance, and if so what the process might look like?

Thanks for such an amazing collection of tools by the way 👍

I don't understand what it does

Hi, sorry.. but I don't understand why this project does.

I spent 20 minutes reading the doc and even part of the core. I don't understand the benefits.
Maybe a one liner in the intro could help.

How is this different than using the k6 API to make http (graphQL) queries?
Also I don't understand the benefits of loadtesting a schema without resolvers?

Action required: Greenkeeper could not be activated 🚨

🚨 You need to enable Continuous Integration on Greenkeeper branches of this repository. 🚨

To enable Greenkeeper, you need to make sure that a commit status is reported on all branches. This is required by Greenkeeper because it uses your CI build statuses to figure out when to notify you about breaking changes.

Since we didn’t receive a CI status on the greenkeeper/initial branch, it’s possible that you don’t have CI set up yet. We recommend using Travis CI, but Greenkeeper will work with every other CI service as well.

If you have already set up a CI for this repository, you might need to check how it’s configured. Make sure it is set to run on all new branches. If you don’t want it to run on absolutely every branch, you can whitelist branches starting with greenkeeper/.

Once you have installed and configured CI on this repository correctly, you’ll need to re-trigger Greenkeeper’s initial pull request. To do this, please click the 'fix repo' button on account.greenkeeper.io.

Support multiple args for a given query

Some GraphQL queries might accept optional arguments in which one would want to test different arguments.

Imagine the following schema

{
  # both args optional
  stuff(a: String b:String): Stuff
}

It would be great to provide the following as arguments for a single query

{
  stuff: [
     // since both `a` and `b` are optional
    {a: null, b: null}, 
    // Load test with `a` as the arg
    { a: 'foo' },
    // Load test with `b` as the arg
    { b: 'bar' }
  ]
}

Thank you.

Support results output for k6

An --out argument is required to save k6 results to a file or push to statsd, etc. This is not currently supported with easygraphql-load-tester.

I propose adding an out property to the options, which is an array of out argument strings.

const options = {
    customQueries: queries,
    queryFile: true,
    out: [
        "json=results.json",
        "influxdb=http://localhost:8086/k6"
    ]
    withMutations: false,
    vus: 10,
    duration: '10s'
}

Then each out value would be added as an --out argument for the spawned k6 process:

const outArgs = options.out ? options.out.map((out) => `--out ${out}`) : []

const k6Process = spawn('k6 run', [...outArgs, fileName], {
    stdio: 'inherit',
    shell: true,
    env: {
        VUS: selectedVus,
        DURATION: selectedDuration
    }
})

Should receive array of queries to test

This method should receive an array with the names of the queries to test! That way you can choose which queries should be tested.

Also, the received queries should be updated to be an object of properties with:

{
  queriesToTest: 
  customQueries: 
}

ThIs object is optional

Example

Schema

...
type Query {
  getFamilyInfo: FamilyInfo!
  searchUser(name: String!): User!
  getFamilyInfoByIsLocal(isLocal: Boolean!, test: [String]!, age: Int!, name: String!): FamilyInfo!
}
const queries = [
  {
    name: 'searchUser(name: "demo")',
    query: `
      {
        searchUser(name: "demo") {
          name
        }
      }
    `
  }
]

easyGraphQLLoadTester.artillery({
  queriesToTest: ['getFamilyInfo', 'searchUser'],
  customQueries: queries
})

The created queries will be only for 'getFamilyInfo', 'searchUser'

lib/index.js missing in 2.0 release

I receive this error when trying to use v2.0

Error: Cannot find module '/node_modules/easygraphql-load-tester/lib/index.js'. Please verify that the package.json has a valid "main" entry

easygraphql-load-tester's package.json has: ""main": "lib/index.js","

lib/index.js is not in the package folder under node_modules

2020-01-28_16-00-51

An in-range update of @typescript-eslint/eslint-plugin is breaking the build 🚨

The devDependency @typescript-eslint/eslint-plugin was updated from 2.19.0 to 2.19.1.

🚨 View failing branch.

This version is covered by your current version range and after updating it in your project the build failed.

@typescript-eslint/eslint-plugin is a devDependency of this project. It might not break your production code or affect downstream projects, but probably breaks your build or test tools, which may prevent deploying or publishing.

Status Details
  • Tests: There are 1 failures, 0 warnings, and 0 notices.

Release Notes for v2.19.1

2.19.1 (2020-02-10)

Bug Fixes

  • eslint-plugin: [unbound-method] blacklist a few unbound natives (#1562) (4670aab)
  • typescript-estree: ts returning wrong file with project references (#1575) (4c12dac)
Commits

The new version differs by 5 commits.

  • 1c8f0df chore: publish v2.19.1
  • 4c12dac fix(typescript-estree): ts returning wrong file with project references (#1575)
  • e9cf734 docs(eslint-plugin): fix typo in readme
  • 10d86b1 docs(eslint-plugin): [no-dupe-class-members] fix typo (#1566)
  • 4670aab fix(eslint-plugin): [unbound-method] blacklist a few unbound natives (#1562)

See the full diff

FAQ and help

There is a collection of frequently asked questions. If those don’t help, you can always ask the humans behind Greenkeeper.


Your Greenkeeper Bot 🌴

Old version 2.0.1 on npm

Hi

Not sure if this is the right channel but I just wanted to let you know that the latest package of 2.0.2 on npm seems to be still containing 2.0.1 code.
To verify, download the tarball from npm:
https://registry.npmjs.org/easygraphql-load-tester/-/easygraphql-load-tester-2.0.2.tgz
Open up package/lib/index.js and navigate to lines 74 and 75. You'll see that the env still contains the old 2.0.1 definitions VUS and DURATION which were changed in one of the 2.0.2 commits:
79919b1

I ran into an issue with k6 loadtesting because of this (vus wouldn't get picked up from my initializer).

Cheers

Single query for all fields

Is there a way to not use custom or selected queries and still get just 1 query for all fields instead of 1 query for every field with each field adding on.

return nestedType.fields.map((field) => {
        const createdField = getField(field, this.schema)
        if (createdField) {
          fields.push(createdField)
        }

        return createQuery({
          fields,
          queryHeader: queryHeader,
          isMutation,
          name,
          operationName,
          variables: this.arguments[query.name],
        })
      })

We end up with multiple queries like

user {
  firstName
}

user {
  firstName
  id
}

user {
  firstName
  id
  lastName
}

Can there be an option to only return the query with all fields please?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.