RSpec. If I avoid using let, let and before, how do I achieve the same functionality?

I heard that it's best to avoid its, let, let!, specify, before, and subject in RSpec.

As for let, let! and before , how can I perform configuration tasks if I don't use these?

+4
source share
6 answers

Whoever wrote these best practices actually just wants to say β€œdon't use RSpec”. It is crazy to avoid using basic functions and still think that you can succeed. Can you reference these best practices? I would love to read them and see if they are justified, or just some j-random-guy opinion.

Avoid before and let ? What kind? Really?

Avoid specify , I think this is just the older syntax for it .

Avoid a specific subject call? I think if your code lives in a perfect fantastic country. Try to minimize it and use implicit objects? Sure.

Avoid its ? It's amazing! Why avoid it? Self-documenting single-line specifications? How awful.

+8
source

Source: Some people asked about the source of all this. I think this came from good practice tips.

Answer: After I read this manual, I was almost exhausted, but after some research I came across this very well-explained entry from the same guys. Let’s not . This is a really good read with lots of insightful testing tips and good practice in general.

There is some general misunderstanding regarding this guide. It says only "avoid", and not "do not use". The result code will be more understandable and more convenient. I will give some points to which the message refers:

  • (...) there are several RSpec DSL features that are often overused, which leads to increased testing services and reduced test readability.
  • Until you need to pull out large guns, as are common examples, avoid DSL constructs such as theme, let, its and before. Stick to old friends: variables, methods, and classes.

That makes a lot of sense to me. Hope this helps.

+6
source

If you really want to research the best practices for rspec, use the following resources:

+1
source

I definitely agree with Nick, these recommendations should not be followed.

I recently wrote a blog post about building the spec correctly. It has a thorough walkthrough, taking a β€œbad” written test suite and making it a blast.

You can read it here .

+1
source

I heard that this is the best practice.

It would be helpful if you could quote some source. I believe that the statements you heard are very inaccurate.

avoid its

I personally do not use its , but this is a matter of preference. Since its is a short method , you can usually use the extended version.

avoid let , let!

There is no reason to avoid them. Official documentation does not discourage them, in fact they are actively advertised.

From a technical point of view, you can replace them by specifying a method.

 let(:foo) { 1 } 

equivalent to

 def foo @foo ||= 1 end 

but as you can see, using let more convenient and efficient.

avoid specify

specify is an alias for it .

avoid before

This makes no sense. There is no way to avoid before if you need it, and the official documentation does not discount it.

avoid subject

Absolutely wrong. Documentation encourages its use.


Bottom line. I firmly believe that what you heard is wrong. Check out the documentation to learn how to use RSpec effectively.

+1
source

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 # Setup project = build_new_project project.tasks = build_done_small_and_large_tasks # Exercise and verification # Exercise is the "total_size" method, because that is what we are testing # Verification is the expectations of what should happen after the exercise expect(project.total_size).to eq(7) end # Teardown is performed by Rspec, you may also perform it yourself in after blocks 

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.

+1
source

Source: https://habr.com/ru/post/1501887/


All Articles