Speed up your tests via :build_stubbed

Dmytro Vasin
2 min readOct 30, 2017

--

Rspec is very awesome thing that was created for ruby community. Most of us writing tests. But some times in large project our test become really slow. So each launch of test really hurts and it does not meter do you launch your test before commit/push, or launch on CI. When your test suits pass over 30 minutes — something definitely went wrong.

There are a lot of things that you can improve: DatabaseClearing, Perform Caching, Stub external requests and so on and so on.

In our project we use FactoryGirl ( FactoryBot ). Here I will try to describe how :build_stubbed could help us to improve test speed.

create:

FactoryBot.create(:comment)

In this case we will create comment object and all association for it.

build:

FactoryBot.build(:comment)

Warning: But here is misconception, we did not save object but we still will have requests to our database if factory has an associations!

:build does not create object — but it creates all association to that object.

factory :comment do
association :post
end

FactoryBot.build(:comment)
(0.1ms) begin transaction
Post Create (0.5ms) INSERT INTO "posts" DEFAULT VALUES
(0.6ms) commit transaction

build_stubbed:

FactoryBot.build_stubbed(:comment) 

:build_stubbed does not call database at all. It just creates and assigns attributes to an object to make it behave like instantiated object. It have an assigned `id`. Thats why we have such speed up.

What about association?

Association also works. `build_stubbed` will create the associations via `build_stubbed`, while `build` will `create` real association.

comment = FactoryBot.build_stubbed(:comment)
#<Comment:0x007f94d2b92df0 id: 1002, post_id: 1001, body: "text">
comment.post
#<Post:0x007f94d5883440 id: 1001, name: nil>

Also, do you actually need to reference the post in every single test?

NOTE: remember that build_stubbed stubs next methods:

  • persisted?
  • new_record?
  • created_at

Also remember that next methods will cause an exception:

  • update_attribute
  • update_column
  • save
  • destroy
  • connection
  • reload
comment.save
RuntimeError: stubbed models are not allowed to access the database - Comment#save()

Conclusion:

build_stub it’s not useful in every situation. But it could be a great approach in some cases. For example when you test models or services.

--

--

No responses yet