Codecademy Practice

Testing

When we buy a chair, bike or car, we are buying products that undergo a fair amount of industrial testing. For example, before it goes out to the market, a car must go through a series of tests for resistance, security, impact absorption, etc.

Software is not an exception. Buggy code can cause serious problems like loosing or corrupting important data, security vulnerabilities, servers going down, slow running programs that use a lot of resources, etc.

Sometimes software bugs can have fatal consequences, like in the case of flight crashes or the Therac-25, a cancer treatment device that killed several patients because an bug in the code caused them to receive 100 times more radiation than the dose prescribed by their doctors.

Crash test dummy reading a book about testing
Testing is important in several industries.

What is automatic testing?

We could manually test our code by running our application. However, we would need to keep an updated list of all the specific cases and all the things that our app can do, and make sure that we don’t forget any. Doing this everytime we make a little change is tedious.

Automatic testing is writing extra code that does that for us. It runs parts of our application, passing them different values and checking that it behaves how we expect and that all operations return the right result. We can run this testing code as many times as we want and it will exercise all the specific cases that our app supports.

For example, if we have a class with a function that adds two numbers:

class Adder {
  add(a, b) {
    return a + b;
  }
}

We could test it like this:

describe('The Adder class', function() {
  it('adds two numbers', function() {
    let adder = new Adder();
    expect(adder.add(2, 1)).toEqual(3);
  });
});

This test uses a testing framework called Jasmine, which is very similar to Ruby’s testing framework RSpec and reads pretty much like English.

Screenshot of the results of a Jasmine passing test
When tests pass they are green.
Screenshot of the results of a Jasmine failing test
When tests fail they are red.

Anatomy of a test

Tests are usually divided in three parts:

let adder = new Adder();
adder.add(2, 1)
expect(/*result of running the code*/).toEqual(3)

Sometimes this is called “the three As: Arrange, Act, Assert”.

TDD

TDD means Test Driven Development. This is when we write our test first, and then we write the code to make the test pass. TDD has 3 stages:

Red: we first write a test, we run it, it’s red because we don’t have any code yet.

Green: we write the simplest possible code that makes the test green, sometimes called “the shameless green” because we are only focused in making the test pass.

Refactor: with the test in place, it’s time to improve the design of the code without changing it’s behaviour.

Red green refactor cycle diagram with arrows showing the direction in which the steps happen
The red-green-refactor cycle.

Benefits of testing

Writing the test first and then the code has a lot of benefits:

To do