Testing: Arrange, Act, Assert

There is no doubt about the need for automated tests.
They

  1. assure refactoring steps
  2. help to detect weaknesses in the implementation
  3. document the implemented logic
  4. enable the implementation of modules, even if some basic modules are still missing (mocking)

Basically tests consist of 3 steps: Arrange, Act and Assert. That means establishing the test environment (Arrange), executing the logic (Act) and verifying the expectation (Assert).
Consider a bank account with the possibility to deposit money as a simple example. The implementation in advance:

class BankAccount
  attr_reader :total

  def initialize(amount)
    @total = amount
  end

  def <<(amount)
    @total += amount
  end
end

The test is quite simple, but is separated into 3 steps in a explicit and extensive way at this point.

Arrange

To make the test executable, the appropriate environment (necessary object etc.) has to be established. This step is pretty important for the tests quality. Poor tests create too many needless objects or even create objects, which are completely counterproductive. Accessing slow or external systems (database, file system, web), even if they add no value to the tests should be avoided too.
The test for the method « requires the object under test (subject) at least:

require 'spec_helper'

RSpec.describe BankAccount do
  # *** Arrange begin ***
  subject { BankAccount.new 100 }
  # *** Arrange end ***

  describe '#<<' do
    it 'adds the passed amount to total' do
    end
  end
end

Act

Quite often the most simple step is executing the logic under test:

require 'spec_helper'

RSpec.describe BankAccount do
  subject { BankAccount.new 100 }

  describe '#<<' do
    it 'adds the passed amount to total' do
      # *** Act begin ***
      subject << 1
      # *** Act end ***
    end
  end
end

Assert

It is important to express the expectation in a clear and concise way, when verifying the result. This is how a good documentation by tests is done. If the expectation is hard to understand, then it is also hard to understand, what the implementation actually has to do:

require 'spec_helper'

RSpec.describe BankAccount do
  subject { BankAccount.new 100 }

  describe '#<<' do
    it 'adds the passed amount to total' do
      subject << 1
      # *** Assert begin ***
      expect(subject.total).to eq(101)
      # *** Assert end ***
    end
  end
end