Testing gRPC #1: Set up a gRPC server and make an API call via gRPC UI
Hi everyone,
I’ve been busy testing and automating some gRPC APIs at work for the past 6 months and I’ve found this technology fascinating.
While HTTP APIs are discussed extensively in blogs and conference talks, curiously gRPC is still a less talked about technology in the Quality engineering space. Let’s change that, shall we?
Why should you read this? ❓
In this blog series, we’ll take a deeper look at gRPC from the lens of a Software Engineer looking to test all the different aspects. If your org uses gRPC this may help solidify its concepts and help you to test better. If not, who knows you may come across this technology in the future and can come back to this series
What will we learn in this series?
- gRPC concepts such as client stub, protocol buffers, blocking, and async calls
- Set up a gRPC server and a client for an example service
- How to do unit testing
- How to do functional API testing
- Performance test these APIs
By the end of this series, I want to personally have a deeper intuition of how to approach all testing at these different layers and take you along with me on this learning journey.
This will be a ton of fun 💖.
I hope you are as excited to start on this learning journey with me. 🏃
What is gRPC?
gRPC stands for Google Remote Procedure call, It is a modern framework to design APIs so that a client can call a method with some params on a remote server (running on a different machine) as if it were a local object.
gRPC uses protocol buffers to define the service and enable serialization/de-serialization. It is essentially an interface definition language (IDL) and we can generate client and server code in any supported language (C++, Java, Python… etc) using a proto compiler.
Source: Introduction to gRPC
Why gRPC?
- Clients (stub) could call any method defined within a service
- gRPC is language agnostic i.e. clients could be written in one language (Ruby, Java) and served in another one (C++)
- gRPC allows for full duplex streaming i.e. client streaming, server streaming, or bi-directional streaming of messages such that clients and servers can issue read or write streams in any order.
- It supports sync and async flows
- Mobile Clients can use advanced streaming and connection features that help save bandwidth and make fewer TCP connections to save battery life and CPU usage
- gRPC provides advanced load balancing and failover, cascading call cancellation, interaction with flow control at the application layer
- Uses static paths in URLs for performance reasons and reducing the cost of parsing query, path, and payload body
- Has formalized set of errors that are more directly applicable to APIs than HTTP status code
If you prefer watching a video, you can watch from ByteByteGo for a quick overview or from IBM Cloud
Protocol buffers
Protocol Buffers (protobufs) are used as the IDL (Interface definition language) to define the gRPC service, essentially this means we can define what methods would this server/API expose along with what params would be passed in, and what response would be returned.
Protobufs are also used as the message exchange format to define the request/response formats and then using a proto compiler (protoc), we can generate client and server code in the supported languages.
What are some advantages of using protocol buffers?
How are protocol buffers used?
Source: How do protocol buffers work
For example: below Person.proto generates below Java class Person.java
To generate client and server code using protoc (protocol buffer compiler), Please read grpc-java/README.md at master
Setup
Now that we have some idea about gRPC and protocol buffers (at least conceptually), let’s get our hands dirty 🤝 and set up a gRPC server and client for an example service to see how these work practically
We will use the Java programming language and I’ll be using Java 17 in this example, we will follow the official gRPC tutorial to set up this app with the client and server
The service that we will set up is called the route guide. You can find the code for that in /grpc/examples/routeguide, we will understand the methods it offers as we set it up.
Let’s clone the code using the below
Note:
We use the v1.61.0
branch by specifying -b
in the clone command and -depth
to do a shallow clone and only get the latest commit. This is to ensure we don't pull in all the git history
We will change the directory to
Defining service and request, response in proto file
The service request and response types are specified in the proto file https://github.com/grpc/grpc-java/blob/v1.61.x/examples/src/main/proto/route_guide.proto
To see the service definition, its methods, and request responses, let’s look at the service RouteGuide
We can see that this service offers 4 different methods
- GetFeature
- ListFeatures
- RecordRoute
- RouteChat.
Each of these provides an example of a different type of RPC call that we can make (simple, server side streaming, client side streaming, bidirectional streaming).
We will grasp them when we test these methods, but for now, you can see that each method accepts a proto and returns either a single proto or a stream of protos (array of protos)
If we look further down in the proto file, we can see how these protos are defined.
- Each proto starts with a keyword message
- We specify fields with their appropriate data types like int32, string, or repeated (similar to an array)
- Proto can have other proto messages as its member fields to create a rich representation of data
Generate server and client code
Given the above service definition, we usually generate client and server interfaces using proto proto-compiler
In the above repo, we can use Gradle to generate these Java classes. You can find these instructions at https://github.com/grpc/grpc-java/blob/master/README.md
We need to ensure the below dependencies are added to our build.gradle file
We need to have below config in our build.gradle file to allow generation of client and server interfaces
Note: grpc-java adds config to support both Android and non-android projects and thus the config is slightly more complex. You can see it here
To ensure latest classes are generated, we should run:
cd examples
Running server with reflection and seeing APIs with gRPC UI
And to run the server, run below:
We can now see that we have the server running on localhost:8980
Let’s play with these APIs using a command line utility called grpcui, to install it run below on macOS:
Once installed, we can spin up the web app to inspect our gRPC APIs using below:
When you initially run this, You will see an error message like below, Oh.. no… 🤦
What went wrong here?
The message is pretty self-explanatory.
To play around with APIs with GRPC Web UI you need to enable server reflection support, If curious, read this tutorial to enable this for the server and understand this in detail
But in short, we need to add package import below and add ProtoReflectionService to our serverBuilder in examples/src/main/java/io/grpc/examples/routeguide/RouteGuideServer.java
After making this change, we can again build and run the server as above and start the grpcui
We can see that the gRPC UI is up and running. We can see our 4 service methods being available
We can select the method that we want to test and then select a request payload and call that API directly
Let’s say we want to call GetFeature method with a test latitude and longitude
We can enter a test latitude and longitude in Request Form
Or directly update the request JSON in Raw Request
For example, say we want to check any feature at given lat or long
If there is no feature at the specified location then the API returns an empty name, like below:
Congratulations! 🎀 You’ve made your first gRPC API request.
In the follow-up post, we will understand other methods for this API and also understand what a unit test for these API methods looks like
Thanks for the time you spent reading this 🙌. If you found this post helpful, please share it with your friends and follow me (@automationhacks) for more such insights in Software Testing and Automation. Until next time, Happy Testing 🕵🏻 and Learning! 🌱
Resources
Originally published at https://automationhacks.io on February 17, 2024.