2. Building a Strong Functional Test

Note: This example exists in your Example project, and it is named Retail: Integration – Products.

Ok, so let’s build our first functional test! We will start by using this API call.

By clicking that link, or using the HTTP composer to make the call, you get this response.

JSON response of demo product API.

As you can see there are 5 objects, so at minimum we want to make sure they ‘exist.’ What API Fortress allows you to do is validate the objects exist and the data is as expected. This is done using our XML markup language, or our GUI composer.

*Side Bar*
API Fortress was specifically built to bridge the gap between testers and engineers, allowing you to write detailed API tests in whatever format you are most comfortable with. Our composer has a drag-and-drop interface that writes the XML code for you, and it also makes it easier to visually understand the nature of the test. With that said, our GUI composer also has a Code View which exposes the underlying XML. This XML can be written or edited in the GUI, or using your own IDE. Meaning that how you want to write and/or edit a test is completely unlocked, so you can work how you are most comfortable.

An API Fortress auto generated functional test.

In the GUI composer view that test looks like this:

If you clicked on Code, or were looking at the test in your own IDE, this is what you’d see:

<unit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" name="main" xsi:noNamespaceSchemaLocation="http://apifortress.com/app/unit.xsd">
   <requirements />
   <configs />
   <sequence name="main">
      <get url="${protocol}${domain}${productsEndpoint}" params="[:]" var="productsPayload" mode="json" />
      <assert-equals expression="productsPayload.status" value="200" comment="" />
      <assert-is expression="productsPayload.success" type="boolean" comment="" />
      <assert-exists expression="productsPayload.content.act" comment="" />
      <assert-is expression="productsPayload.content.products" type="array" comment="" />

Now if we look at the code itself carefully, it’s pretty clear what we’re seeing.

  • The unit section is referencing our markup Namespace file (useful when using your own IDE).
  • Requirements and Sequence are more advanced feature we can discuss later.
  • GET is where we make the API call. Within this call it contains the necessary information to make the call (can include more if we’re dealing with oAuth for example). Some important things to note is how we have variablized protocol, domain, and then the chosen endpoint. You’ll also notice the Data Sets section on the left contains those same variables and the data associated. This is hugely important to allow the test to be easily run against any environment. We will go into more detail on that later, but think of it as futureproofing the test from location specificity.
    Then there is also var=”productsPayload”. What this does is call an API, gets a response, and then stores that entire payload into a variable called productsPayload. This is then referenced in the next assertions.
  • Note: Performance can be an assertion within the test itself. See this page for more information.
  • Now we get to the assertions! There are over 70 assertions, so we won’t get into too much detail here, but you can see the next four lines are assertions for each object. Looking at the first we see:
    <assert-equals expression=”productsPayload.status” value=”200″ comment=””/>
    This line calls the assert-equals assertion, which validates an object exists and is equal to a chosen amount. Expression references the specific object we are talking about. You’ll notice that it has productsPayload.status. So it’s referencing the status object within the productsPayload variable. Remember, the GET call gets an API response and stores it in that variable. This is useful for when you are dealing with multiple payloads (variables) in an integration test.
    It’s important to note that with the Generate Test feature you can have this entire structure generated for you in seconds. This frees you to focus on the more important and tricky aspects of writing detailed tests.