{"id":5734,"date":"2016-10-04T17:39:50","date_gmt":"2016-10-04T20:39:50","guid":{"rendered":"http:\/\/blog.plataformatec.com.br\/?p=5734"},"modified":"2016-10-05T09:48:16","modified_gmt":"2016-10-05T12:48:16","slug":"using-the-test-pyramid-to-have-better-feedback-from-your-test-suite","status":"publish","type":"post","link":"http:\/\/blog.plataformatec.com.br\/2016\/10\/using-the-test-pyramid-to-have-better-feedback-from-your-test-suite\/","title":{"rendered":"Using the test pyramid to have better feedback from your test suite"},"content":{"rendered":"

In this blog post, I’ll explain the problem of developers spending too much time trying to discover a problem in a failing test suite. A cause of this issue may be the lack of a good test feedback. A good feedback is one that happens fast with a helpful message.<\/p>\n

To illustrate this problem, consider a simple application of storing and listing contacts. You have an actor user that can sign up, sign in, then can CRUD their contacts with first name, last name and phone number. We are in a context of multiple developers working together, programming and delivering features every day. For the examples below I’ll use Ruby, RSpec, Capybara and Ruby on Rails.<\/p>\n

Suppose we have a UI testing using RSpec features test<\/a> like this:<\/p>\n

#spec\/features\/contacts_spec.rb\nfeature 'User can create new contact' do\n  scenario 'when user provides valid contact information' do\n    login_with email: 'default@mail.com', password: 'default'\n\n    click_link 'Contacts'\n\n    expect(page).to have_content('Listing Contacts')\n    expect(page).to have_content(\"There're no contacts.\")\n\n    click_link 'New Contact'\n\n    fill_in 'First name', with: 'Jon'\n    fill_in 'Last name', with: 'Doe'\n    fill_in 'Phone number', with: '1199999999'\n\n    click_on 'Create Contact'\n\n    expect(page).to have_content('Listing Contacts')\n    expect(page).to have_content('Jon Doe - (11) 9999-9999')\n  end\nend\n<\/code><\/pre>\n

Simple and straight forward. The good part of this test is it checks the entire application stack: authentication, rendering, storing stuff on the database and the logic of creating contacts. Some developer may be confident with this test and start to question: Should I add more unit tests? For phone number formatting? For displaying complete names? For user authentication? For contact validation and creation? If one of these features fail, this feature test will fail too. Why should I care to add more tests? Isn\u2019t it redundancy? Waste of time? The short answer is you should add more unit and integration tests because of feedback. Now, let’s expand the topic.<\/p>\n

Speed matters<\/h2>\n

We know the UI test brings confidence since it tests the entire stack of your application. But overusing this type of tests will severely impact your test suite speed.<\/p>\n

In our contacts creation test example, we have some edge cases that were not covered. What happens if we use a different size of numbers in the telephone number field? How will it be displayed? We can add a new UI test to cover this case, but a unit test suits better and faster. If the number formatting is a view helper we can check it with a helper test, for example:<\/p>\n

describe '#format_phone_number' do\n  it 'formats cell phones numbers of 10 digits in \"(XX) XXXXX-XXXX\" format' do\n    formatted_number = helper.format_phone_number('11999998888')\n    expect(formatted_number).to eq '(11) 99999-8888'\n  end\n\n  it 'does not format others digits different of 10' do\n    formatted_number = helper.format_phone_number('11888')\n    expect(formatted_number).to eq '11888'\n  end\nend\n<\/code><\/pre>\n

This test is way easier to write, read, cheaper and faster than adding a new UI to test this specific case. Keeping this practice, you will have fewer UI tests and more integration and unit tests. Such distribution of the different kind of tests resembles the format of a pyramid:<\/p>\n

\"pyramid\"<\/p>\n

Few UI tests on top and a solid base of unit tests. If you want more information about the test pyramid, I recommend you the following links:<\/p>\n