Chapter 13 - Unit Testing

Exercise 1: Test assertions

Below is a Minitest::Test subclass with a couple failing assertions:

require 'minitest/autorun'

class TestMath < Minitest::Test
  def test_addition
    assert(2 + 2 == 5)
  end

  def test_multiplication
    assert(3 * 4 == 13)
  end
end

Running them produces this output:

Run options: --seed 5157

# Running:

FF

Finished in 0.001554s, 1287.0013 runs/s, 1287.0013 assertions/s.

  1) Failure:
TestMath#test_addition [-:5]:
Failed assertion, no message given.


  2) Failure:
TestMath#test_multiplication [-:9]:
Failed assertion, no message given.

2 runs, 2 assertions, 2 failures, 0 errors, 0 skips

See if you can get the tests passing.

When you’re ready, have a look at the solution.

Exercise 2: Test-driven development

Test-driven development is a popular practice where the developer writes the tests first, knowing they will fail, and then implements the code so that they pass. TDD helps ensure you write well-encapsulated, easily testable code.

Let’s try TDD out now. Below is code for a Rectangle class, as well as a unit test for it. The test is failing right now, though, because the area and perimeter methods are empty. Implement the methods in Rectangle so that the tests pass.

require 'minitest/autorun'

class Rectangle

  attr_accessor :width, :height

  def area
    # YOUR CODE HERE
  end

  def perimeter
    # YOUR CODE HERE
  end

end

class TestRectangle < Minitest::Test

  def test_area
    rectangle = Rectangle.new
    rectangle.width = 2
    rectangle.height = 4
    assert_equal(8, rectangle.area,
      "Area should equal width * height")
  end

  def test_perimeter
    rectangle = Rectangle.new
    rectangle.width = 2
    rectangle.height = 4
    assert_equal(12, rectangle.perimeter,
      "Perimeter should equal width * 2 + height * 2")
  end

end

Running the test produces this failing output:

Run options: --seed 57578

# Running:

FF

Finished in 0.000862s, 2320.1856 runs/s, 2320.1856 assertions/s.

  1) Failure:
TestRectangle#test_area [-:22]:
Area should equal width * height.
Expected: 8
  Actual: nil


  2) Failure:
TestRectangle#test_perimeter [-:30]:
Perimeter should equal width * 2 + height * 2.
Expected: 12
  Actual: nil

2 runs, 2 assertions, 2 failures, 0 errors, 0 skips

When you’re ready, have a look at the solution.

Exercise 3: Test setup

The unit test from the previous exercise has some repeated code for setting up the Rectangle object. Move that code to a setup method within the test class, to eliminate the duplication. (You’ll need to change the local variable that holds the Rectangle to an instance variable.)

When you’re ready, have a look at our solution.