Giter Site home page Giter Site logo

apickli's Introduction

apickli - REST API integration testing framework with cucumber.js

NPM version apickli tests

Apickli is a REST API integration testing framework based on cucumber.js.

It provides a gherkin framework and a collection of utility functions to make API testing easy and less time consuming.

Apickli is also available as an NPM package.

Cucumber.js is JavaScript & Node.js implementation of Behaviour Driven Development test framework - Cucumber. Cucumber.js is using Gherkin language for describing the test scenarios in BDD manner.

How to start - a simple tutorial

Start new project

Below steps will help you start a new test project from scratch.

1. Folder structure

Let's start a new integration testing project for an API called myapi. The folder structure will need to match the structure expected by cucumber.js:

test/
---- features/
--------- step_definitions/
-------------- apickli-gherkin.js
--------- support/
-------------- init.js
--------- myapi.feature
---- package.json

Features directory contains cucumber feature files written in gherkin syntax. step_definitions contains the JavaScript implementation of gherkin test cases. Check out the GitHub repository for example implementations covering most used testing scenarios.

2. Package.json

This can be an example package.json file for our project:

{
	"name": "myapi-test",
	"version": "1.0.0",
	"description": "Integration testing for myapi v1",
	"dependencies": {
		"apickli": "latest"
	}
}

3. Install dependencies

Now we can get the project dependencies installed:

$ npm install

4. Scenario definitions

Let's start with the scenario file called myapi.feature. For more examples of feature and scenario definitions, check out test folder.

Feature:
	Httpbin.org exposes various resources for HTTP request testing
	As Httpbin client I want to verify that all API resources are working as they should

	Scenario: Setting headers in GET request
		Given I set User-Agent header to apickli
		When I GET /get
		Then response body path $.headers.User-Agent should be apickli

5. Get apickli-gherkin steps

We now need the corresponding step definitions that implement the steps in our scenario. Apickli has a collection of steps already implemented - ready to be included in your project - see gherkin expressions.

The simplest way to adopt these expressions is to create a file named apickli-gherkin.js in features/step_definitions and import the apickli/gherkin.js module.

Add the following to test/features/step_definitions/apickli-gherkin.js

module.exports = require('apickli/apickli-gherkin');

6. Support code

Now we need a support code to implement cucumber hooks and initialize apickli. Add the following in features/support/init.js:

'use strict';

const apickli = require('apickli');
const {Before} = require('@cucumber/cucumber');

Before(function() {
    this.apickli = new apickli.Apickli('http', 'httpbin.org');
    this.apickli.addRequestHeader('Cache-Control', 'no-cache');
});

7. Run tests with cucumber.js

The following will run our scenario (in the project directory):

$ cucumber-js features/myapi.feature
....

1 scenario (1 passed)
3 steps (3 passed)

Step timeout

Cucumber.js default step timeout is 5000ms. Add the following to features/support/init.js in order to change it:

setDefaultTimeout(60 * 1000); // this is in ms

Gherkin Expressions

The following gherkin expressions are implemented in apickli source code source/apickli/apickli-gherkin.js:

GIVEN:
	I set (.*) header to (.*)
    	I set cookie to (.*)
	I set body to (.*)
	I pipe contents of file (.*) to body
	I have basic authentication credentials (.*) and (.*)
	I set bearer token
	I have (.+) client TLS configuration
	I set query parameters to (data table with headers |parameter|value|)
	I set headers to (data table with headers |name|value|)
    	I set form parameters to (data table with headers |parameter|value|)

WHEN:
	I GET $resource
	I POST to $resource
	I PUT $resource
	I DELETE $resource
	I PATCH $resource
	I request OPTIONS for $resource

THEN:
	response code should be (\d+)
	response code should not be (\d+)
	response header (.*) should exist
	response header (.*) should not exist
	response header (.*) should be (.*)
	response header (.*) should not be (.*)
	response body should be valid (xml|json)
	response body should contain (.*)
	response body should not contain (.*)
	response body path (.*) should be (.*)
	response body path (.*) should not be (.*)
   	response body path (.*) should be of type array
   	response body path (.*) should be of type array with length (\d+)
   	response body should be valid according to schema file (.*)
   	response body should be valid according to openapi description (.*) in file (.*)
	I store the value of body path (.*) as access token
	I store the value of response header (.*) as (.*) in scenario scope
	I store the value of body path (.*) as (.*) in scenario scope
	value of scenario variable (.*) should be (.*)
	I store the value of response header (.*) as (.*) in global scope
	I store the value of body path (.*) as (.*) in global scope

Setting Proxy Server

apickli uses node.js request module for HTTP communications which supports setting proxy servers via the following environment variables:

  • HTTP_PROXY / http_proxy
  • HTTPS_PROXY / https_proxy
  • NO_PROXY / no_proxy

For more information, see https://github.com/request/request#controlling-proxy-behaviour-using-environment-variables

