Hello everyone!
I was inspired to write this article by my students and mentees. I often recommend they learn TypeScript as soon as they get comfortable with the test automation process on JavaScript. Let’s see what the traits of using TypeScript in your test automation framework in terms of REST API testing are…
You can find the full code of a test project here.
Let’s not get too deep into what TypeScript is and how it is different than JavaScript and state the important thing -
TypeScript is presented as a Node.js package, so I look at this just as JavaScript with some cool features.
To learn more about the language itself and what it has to offer - please visit the official website while we are going to talk about its features in terms of test automation…
Let’s go through the test automation project creation process on TypeScript:
Create a Node.js project.
npm init -y
Install the TypeScript package.
npm i typescript
Generate a default TypeScript configuration for the project - tsconfig.json
.
npx tsc --init
The command above will generate a default config file, but I recommend shortening it a lot to something like this:
{
"compilerOptions": {
"baseUrl": "./",
"module": "esnext",
"target": "esnext",
"sourceMap": false,
"moduleResolution": "node",
"allowJs": true,
"skipLibCheck": true,
"resolveJsonModule": true,
"allowSyntheticDefaultImports": true,
"paths": {
"*": ["./*"]
}
}
}
This config contains the required minimum:
You can extend your config using official documentation.
You can use any tool that the Node.js ecosystem has to offer, but in my experience - most of the engineers who work with TypeScript choose Jest for a couple of good reasons:
Previously, I had fun using Mocha + Chai to set up the core of the project, but now I'm sticking to Jest, too, as it contains both a test runner & assertion library.
Axios seems to be the most popular HTTP client, so I suggest this is your pick too.
Can't say that you are forced to use this for your setup, but I'm saying that it's the usual thing when you look through the projects.
Now, simply install these packages as dependencies:
npm i jest axios
Some packages (like Axios) contain TypeScript types inside, but Jest & Mocha don't. Also, Jest requires a ts-jest package along with @types/jest to work properly - the first one enables TypeScript features & second lets you use IntelliSense.
So keep in mind - if you don't have autocomplete feature when you're trying to use some of the packages - you're probably missing type declarations.
Let's install TypeScript-related extensions (packages) as well:
npm i ts-jest @types/jest
Jest requires a ts-jest config preset, so you must declare it in your config (or package.json) file:
{
"jest": {
"preset": "ts-jest"
}
}
If you're planning to use absolute path within a project, you'd need to adjust your config as well:
{
"jest": {
"preset": "ts-jest",
"moduleDirectories": [
"node_modules",
"<rootDir>"
]
}
}
This config allows you to run tests with a simple command... jest
So, configure your test script in package.json to be:
{
"scripts": {
"test": "jest"
}
}
And then run your tests any time with npm test
or npm run test
command.
I also recommend you install a Jest Runner extension if you are a Visual Studio Code user - it allows you run/debug desired tests/suites with just one click. In WebStorm, it's a built-in feature.
The main feature that TypeScript introduces into REST API testing is...
You can declare what your request & response body should look like, i.e.,
Let's take a Paysis server as an example - we can write down its request body payload for /auth
endpoint as a type:
export type AuthRequestBody = {
login: string
password: string
}
And same for the response body - what server should send to our request:
export type AuthResponseBody = {
token?: string
message?: string
}
Since there'd be a different payload for success/failure scenarios - you can mark keys as "optional" via the “?” character.
Once it's done - you can use these types to compose requests and verifications in your tests...
In Axios, you can say what body you are sending via the request config:
const payload: AxiosRequestConfig<AuthRequestBody> = {
method: 'post',
url: '/auth',
data: {
login: process.env.USERNAME,
password: process.env.PASSWORD,
},
}
AuthRequestBody
in AxiosRequestConfig<AuthRequestBody>
means exactly that ☝️
It means you'll be forced to use the payload that matches the provided type AuthRequestBody
in data
object. If you forget to set some required fields or set some excessive ones - you'll see an error.
The same thing can be done about response as well:
const response: AxiosResponse<AuthResponseBody> = await client.request(payload)
It will add autocomplete to the response.data
object, so you'd be able to reach response.data.token
or response.data.message
fields.
Apart from the simple stuff above, it's also possible to generate a JSON schema from your custom types. It lets you not check every single key in a response body to see if it matches the schema but check the whole payload.
So the idea is:
Pretty cool stuff, but keep in mind that your tests might become flaky after these changes - it happens when some additional fields appear, so you'd need to update the schema regularly.
TypeScript setup might be tricky, especially if it's your first time, but it's worth it!
If you cover your input & output data with types - there’s no way you’d make a typo or some other syntax error when you parse these objects. It saves you from simple mistakes and lets you see the structure of your requests right in your code, so you don’t have to open any HTTP collection (like Postman) and look for the request you need to see what body it request/responds with.
Let me know about your experience and what you think about it.