Skip to content
Permalink
master
Switch branches/tags

Name already in use

A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?
Go to file
 
 
Cannot retrieve contributors at this time

Advanced Testing

In this lab you will be refining your unit tests and augmenting these with the use of acceptance tests. The first part of this lab contains a number of exercises that cover the skills needed to complete the assignment. Make sure you take the time to complete the Test Your Understanding sections before applying these to your assignment.

Resources:

  1. Lecture slides
  2. Test Cafe (an alternative acceptance testing tool)
  3. Test Cafe Studio (acceptance testing IDE)

1 Defining API Fitness Functions

It is important that we clearly define the interface that our API exposes. If this changes it can impact any code that makes use of it. This interface is defined in the routes file index.js. Up to this point however we have focussed our automated testing on the modules it imports. In this lab you will be learning how to write unit tests for the routes file.

  1. Locate the exercises/05_advanced_testing/mocks/ directory and examine the index.js route file. Notice it has been created using the Koa web framework.
  2. At the end of the file we export the koa server object, this allows us to import it into our test framework.
  3. The __tests__/ directory contains two test suites, one for the todo.js module (we have already seen this) and a second one, called index.test.js that will test our routes. Open this and study the code:
    1. At the top we import the [supertest](npmjs supertest) framework. This allows us to make HTTP api calls and check the response object.
    2. The tests are written in jest and therefore follow the same structure as the unit tests you have previously written.
    3. Note that the sample code makes heavy use of async functions and so, if you are not familiar with them you should complete the Async Code lab exercises.
    4. There are two code styles you can use when writing the tests:
      1. The get empty list test demonstrates making the async http call, storing the results in a variable and then checking its content.
      2. The retrieve a single item test shows a chaining style.

1.1 Test Your Understanding

There is currently no delete functionality offered by the API. You will be expected to apply the principles of TDD to solve this:

  1. Locate the todo.remove() functionality in the module. Take a few moments to understand how this works.
  2. Create a new route DELETE /items:item which will delete the specified resource. At this stage it should be empty. Create a describe() block in the test suite.
  3. Complete the first TDD iteration:
    1. Write a test to add, then delete a single item, the status code should be 200 and the response body should return the item deleted using the same son structure as the other responses.
    2. Run the test suite, this new test will fail!
    3. Run the test suite with a watcher so that the tests run every time you save a file.
    4. Now implement the feature. As you save the code the tests will run. Keep working on this until all the tests pass. IS your linter picking up any coding errors?
    5. See if you can refactor the code to make it easier to follow.
  4. Complete the second TDD iteration by defining a tests that tries to delete an item that is not in the list, the status code should be 404 and the response body should contain the name of the item not found.

2 Mocking

In the previous example you were working with the todo module which saves and retrieved data stored on the hard drive of the server. Whether the data is persisted like this or in a database it always required the script to read and write from the hard drive which slows things down hugely. Because this is so sclow it makes all our tests run slowly, increasing the test suite run time and slowing us down. To solve this we will identify the module causing the slowdown and mock_ it.

  1. Locate and open the modules/todo.js script.
    1. Notice that it imports the node-persist module and it is this module that reads and writes to and from the hard drive.
    2. Run the test suites, this will run the unit tests for both the todo.js module and the routes file index.js. Note the total runtime of these tests.
    3. This is the module that we need to mock.
  2. Locate the __mocks__ directory in the root directory of the project:
    1. Notice that this contains a file called node-persist.x.js. This is the mock module. As soon as we change the name to node-persist.js it will be used instead of the nom module of the same name.
    2. Notice that it exports exactly the same functions with the same signatures as used in the nam module.
    3. Change the name as indicated and run the tests again.
    4. Notice that several tests fail, this is because the mock has not been fully implemented.

2.1 Mocking Tips

Once the tests run with the live modules you can start to write the mock. Since there are so many tests running it can be helpful to isolate these. To run a single test you can use the -t flag as shown:

node_modules/.bin/jest -t 'existing single item'

A usefule tip is how to use the debugger to debug your tests (and mocks). We will cover this in more detail in the next lecture. In brief:

  1. Open the chrome web browser and go the the url chrome://inspect.
  2. Click on the Open dedicated DevTools for Node link. This opens the chrome debugger and waits for the debugger to start.
  3. Run the command $ node --inspect node_modules/.bin/jest --runInBand -t 'remove item from list' substituting the test you are trying to debug.
  4. Use the Chrome Debugger to step through your code.

2.2 Test Your Understanding

  1. Your first challenge is to finish writing the mock so that all the current tests pass.
    1. Run the test suite again, has there been any improvement in the execution time?
  2. For an advanced challenge, note that the index.js routes file imports our todo.js module.
  3. Locate the modules/ directory and locate the __mocks/ directory inside it. This is where you need to place any mocks for your custom modules.
  4. The __mocks__/todo.x.js file is currently empty.
    1. Change the file name to trigger the mocking.
    2. Implement the mock so that all tests pass.
  5. Run the entire test suite a final time and make a note of the time this took. Did mocking the todo.js module make a difference?

3 Acceptance Testing

3.1 Test Your Understanding

4 Snapshot Testing

4.1 Test Your Understanding

5 Continuous Integration

Its now time to implement the advanced techniques we have covered in this lab and incorporate the skills from the previous labs. By now you should have started to build your assignment.

  1. You are already writing tests for any modules you have been building and these tests should run every time save your work. Your pre-push hook should prevent you pushing the code if:
    1. Any of your tests fail.
    2. Your test suite is not providing 100% code coverage.
  2. Note how long the entire test suite takes to run:
  3. Study your code carefully and identify any modules that are reading from or writing to the hard drive.
  4. Write mocks for these to speed up the testing process.
  5. You have already started building the UI, whether a website or an app.
  6. Create acceptance tests that validate this interface.
  7. Once you have a working interface for some of the functionality try implementing snapshot testing.