Movatterモバイル変換


[0]ホーム

URL:


Skip to content
DEV Community
Log in Create account

DEV Community

Cover image for CGPA Calculator with AdonisJS: API Testing
Osinachi Chukwujama
Osinachi Chukwujama

Posted on

     

CGPA Calculator with AdonisJS: API Testing

Testing is an important part of any software development project. Testing gives us confidence in our code and helps us catch bugs before deployment. Welcome to part 5 of this series. We wrote the final APIs in part 4. Now, we will write functional tests for our APIs. If you will like to skip the previous steps, clone therepo and checkout to themore-relationships-and-seeding branch, then code along.

Functional Testing

According to Wikipedia

Functional testing is a quality assurance (QA) process and a type of black-box testing that bases its test cases on the specifications of the software component under test.

Basically, functional tests are written in a way that matches how a real user will interact with the app. Take, for example, we want to test course addition from scratch. We will

  1. Open a headless or real browser
  2. Navigate to the register page
  3. Register the user
  4. Navigate to the course addition form
  5. Fill in the details
  6. Sumit the formWe will have a test that will carry out these steps and ensure no error is thrown. If an error is thrown, then our tests fail and we will have to investigate what went wrong.

Getting started testing Adonis apps

@adonisjs/vow, the standard library built for the framework uses chai under the hood for assertions. We will mainly be testing using assertions. Get started by installing vow

adonisinstall @adonisjs/vow
Enter fullscreen modeExit fullscreen mode

The installation adds three files to your project. Add the configuration to the aceProviders array of app.js

const aceProviders = [  // ...other providers  '@adonisjs/vow/providers/VowProvider']
Enter fullscreen modeExit fullscreen mode

You can see how testing works by testing example.spec.js

adonistest
Enter fullscreen modeExit fullscreen mode

Output

  Example    ✓ make sure 2 + 2 is 4 (2ms)   PASSED   total       : 1  passed      : 1  time        : 6ms
Enter fullscreen modeExit fullscreen mode

Pre-testing checklist: Suites and Traits

Below is the content of the example test file.

'use strict'const{test}=use('Test/Suite')('Example')test('make sure 2 + 2 is 4',async({assert})=>{assert.equal(2+2,4)})
Enter fullscreen modeExit fullscreen mode

Notice that we are destructuring the test function fromTest/Suite. Since we are testing APIs, we need a JS version of Postman. This is provided byTest/ApiClient, a trait. Traits were implemented to keep the test runner lean, so any desired functionality is required when needed.

Basically, we obtain trait from Suite and require theTest/ApiClient trait. Since some of our routes require authentication, we also require theAuth/Client trait.

const{test,trait}=use("Test/Suite")("Example");trait("Test/ApiClient");trait("Auth/Client");
Enter fullscreen modeExit fullscreen mode

To understand more about Suites and Traits, I suggest you read thedocs. The Adonis team did a job explaining Suites and Traits.

Our first tests

We will structure our tests such that each controller will contain tests for each method. Go ahead and delete example.spec.js, then run this

adonis make:test User-f# output: create: test/functional/user.spec.js
Enter fullscreen modeExit fullscreen mode

Replace the content of user.spec.js with this

"use strict";const{test,trait}=use("Test/Suite")("User");trait("Test/ApiClient");trait("Auth/Client");constUser=use("App/Models/User");
Enter fullscreen modeExit fullscreen mode

Testing registration

We'll follow the convention of using the present tense on test cases. Here, we are testing the register route and asserting that the status is 201.

test("registers a new user",async({client})=>{constresponse=awaitclient.post(`/api/v1/register`).send({email:"test-user@email.com",password:"some password",grade_system:"5",}).end();awaitresponse.assertStatus(201);});
Enter fullscreen modeExit fullscreen mode

Kent C. Doods always says to ensure your test is working, feed it a wrong assertion. So we'll asset a 200 and run our tests.

- response.assertStatus(201);+ response.assertStatus(200);
Enter fullscreen modeExit fullscreen mode

Now, run the tests

Failing tests

Our tests said expected 201 to equal 200. We know that it is meant to be 201, so it means our test is working. Now return the assertion to its previous state and run the tests again.

Screenshot from 2020-11-28 19-49-57.png

Huh 🤨? 400? Remember that theregister() method in UserController.js returns errors for non-unique emails. We should probably write a test for that too eh? Change the email and run the test again.

Passing registration test

Hurray 🎊! It worked! That felt manual and isn't ideal. You know what will be better? A separate testing database which will be migrated and seeded before any tests run and revert the migrations after all the tests have run.

Configuring the testing setup

First things first, let's create a testing DB. If you are using sqlite, create one in the database directory.

touchdatabase/testing.sqlite
Enter fullscreen modeExit fullscreen mode

If you are using a different DB, create a testing database. Name it whatever you wish.

In .env.testing, add your database name

DB_DATABASE=testing
Enter fullscreen modeExit fullscreen mode

.env.testing is used to override the default values of .env when testing.
We will complete our configuration in vowfile.js. vowfile.js is used for pre-tests and post-tests setup. First of all, uncomment the ace import:// const ace = require('@adonisjs/ace')
. In the runner.before function, uncomment// await ace.call('migration:run', {}, { silent: true }) and add this below it

awaitace.call('seed',{},{silent:true})
Enter fullscreen modeExit fullscreen mode

Likewise, inrunner.after, uncomment// await ace.call('migration:reset', {}, { silent: true }).

Now, run your tests multiple times to verify that we don't run into that 400 again.

Testing an auth only route:

Let's test a route that requires authentication:update/profile. First, we will create the case alongside a test user.

test("updates a user's profile",async({client})=>{constuser=awaitUser.create({email:"some-other-email@email.com",password:"some password",});});
Enter fullscreen modeExit fullscreen mode

Then we call the API with aloginVia method attached. Note that we won't be able to useloginVia without requiringtrait("Auth/Client"). Finally, we assert the status to be 200 and the returned JSON to contain the names.

response.assertStatus(200);response.assertJSONSubset({firstName:"John",lastName:"Doe",});
Enter fullscreen modeExit fullscreen mode

We could have also usedassertJSON, but it will require that we include every field of the returned JSON. This may not be ideal for every case. Learn more about assertionshere.

Test the new test case.

Two passing test cases

So, what now?

Now, you test the other routes. Write as many test cases as you deem fit. If you compare your tests with mine, checkout themain branch onthis repo

Farewell

It's been 5 articles of bravery and honour. It can't deny how impressed I am to see you become an Adonis hero my young warlock. No that's not right, we've been writing APIs 😂. But it's been quite a journey. I hope you enjoyed every bit of it. Please I need your honest feedback on

  1. The tutorial style
  2. If I explained too much
  3. The minimal use of images and memes.Feel free to add a comment. I really want to grow as a writer and your feedback matters a lot. Thank you for following along. Adios ✌🏾🧡.

Top comments(0)

Subscribe
pic
Create template

Templates let you quickly answer FAQs or store snippets for re-use.

Dismiss

Are you sure you want to hide this comment? It will become hidden in your post, but will still be visible via the comment'spermalink.

For further actions, you may consider blocking this person and/orreporting abuse

Learning server-side development. Creating courses on educative.io
  • Location
    Owerri Nigeria
  • Education
    Federal University of Technology Owerri
  • Joined

More fromOsinachi Chukwujama

DEV Community

We're a place where coders share, stay up-to-date and grow their careers.

Log in Create account

[8]ページ先頭

©2009-2025 Movatter.jp