Implementing Test Automation Frameworks for gRPC & REST Services
Tags: Engineering, Automation, Test Automation, Grpc, Quality Engineering

Writing automation framework at Chewy has been an awesome learning experience. Right from the start, I was always given the flexibility to explore any reasonable tools available in the market for automation. When I started working at Chewy, I was introduced to the concept of gRPC for the first time. This required me to familiarize myself with the basic principles of gRPC and learn how to write automation at the same. Testing this service required knowledge of this protocol at service architecture level, so I had to dig for resources. In this blog post, I have summarized my approach to implement a robust gRPC testing automation framework and how I used Java to write it. Very recently, we began transitioning from gRPC to REST service contract. With regards to that, I have also included my approach for a smooth transition from gRPC framework to REST testing framework using a tool called REST Assured.

gRPC

gRPC is becoming a popular RPC framework used by variety of modern companies like Netflix, Square, Cisco & Juniper Networks [1]. It is a Remote Procedure call provided by Google which defines a service calling methods on a remote server. The client creates a stub of the server and provides parameters and return types to these methods while the server implements them and returns a response. Data is structured in form of protobuf files, you can read more about them here. Some advantages of gRPC are; it supports multiple languages and has a high performance compared to regular RPC services. More details on gRPC documentation in Java, request and response structure can be found here.

How we wrote tests for gRPC services

In order to test client and server-side behavior for gRPC, at Chewy we wrote integration tests implementing a framework of request response similar to the one explained above. The hierarchy structure of files included a parent class which defined a gRPC channel, built it and thereafter defined a mocking stub as per requirements. The channel acted as a connection between stub and client for implementing server-side methods. This channel could be configured to point to any particular test environment. In this post, I have defined it to point to local environment (port 8888). In the following code snippet, the channel is declared as managedChannel.

public abstract class AbstractClientIntegrationTest { ServiceGrpc.ServiceBlockingStub stub; String host = System.getProperty("dns:///localhost:8888”); managedChannel = NettyChannelBuilder.forTarget(getTarget()) .build(); }

This class was inherited by all test class files, which called gRPC server methods through the stub. As mentioned earlier, gRPC supports multiple languages and test frameworks. For the purpose of this post, I shall be using Java language and Junit5 framework. A code snippet of a sample test making client calls and mocking server response is shown below.

@Test void test_nonNullResponse_validChannel() { ServiceProto.GetFeatureRequest request = SrviceProto.GetFeatureRequest.newBuilder().setParam("Param 1 Value").build(); Proto.Feature featureResponse = stub.getFeature(request); assertNotNull(featureResponse, "The response valid request was null"); }

In this test, client calls method GetFeatureRequest which has been defined on server using ServiceProto and sets input parameters in the same call (herein represented by setParam). Thereafter, client-side stub implements that method and returns a response. Finally, test asserts for response being not null using Junit assertion and throws an error message in the case that it does.

REST Assured

REST Assured is a framework for testing response and request of Rest APIs. It is written in Java language and in Behavioral Driven Development (BDD) format. Rest Assured framework can be used to parse a REST API response to validate JSON key-value pairs or check critical parts of response in XML or JSON path. Literature for REST Assured is more readily available than gRPC automation frameworks and have been referred to in the references.

REST Assured tests at Chewy

Before starting writing tests in REST Assured framework, it’s important to have the right dependencies included in Maven or Gradle project. The full documentation of REST Assured setup can be found on the official getting started page. Critical dependencies which are required by any project to set it up are as follows:

· Rest-Assured

· Json Schema validator

· JsonPath

· XmlPath

· Scala support and Kotlin extension module (optional)

A sample gradle project snippet of dependencies is shown here for dependencies specific to REST Assured. It is also recommended to statically import methods from Rest Assured classes for an effective implementation of REST Assured [2], some example is included in the following snippet.

testCompile group: 'io.rest-assured', name: 'rest-assured', version: '4.0.0' testCompile group: 'io.rest-assured', name: 'json-schema-validator', version: '4.0.0' testCompile 'io.rest-assured:json-path:4.0.0' testCompile 'io.rest-assured:xml-path:4.0.0' testCompile group: 'org.apache.geronimo.specs', name: 'geronimo-jms_1.1_spec', version: '1.1.1' import static io.restassured.RestAssured.given; import static io.restassured.matchers.RestAssuredMatchers.* ;

Here is an example of a test showing implementation of REST Assured framework in BDD in a similar format as was used at Chewy.

@Test public void validate_nonNullResponse() { String responseString = given(). when(). get(url+"/?q=param1+param2"). then(). assertThat() .statusCode(200) log().ifError(). extract(). jsonPath().get().toString(); assertNotNull(responseString, , "The response was null"}

To write a test in REST Assured BDD, you can either specify query params and URI to hit in the given clause or leave it empty (as shown in example). This can be followed by when clause where you could specify more conditions for Rest endpoint (e.g.: any detailed query parameters) or specify the URI & main params, if not done in the previous step (as shown in this example). Finally, in the then part mention the assertion you want to test as part of acceptance criteria or expected condition of test. More details on Rest Assured documentation and libraries available can be found on their official website.

CI/CD implementation at Chewy

For a robust regression framework testing, gRPC and REST automation frameworks have been implemented by Chewy. On a broad level tools used are Ansible Tower (AWX) for deployment, Atlassian Bamboo as the CI/CD server and GitHub for version control. To start the pipeline of framework, a final task has been written in Ansible playbook which makes a cURL call to bamboo API. This call triggers an automation test job residing in Bamboo. Once the tests run, a status of pass/fail is communicated to GitHub using an inline bamboo shell script. GitHub is then able to enable/disable merge functionality for the initial deployment branch which started this whole process with a deployment.

Developing an automation framework at Chewy was the most fun, mentally stimulating and learning experience to say the least. Looking back at this journey and seeing how much progress we’ve made, fills me with a sense of accomplishment. I would like to give a huge shout out to the rest of the team including but not limited to James, Amir, Pat, AP, Chris and Nelson, without whose help this would not have been possible.

References

[1] gRPC, accessed on August 13, 2019, https://grpc.io/docs/guides/concepts/

[2] John Haleby, June3, 2016, accessed on September 2, 2019, https://github.com/rest-assured/rest-assured/wiki/gettingstarted

by Shvetashva Suri

Quality Engineer II @ Chewy