Rest API testing tools review
— Automation Testing, API Testing, Tools — 2 min read
Introduction and theory
What is REST Api and how does it differ from GraphQL
Roy Fielding defined REST as architectural style for distributed hypermedia systems. It's described here if you want to dive in. For this blog post consider REST as set of contraints that tells you how to create API.
What's an API? It's an interface (a strict set of rules) that will allow you to communicate and use existing code in different applications (it might be even the same app).
What's in that case REST API? It's an API that is compliant with REST rules.
Which protocol does REST uses? Mostly HTTP.
What's GraphQL? All the answers in REST will return you whole resource. For example if you want to get user info you'll get something like:
1{2 'name': 'John',3 'surname': 'Kowalsky',5 'age': '5'6}
And that goes on and on. Think about resources that will have 50 fields (yeah, it happens sometimes).
GraphQL solves that, instead of asking for the whole resource, you can ask just for email, or age and email. Then you'll get only the fields that you are interested in:
1{3 'age': '5'4}
This saves time, traffic and resources that you have to pay for the servers. More info about GraphQL here
What are REST rules (in shortcut)
- Client-server architecture
Client does not know anything about server besides endpoints and payloads that he needs to send.
- Stateless
No sessions, no remembering what was sent in previous requests. Only JWT Tokens (or something similar) that needs to be sent with every request.
- Layers
We know only about next layer (if it's more than one, we only know about the next one we need to communicate with)
- Cache
Try to cache images on the client side. Don't DDOS yourself.
- Uniform Interface
Pick one (I suggest JSON) and stay with it. And create unique URI for separate resources.
What is HTTP Protocol
Full RFC for HTTP Protocol is here, try to get familiar with it on the fly. REST API should be compliant with HTTP codes below (GraphQL might on the other side sent you response: 200 OK and error in json payload)
HTTP Request | CRUD | Resource Collection | Single resource |
---|---|---|---|
POST | Create | 201 (Created) | 404 (Not Found) |
GET | Read | 200 (Ok) | 200 (Ok) |
PUT | Update | 405 (Method Not Allowed) | 200 (Ok) |
PATCH | Update | 405 (Method Not Allowed) | 200 (Ok) |
DELETE | Delete | 405 (Method Not Allowed) | 200 (Ok) |
Actual Testing tools
Postman
The oldest and most used now tool
Pros:
- (mostly) free for normal usage, paid features include team support
- low learning curve
- you can automate tests with a bit knowledge of JavaScript
- you can mock API responses
- support multiple environments
- built in runner and reporting
- works on all OS
- built in Open API support
- exports stuff that can be run with newman in CI
Cons:
- does not support other languages than JS
- no support for js syntax
- a bit hard to evolve into full testing framework (that will check database), this require a lot of javascript knowledge
- hard to keep the tests under version control (reviewing them is nightmare)
Newman (+npm)
Postman CLI that runs on the top of npm. Nice extensible tool that will generate reports that your CI/CD tool understands.
VS Code + Rest Client
Rest Sharp / Rest Assured
If you want to work with libraries to test REST API programatically, for C# use Rest Sharp, for Java Rest Assured. They have the most support from the community and are mature solutions.
Framework example
GraphQL testing framework
I haven't found GraphQL testing framework yet, but it's so similar to REST that RestAssured/RestSharp with some additional helper classes is sufficient. I've created simple GraphQL testing framework in this repo
The main functionality is to create a proper query builder. Reverse engineering from Postman told me to solve it this way.
1public class GraphqlParser {2 // prevent instantiating GraphQl3 private GraphqlParser() {4 }5
6 public static String parseFile(String fileName) throws JsonProcessingException {7 return parseFileWithParams(fileName, null);8 }9
10 public static <K, V> String parseFileWithParams(String fileName, Map<K, V> params) throws JsonProcessingException {11 String query;12 ObjectMapper mapper = new ObjectMapper();13
14 Path filePath = Paths.get("src", "test", "resources", fileName);15 try {16 query = Files.readString(filePath);17 } catch (Exception e) {18 System.out.println("GraphQL file not found by name:" + fileName);19 return null;20 }21
22 Map<String, String> queryMap = new HashMap<>();23 queryMap.put("query", query);24
25 if (params != null) {26 queryMap.put("variables", mapper.writeValueAsString(params));27 }28
29 return mapper.writeValueAsString(queryMap);30 }31}