Since none of the answers here addresses the real question and instead gives an opinion on the practices mentioned, I felt the need to add another answer, even if it was 7 6 years since it was asked:
All the "problematic" DSL methods can be replaced with the usual old Ruby methods. You can still be DRY without using methods that deflect attention to different parts of the code.
The following code is directly taken from Noel Rappin's Rails 5 Test Guidelines
describe "estimates" do let(:project) { Project.new } let(:done) { Task.new(size: 2, completed: true) } let(:small_not_done) { Task.new(size: 1) } let(:large_not_done) { Task.new(size: 4) } before(:example) do project.tasks = [done, small_not_done, large_not_done] end it "can calculate total size" do expect(project.total_size).to eq(7) end it "can calculate remaining size" do expect(project.remaining_size).to eq(5) end end
Replacement with simple Ruby methods
describe "estimates" do it "can calculate total size" do project = build_new_project project.tasks = build_done_small_and_large_tasks expect(project.total_size).to eq(7) end it "can calculate remaining size" do project = build_new_project project.tasks = build_done_small_and_large_tasks expect(project.remaining_size).to eq(5) end def build_new_project Project.new end def build_new_task(size=1, completed=false) Task.new(size: size, completed: completed) end def build_done_small_and_large_tasks tasks = [] tasks << build_task(2, true) tasks << build_task(1, false) tasks << build_task(4, false) tasks end end
In my opinion and Thoughtbot's opinions, this approach has its advantages:
- Each test tells a story about how to use the code you write later.
- Each test is self-sufficient and descriptive, ideally you do not need to go through the entire file to immediately understand what is happening in each test (but it will also depend on your ability to write good tests)
- No dependency between examples
- No "Secret Guest" antipattern
On the other hand, the point is to clearly show each phase of testing in each test.
- Setup - get the right conditions for the test
- Exercise - Do What You Test
- Verification - make sure the exercise has completed what you expected
- Destruction - cancellation of any conditions that should not be preserved after testing (this should be done by Rspec automatically, but everything that can be explicitly done in the after block)
Example:
it "can calculate total size" do
In conclusion, one corporate identity guide will never be suitable for any purpose, nor for other companies. As far as I understand, this approach is especially useful for testing- based development, where the code should be based on what every failed test offers to fix it. The fact that you should not follow this approach is quite subjective. He has good arguments, but there are also disadvantages, and, as always, you must weigh them and stick to what suits you best. In my case, I believe that these tests are much easier to read and more useful for understanding each module of the application, and not just to tell you when something happens, I like to have code that documents itself. This approach will allow you to clearly see how your future code will be used and what to expect from each condition.
To learn more about TDD and how to follow this testing approach, check out how to tell a story using your tests.