Email Subscription Form

Saturday, January 26, 2019

Easy Free Automation Part II: Component Tests

Last week, I started an eight-part series to demonstrate in a free and very easy way how to write automation for each test type in the Automation Test Wheel.  This week, we're taking a look at component tests.

As with every term in software testing, component tests mean different things to different people.  I like to define a component test as a test for a service that an application is dependent on.  For example, an application might need to make calls to a database, so I would have a component test that made a simple call to that database and verified that it received data in response.  Another example of a component would be an API that the application doesn't own.  In this scenario, I would make a simple call to the API and verify that I got a 200-level response.



Coming up with a free and easy example of automated component tests was, unfortunately, not that easy!  But I have created a very simple Node.js application, which you can download from Github here.

In order to run this application and have my two tests pass, you'll need to have Node, npm, and MongoDB installed, and you'll need to create a very simple Mongo database with just one item in it.  I used most of the instructions in this really awesome tutorial by Chris Buecheler at CloseBrace.com to create this application.  You can use my application along with the instructions in Part 3 of the tutorial to make your Mongo database.  Or you can just clone my application and run it, with the understanding that one of the tests will fail. Or if this seems like too much work, you can just read on and look at my test code!

My extremely simple app is dependent on two things: my Mongo database, and an external API (the really great Restful-Booker API, which I'll be using in next week's blog).  For my component tests, I want to test those two dependencies: that I can make a request to the database and get a positive response, and that I can make a call to the Restful-Booker API and get a positive response. 

I am using Jest and Supertest for these tests.  I have limited experience with Jest, but from what I have seen so far, it is very easy to set up.  Supertest is a library that enhances Javascript testing by making it easier to call APIs. 

I've put my tests in a file called index.test.js, and this is what it looks like:

const request = require('supertest');

describe('Database Connection Test', () => {
  it('Returns a 200 with a call to the DB', async () => {
    const res = await request('http://localhost:3000')
      .get('/userlist')
      .expect(200)
  });
});

describe('Restful-Booker Connection Test', () => {
  it('Returns a 201 with a health check', async () => {
    const res = await request('https://restful-  booker.herokuapp.com')
      .get('/ping')
      .expect(201)
  });
});

The first line of my file is invoking Supertest, so I will be able to do HTTP requests.  Let's take a look at each part of the first test so we can see what it's doing:

describe('Database Connection Test', () => {
  it('Returns a 200 with a call to the DB', async () => {
    const res = await request('http://localhost:3000')
      .get('/userlist')
      .expect(200)
  });
});

The "describe" section comprises the entire test. 

describe('Database Connection Test', () => {
  it('Returns a 200 with a call to the DB', async () => {
    const res = await request('http://localhost:3000')
      .get('/userlist')
      .expect(200)
  });
});

'Database Connection Test' is the title of the test.

describe('Database Connection Test', () => {
  it('Returns a 200 with a call to the DB', async () => {
    const res = await request('http://localhost:3000')
      .get('/userlist')
      .expect(200)
  });
});

The "it" section is where the assertion is called.

describe('Database Connection Test', () => {
  it('Returns a 200 with a call to the DB', async () => {
    const res = await request('http://localhost:3000')
      .get('/userlist')
      .expect(200)
  });
});

'Returns a 200 with a call to the DB' is the title of the assertion.

describe('Database Connection Test', () => {
  it('Returns a 200 with a call to the DB', async () => {
    const res = await request('http://localhost:3000')
      .get('/userlist')
      .expect(200)
  });
});

Here is where we are making a GET request to 'http://localhost:/3000/userlist'.

describe('Database Connection Test', () => {
  it('Returns a 200 with a call to the DB', async () => {
    const res = await request('http://localhost:3000')
      .get('/userlist')
      .expect(200)
  });
});

Here is where we are expecting that we will get a 200 response.

If you'd like to try to run the tests on your own, assuming you have cloned the application, you can do so with these commands:

cd easyFreeComponentTests (this will move you to the directory where you cloned the application)
npm install (this will install all the components you need to run the application)
npm start (this will start the application)

Then go to a new command-line window, cd to where the application is located, and run:

npm test (this will run the tests)

That was a lot of information for just two component tests!  But remember it will be easier to get started when there is already a project to test.  How many tests you have in this area will depend on how many external systems your application is dependent on.  It may be a good idea to create a "health check" that will run your component tests whenever your code is deployed.  That way you will be alerted if there is any error when calling your external systems. 

Next week, we'll move on to my favorite test type: services tests!

2 comments:

  1. Great article. As the number of dependencies grow, application may be more vulnerable to downtime. If any of one the dependencies are down, application will be affected. Therefore, it may prudent to ask questions like:
    "Do we really need this dependency?" or
    "Is there a way we can design our app without taking a direct dependency on a service we don't control?"
    from time to time.

    Hopefully, there is a good "business" reason and the answer is not "umm... because microservices" :)

    ReplyDelete
    Replies
    1. This is a really good point, Alper- thanks for sharing it! :-)

      Delete

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...