Variable Injection

It is possible to use Scenario Variables in a Feature file, that will have values injected when the tests are run. Whilst defining values explicitly provides better clarity to those reading a feature file, there are some configuration values such as Client Id which it is easier to externalise.

By default, backticks are use to indicate a variable in a feature file. When instantiating Apickli, a different character can be passed as a parameter. In order to follow BDD best practices, global variables should not be used in the way. Each Scenario should be independent, and as such if you would like to define configurable variables it should be done using the Before hook:

See source/test/features/injecting-variables.feature for examples.

Client Authentication

In order to make a request to a server that is protected by Mutual TLS, you must specify your client TLS configuration. This can be done when initializing Apickli as shown below.

Before(function() {
		this.apickli = new apickli.Apickli('http', 'httpbin.org');
		this.apickli.clientTLSConfig = {
				valid: {
						key: './fixtures/client-key.pem',
						cert: './fixtures/client-crt.pem',
						ca: './fixtures/ca-crt.pem',
				},
		};
});

This configuration can then be referenced using the following step definitions.

Given I have valid client TLS configuration

Contributing

If you have any comments or suggestions, feel free to raise an issue or fork the project and issue a pull request with suggested improvements.

apickli's People

Contributors

antxxxx avatar earth2marsh avatar laughingbiscuit avatar michaelshaffer37 avatar oseymen-apigee avatar pablochacin avatar sauliuz avatar seanapigee avatar seantdg avatar seymen avatar thetesttube avatar zazoomauro 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  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

apickli's Issues

Add the ability to get a scenario variable

Currently you can get and set global variables, however you can only set and assert scenario variables. It would be useful to have a function in apickli.js to get a scenario variables.

socket dont listen when I send a string

Hello!

I have created a socket with the following code in a myfile.js file:

var PORT = 44444;
var HOST = '127.0.0.1';
var dgram = require('dgram');
var client = dgram.createSocket('udp4');
buffer = new Buffer(this.result);
client.send(buffer, 0, buffer.length, PORT, HOST, function(err) { console.log(err);});

This Code is implemented in a js file called myfile.js, inside ../features/step_definitions directory which has a step definitions for Gherkin language, because I want to send a string by this socket, then I execute the command from ../features

'cucumber.js myfile.feature'
but when I type in a shell

'nc -lu 44444' I dont see anything, and I dont know why. I am using cucumber.js module, that module runs on Node.js, but it doesnt work !!
I have tried the code of this socket on Node.js and works perfectly in the same port.

Note: my structure is
project/
features/
myfile.feature
step_definitions/
myfile.js

And I run 'cucumber.js myfile.feature' from ../features

Thanks in advanced !!
See you coders ! :)

Forked - Tests not passing

Hi,

I just forked the Repo to make an update but before I made an update I ran gulp test and a number of the tests aren't passing. Am I doing something incorrectly? Should I try to fix the tests?

Echo of headers in Response

We have a requirement that all the headers sent in the request should be echoed as it is the response. But, currently the platform mainly cucumber is converting all the headers to lower case while getting returned in response.

Could anyone of you suggest how can we resolve this issue.

Not able to pass variables from one scenario to another

Hello, I am developing an API proxy. I perform a login that returns two tokens I need in consecutive requests, so I store these values and use in the next scenario.
When I inject them they are blank for no apparenty reason.
I have been taking a look into the code and I think it is not possible to set a header to a value stored in the global scope, but I am not sure.
Please someone can help me?

Feature: Validate if WCS API Proxy provides expected functionality

Scenario: OK. Request to WCS Guest Login. Login
Given I set Apikey header to nN3VsRWiinvhfWQrnP05G80jazTRVCh9
When I POST to /xxxxxxxx-wcs-guest-login
Then response code should be 201
And response body should be valid json
And response header Access-Control-Allow-Origin should exist
And I store the value of body path $.WCToken as myWCToken in global scope
Then I store the value of body path $.WCTrustedToken as myWCTrustedToken in global scope

Scenario: OK. Request to WCS Baskets. Add Items to Baskets
Given I set headers to
|name|value|
|WCToken|myWCToken|
|WCTrustedToken|myWCTrustedToken|
|Apikey|nN3VsRWiinvhfWQrnP05G80jazTRVCh9|
Given I set body to {"orderId":".","orderItem":[{"productId":"10706","quantity":"1"}],"x_calculateOrder":"0","x_inventoryValidation":"true"}
When I POST to /xxxxxxxxxxxx-wcs-baskets/
Then response code should be 200
And response body should be valid json
Then response header Access-Control-Allow-Origin should exist

How to validate a big response

Hi,

Could you help me in validating a very big response through Gherkins.

Eg: response with 20 and 30 lines and it will always come same for that request.

How can i do it or which scenario i can use it to write.

How to pass multiple data from excel sheet in our scenarios

Hi @seymen ,

