Getting Started with API Testing by Using TestMace
Tags: testing, codequality, showdev, productivity
Published: 2019-12-02 12:15:54

Hello there! We're coming out of the shadows and continuing the series of articles about our product. We've got so many feedbacks (mainly positive), suggestions, and bug reports after publishing our [last](https://dev.to/dimansny/we-built-an-ide-to-work-with-api-design-here-s-what-we-did-5dhe) overview article. Today you'll see [TestMace](https://client.testmace.com/) in action and try out some features of our application.

For more information be sure to look over its documentation - [http://docs.testmace.com](http://docs.testmace.com). Let's go!

# Installation

We'll start with some basic things. Our application is available and is being tested on three platforms: Linux, Windows, MacOS. You can download an installer for particular OS from [our site](https://client.testmace.com/).

Linuxoids can install a [snap package](https://snapcraft.io/testmace).

We're really hoping to get our hands on Microsoft Store and App Store (should we?).

# Experimental Scenario

For our little experiment we have the following standard scenario:
- log in:  user - **admin**, password - **password**;
- add a new record;
- check if the record was added correctly.

We'll be using the [https://testmace-quick-start.herokuapp.com](https://testmace-quick-start.herokuapp.com/) url. It's a plain [json server](https://github.com/typicode/json-server), perfectly suitable for testing this kind of applications. All we've done is token authorization for all json server routes and the login method for getting this very token.

We'll move step by step, improving our project.

# Creating a project and trying to create an entity without authorization

Let's start with creating a new project (**File**->**New project**). If TestMace is launched the first time, it'll be done automatically. Let's issue a request for creating a new post (in case if it is possible without authorization). In the Project node context menu select **Add node** -> **[RequestStep](https://docs.testmace.com/node-types/request-step)**.
Name it **create-post**. You'll see a new node in the project tree and it's tab will be shown.

Set the following request parameters:

- Request type: **POST**
- url: [https://testmace-quick-start.herokuapp.com](https://testmace-quick-start.herokuapp.com) posts
- Request body: **json** with the `{"title": "New testmace quick start post"}` value.

If you do it right, you'll see the following interface:

![Alt Text](https://thepracticaldev.s3.amazonaws.com/i/m1j0uqepdsri9idj9279.png)

However, if you send this request, the server will return the 401 code, and you won't be able to do anything with the server without authorization. Just as expected.

# Adding an authorization request

As mentioned before, we've got a POST endpoint **/login**, that takes the following json as the request body: `{"username": "<username>", "password": "<password>"}`, where **username** and **password** have the **admin** and **password** values respectively. This endpoint returns the following json as a response: `{"token": "<token>"}`.

Let's use it for authorization. Create a [RequestStep](https://docs.testmace.com/node-types/request-step) node named **login** with the [Project](https://docs.testmace.com/node-types/project) node being its parent. Drag and drop this node above the **create-post** node in the tree.
Set the following parameters for the newly added node:

- Request type: **POST**
- url: [https://testmace-quick-start.herokuapp.com/login](https://testmace-quick-start.herokuapp.com/login)
- Request body: **json** with the `{"username": "admin", "password": "password"}` value.

If you send the request, you'll get the 200 code with the token as a response:

![Alt Text](https://thepracticaldev.s3.amazonaws.com/i/uu4s7dlu5j4i79uf9mo6.png)

# Refactoring: removing domain duplication

Our requests are not grouped in one scenario yet. But that is not the only problem here. If you look at them closer, you'll see that the domain is duplicated in both requests. That's not good. It's time to refactor this part of our future scenario with the help of variables.

Variables in TestMace roughly do all the same things as in other similar tools and languages - deduplication, improving readability, etc.

Refer to [our documentation](https://docs.testmace.com/variables/user-variables) to read more about variables. This time we'll need user-defined variables.

Define the `domain` [variable](https://docs.testmace.com/variables/user-variables) with the value `https://testmace-quick-start.herokuapp.com` at the Project node level. To do that, you need to:
- Open the Project node tab and click on the calculator icon at the top right of the window;
- Select **+ADD VARIABLE**;
- Enter the name and value for this variable.

In our case, the variable dialog will look like this:

![Alt Text](https://thepracticaldev.s3.amazonaws.com/i/87w32zy334wrcqc38lxd.png)

OK. Now we can inherit this variable in children of any nesting level and in the **login** and **create-post** nodes in particular. To use the variable in the text box, you should write `${<variable_name>}`. For example, the url for **login** will be written as `${domain}/login`, and the url for the **create-post** node - `${domain}/posts`.
By doing so, we've followed the DRY principle and improved our little scenario.

# Storing the token in a variable
While we're on the subject of variables, let's go a bit further. If the login is successful, we get an authorization token from the server, that we're going to need in future requests. Let's save this token into a variable. Since the variable value is defined while running a scenario, we'll use a special mechanism called [dynamic variables](https://docs.testmace.com/variables/user-variables/dynamic-variables).

First, let's send the login request. In the **Parsed** tab of the response point to the token in the context menu and select **Assign to variable**.

You'll see a dialog with the following fields:

- **Path** - the part of a request taken (`body.token` in our case);
- **Current value** - the value at the specified path (the token value);
- **Variable name** — the name of the variable where our **Current value** will be stored. (`token` in our case).
- **Node** — the parent node where the **Variable name** will be created. Choose **Project**.

The dialog with complete fields should be the following:

![Alt Text](https://thepracticaldev.s3.amazonaws.com/i/ukpmukn6nkjmi0q7m4fx.png)

At this point, every time the **login** node runs, the `token` variable is updated with the value from the response. This variable will be stored in the **Project** node and will be available in child nodes, thanks to inheritance mechanism.

To access dynamic variables, use the [default variable](https://docs.testmace.com/variables/variables) `$dynamicVar`. For instance, to get to the saved token you should write `${$dynamicVar.token}`.

# Passing the authorization token into requests

Previously we've received an authorization token and now we only need to add the **Authorization** header with the `Bearer <tokenValue>` value to every request where authorization is needed, including the **create-post** request.

There are a few ways to do that:
- To copy the token and add the authorization header to every request manually. This works just fine, but is limited to fire-and-forget requests and not suitable for scenarios;
- To use [authorization](https://docs.testmace.com/working-with-project/authorization) feature.
- To use [default headers](https://docs.testmace.com/other-features/default-http-headers).
The second approach seems to be just what we need, but in terms of this article it's of no interest. Seriously, you should be more or less familiar with the authorization mechanism from other tools and shouldn't have any trouble with it (even though we have such things as [authorization inheritance](https://docs.testmace.com/work-with/authorization#inherit-from-parent) in TestMace).

Using default headers is much more exotic. Long story short, default headers are inherited HTTP headers that are by default added to requests if you don't turn it off explicitly. With the help of this feature you can, for example, implement custom authorization or get rid of duplications in your scenarios. Let's use this feature to pass the token through the headers.

Earlier we've saved the token into the `$dynamicVar.token` dynamic variable at the **Project** node level. Now we have to:
1. Define the Authorization default header with the `Bearer ${$dynamicVar.token}` value at the **Project** node level. To do that, open the default headers dialog (select the **Headers** button at the top right of the screen) and add the corresponding header. This is how the dialog with the filled fields should look like:

![Alt Text](https://thepracticaldev.s3.amazonaws.com/i/8k4yuyk9bqy9l4suzcgv.png)

2. Disable this header in the **login** request. Sure thing: at the moment of logging in we don't have a token, we'll set it with this particular request. Thus, uncheck the **Authorization** checkbox in the **Headers** tab in the **Inherited** area.
That's it. The authorization header will now be added to all **Project** node children, except for the **login** node. Seems, the scenario is ready, and we only need to run it. To do that, select **Run** in the **Project** node context menu.

# Checking if the post was made correctly

So far, our scenario can log in and create a post using an authorization token. But we have to make sure that the created post has the correct name.

So here's what we need to do:

- Send a request to get the post via its id;
- Check if the name received from the server corresponds to the name used while creating the post.

Let's discuss the first step. Since the id value is defined while running the script, we need to create a dynamic variable (let's name it `postID`) in the **create-post** node at the **Project** node level.

You already know how to to that, just go to the **Storing the token in a variable** section. All we have left is sending a request for getting the post by its id.
Create a RequestStep node named **get-post** with the following parameters:
- Request type: **GET**
- URL: `${domain}/posts/${$dynamicVar.postId}`

To go further, you need to take a closer look at [Assertion](https://docs.testmace.com/node-types/assertion-node) nodes. An Assertion node is a node that allows to create tests for specific requests. Each Assertion node may contain several assertions (tests). To learn more about supported assertions you can refer to our [documentation](https://docs.testmace.com/node-types/assertion-node). We'll use a Compare assertion with the equal operator.

There are two ways of creation assertions:

1. Long. Do it manually from the RequestStep node context menu. In the created Assertion node add the desired assertion and fill in the fields.

2. Quick. Create an Assertion node along with the desired assertion from the RequestStep node response using the context menu.

Let's stick with the second one. Here's how it'll look like for our example:

![Alt Text](https://thepracticaldev.s3.amazonaws.com/i/q7nsu1uaghn1f278cmn7.gif)

Basically, you do the following:
- Create a request in the **get-post** node.
- Open the context menu in the **Parsed** tab and select **Create assertion** -> **Compare** -> **Equal**.

Wow, we've just created our first test! Simple as that! Now you can run the full scenario and enjoy the result. You can make it even more beautiful if you put `title` into a separate variable though.
We leave it to you as an exercise :)

# Conclusion

In this guide we created a full-blown scenario and tried some features of our product as well.

Of course, these were just a few of them, and we're going to make a full review of all TestMace features next time. So watch out for updates in our blog!

P.S. If you feel lazy to follow the steps described in the article, we've have a [repository](https://github.com/TestMace/testmace-quick-start-project) with this project just for you. Select **File** -> **Open project** and choose the **Project** folder.