Email Subscription Form

Saturday, July 27, 2019

One Request, Sixteen Assertions

Anyone who has been reading my blog for a while knows that I'm passionate about API testing.  I'm also passionate about using Postman for API testing, because in my opinion it's the easiest way to test API requests.  So it makes me sad when I see people testing an API and only asserting that they got a 200 response!  In this week's post, I'm going to take a simple GET request and show examples of 16 assertions that could be run on the request.



For the GET request, I'll be using the wonderful Restful-Booker application created by Mark Winteringham to teach people how to do API testing.  The request URL I'll be using is https://restful-booker.herokuapp.com/booking/1 which will retrieve the booking with the ID of 1. If you run this GET request in Postman, you'll get a response like this:



The response has the first and last name of a hotel guest, the total price of their room, whether or not their deposit has been paid, and what their checkin and checkout dates are.

You may see different details in the response from those in the above image, because this is a site that is under frequent use as people practice making API requests to change booking information.

Let's look at all the different assertions we can do on this response. To add these assertions yourself, click on the "Tests" tab just underneath the request URL.

1. First, we can add the most common assertion: asserting that the response code is correct.

pm.test("Status code is 200", function () { pm.response.to.have.status(200); });

The pm.test refers to "Postman test". "Status code is 200" is the name of our assertion. And pm.response.to.have.status(200) is what we are expecting from the response.

2. We can also assert that the response comes back within a reasonable time frame, like this:

pm.test("Response time is less than 1000ms", function () { pm.expect(pm.response.responseTime).to.be.below(1000); });

This asserts that the response time is less than one second.

3-8. Next we can assert that expected headers are present:

pm.test("Server header is present", function () { pm.response.to.have.header("Server"); }); pm.test("Connection header is present", function () { pm.response.to.have.header("Connection"); });

pm.test("Content-Length header is present", function () { pm.response.to.have.header("Content-Length"); }); pm.test("Etag header is present", function () { pm.response.to.have.header("Etag"); }); pm.test("Date header is present", function () { pm.response.to.have.header("Date"); }); pm.test("Via header is present", function () { pm.response.to.have.header("Via"); });

These assertions are looking for the presence of a particular header rather than checking that the header has a specific value. The specific assertions above might not be particularly necessary, but sometimes it's a good idea to assert that certain headers are in place, such as X-XSS-Protection (not in this API), which indicates that there are measures in place to protect from cross-site scripting.  

9-10.  We can also have assertions that validate that a specific header value is being returned:

pm.test("X-Powered-By header value is Express", function () {
    pm.response.to.be.header("X-Powered-By", "Express");
});

pm.test("Content-Type header value is application/json", function () {
    pm.response.to.be.header("Content-Type", "application/json; charset=utf-8");
});

The first assertion is validating that the server used is Express, and the second assertion is validating that the Content-Type of the response is application/json.

11.  We can assert that certain text is included in the body of the response:

pm.test("Response contains last name", function () {
    pm.expect(pm.response.text()).to.include("lastname");
});

In this assertion, I am validating that the text in the body of the response contains "lastname".

12-13.  I can also assert that specific json fields exist in the response.  To do this, I first need to parse out the json in the response and save it to a variable:

var jsonData = pm.response.json();

Then I can assert on specific fields in the jsonData variable.  Here I am checking to make sure that the response has both a checkin field and a checkout field:

pm.test("Response contains checkin date", function () {
    pm.expect(jsonData.bookingdates.checkin).to.exist;
})

pm.test("Response contains checkout date", function () {
    pm.expect(jsonData.bookingdates.checkout).to.exist;

})

14-15. I can also assert that specific values are returned in the response:

var jsonData = pm.response.json();

pm.test("Correct first name is returned in response", function () { pm.expect(jsonData.firstname).to.eql("Mark"); });

pm.test("Deposit has been paid", function () { pm.expect(jsonData.depositpaid).to.be.true; });

In this first assertion, I am validating that the value of the first name returned in the response is "Mark". In the second assertion, I'm validating that "depositpaid" is true. Keep in mind that these values may actually change because others are using this API. When you add specific value assertions, you'll want to be sure that your test data does not change; otherwise your tests will be flaky!

16. Finally, I can assert that a value is greater or less than a certain number:

var jsonData = pm.response.json();

pm.test("Total price is greater than 100", function () { pm.expect(jsonData.totalprice).to.be.above(100); });

In this case, I am asserting that the total price paid is greater than 100.

The types of assertions that you run on your API responses will vary depending on what is important for you to test. While you may not decide that all types are appropriate for your API, I hope that these examples show that there are many more things to assert on than simply "200 OK"!



9 comments:

  1. Nice one!
    17) You can do response schema validation.

    ReplyDelete
    Replies
    1. Good point, Arpit! A description of how this works is in tip #4 of this blog post: https://blog.getpostman.com/2017/07/28/api-testing-tips-from-a-postman-professional/

      Delete
  2. Love that you're covering all the checks. I actually found an easier way to do this using ApprovalTests, as writing 16+ verifications for every test is tedious.

    http://angiejones.tech/verifying-entire-api-responses/

    ReplyDelete
    Replies
    1. Thanks for sharing this link, Angie! I had read your post on this and it's definitely a cool way to validate.

      Delete
    2. I agree adding the tests in each request is tedious - You could also just add it once, at the Collection level, it will run against all the requests in any folder each time you hit send :)

      Also, you're managing that in a single central place rather than in X number of single requests :)

      Delete
  3. Nice post! These assertions are useful to write functional and security tests. As you mentioned, I use some of these assertions based on the need and objective of a test.

    ReplyDelete
  4. Another awesome post Kristin!!

    ReplyDelete

Why You Should Be Testing in Production

This is a true story; I'm keeping the details vague to protect those involved.  Once there was a software team that was implementing new...