I have a issue where i have multiple data in excel sheet and i want to use that multiple times for the same test case.

Eg: Name Place
value ABC ABC
value XYZ XYZ

With Apache Jmeter i am able to pass everything from a file as comma separated and run the same test multiple times with different test data.

Could you please suggest how can this be done here.

ship apickli-gherkin in npm package

Symlink in example-project should then be to node_modules.

This will enable step definitions to be upgraded automatically when we do a new npm package.

Otherwise we will be depending on users to go to repo, copy-paste changes manually.

Mutual SSL

We are currently using apickli to test rest endpoints with one way ssl, can we use it to test endpoints where mutual ssl is enabled ?

getPayloadItem is not a function

I'm trying to run some simple tests and I get this error

TypeError: node_modules/apickli/apickli-gherkin.js:9 event.getPayloadItem is not a function
    at Object.handleBeforeScenario (/Users/n0235626/Documents/API_Management/amplifier---role-sync/node_modules/apickli/apickli-gherkin.js:10:30)

I was using cucumber v2.0.0-rc.1 It looks like the event object that you pass in has changed in the new version of cucumber. I downgraded to cucumber 1.3.0 and the tests passed again.

"Given I set query parameters to" syntax does not appear to work

Here is the scenario that I have defined in my feature file. When I execute this it passes, but it should fail. I started Wireshark and captured the request sent from my local machine and it does not include the query parameters that I have listed below. I looked through the other examples that are in your file sample features file and they all show a similar query parameter syntax.

Scenario: Submit a request without an API key
Given I set query parameters to
|apikey|validKey|
|test|valuetest|
When I GET /weatherapi
Then response body should be valid json
And response code should be 401
And response body should be valid according to schema file ./test/features/fixtures/401.json

apickli eats console log

Hi,

I found a bug in my code and I added a console log to debug it but since I'm using apickli the console log doesn't print out. Any suggestions?

Multipart/form-data not handled

Hi I tried using the pipe file to body but I don't think that does exactly what I need to do. The options for the request that I am trying to test would have to look something like:

{ method: 'POST',
  url: 'http://localhost:9000/Path',
  headers: 
   {authorization: 'Basic auth'}
  formData: 
   { file: 
      { value: 'fs.createReadStream(fileName)' }
   }
 }

Add a Given statement to change a value in json request body

For requests that use the "Given I pipe contents of file (.*) to body" this would allow tests to change a value in the body. (e.g. Edit id to be unique between two tests which use the same body file)

Example: "Given I modify the value of request body path (. *) to value (. *) "

Given I set body to (.*)

Hi,

I was working with this library. I really like it. For the step that goes:
Given I set body to (.*)
I would suggest the method change to:

Apickli.prototype.setRequestBody = function(body) {
    body = this.replaceVariables(body);
    this.requestBody = JSON.parse(body);
};

As it currently is it passes a string to the body instead of a JSON object.(or the change could be in the post method body: JSON.parse(this.requestBody),

Though this would only support 'application/json' requests. maybe there is a better way to solve this or maybe the best way is if an application/json request header is present do the parse.

need a CI!!!

codeship free plan seems to fit very well to this.

socket dont listen when I send a string

Hello!

I have created a socket with the following code in a myfile.js file:

var PORT = 44444;
var HOST = '127.0.0.1';
var dgram = require('dgram');
var client = dgram.createSocket('udp4');
buffer = new Buffer(this.result);
client.send(buffer, 0, buffer.length, PORT, HOST, function(err) { console.log(err);});

This Code is implemented in a js file called myfile.js, inside ../features/step_definitions directory which has a step definitions for Gherkin language, because I want to send a string by this socket, then I execute the command from ../features

'cucumber.js myfile.feature'
but when I type in a shell

'nc -lu 44444' I dont see anything, and I dont know why. I am using cucumber.js module, that module runs on Node.js, but it doesnt work !!
I have tried the code of this socket on Node.js and works perfectly in the same port.

Note: my structure is
project/
features/
myfile.feature
step_definitions/
myfile.js

And I run 'cucumber.js myfile.feature' from ../features

Thanks in advanced !!
See you coders ! :)

Check an object exists in a response path

Hi,

I'm sure I'm just not understanding something but my test is failing and I don't know how to get the steps to check for the response value in the right way:

stepContext: 
  scenario: create user success
  step:     response body path environments should be production: true nonProduction: true
testOutput: 
  success:  false
  expected: production: true nonProduction: true
  actual: 
    production:    true
    nonProduction: true
  response: 
    statusCode: 201
    headers: 
      x-powered-by:   Express
      content-type:   application/json; charset=utf-8
      content-length: 87
      etag:           W/"57-NZwST3eL7b5VW6/DN41FOw"
      date:           Fri, 30 Sep 2016 01:11:14 GMT
      connection:     close
    body:       {"email":"[email protected]","environments":{"production":true,"nonProduction":true}}

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.