Reflection to Tealeaf Course3 Week7 (1/3)
Last week, we use Stripe for charge in UsersController#create, it’s a bit little complex code here. We need to wrap it.
Why we need to wrap it into a class:
Easy to maintain code, isolate controller’s and business logic. Remember we knew that
fat models, thin controllers
, here is a step further concept, we encapsulate code intomodels/stripe_wrapper.rb
Easy to test, isolate test between different object is always a good idea.
#How to Wrap
For module StripeWrapper
is just a namespace. Then we sort the code in UsersController#create,
1 | module StripeWrapper |
Then we can call method StripeWrapper::Charge(options)
.
new(repose, :sucess)
and new(e, :error)
return an StripeWrapper::Charge
object result.
#How to Test StripeWrapper
Test return object charge
:
1 | describe StripeWrapper do |
But there is a problem, everytime we test, it will send a request to Stripe server. We don’t want to do this and want to reduce test consumer time, use gem vcr
.
1 | $ gem install vcr |
Then add vcr: true
to spec
1 | it 'make successful charge', vcr: true do |
vcr will record the reponse in spec/cassettes
, when next time it find that test emit the same request again, it will not send the request outside to the server, but replaying saved response.
Here is vcr setting:
1 | require 'vcr' |
#How to test Controller#create
Since we have test StripeWrapper, we don’t want to test it again in Controller, or hit the Stripe server again. Use Test Double stub
here.
For example, if we have a PaymentController
:
1 | describe PaymentController do |
- Create a test stub
charge
, and stub a methodsuccessful?
and returntrue
. - stub
:create
method toStripeWrapper::Charge
and returncharge
.
Now we strike post :create
, in PaymentController#create when running to code StripeWrapper::Charge, it will return a result charge
with charge.successful?
is true
.
We do this is because make this controller#create test itself independently, and all we need to do is set StripeWrapper return successful.
StripeWrapper will make a HTTP request, we can use
vcr
to record this, but it’s not necessary becuase this test is already done in stripe_wrapper_spec. So here we choose to usestub
.
#How to do Feature Test with JavaScript
Since we use javascript in view form, we need to turn on :js
1 | feature 'visitor make payment' do |
Install gem
1 | gem 'selenium-webdriver' |
And set in spec_helper.rb
1 | Capybara.javascript_driver = :webkit # For default javascript server |
webkit
is offered by Qt
framework, it’s faster than Selenium
and invisible. Selenium
process is visible, so it’s suit for debug.
Careful when test in Email Invitation, I need to use Selenium
instead of webkit
, otherwise the test will be failed.
1 | scenario 'User successfully invites friend and invitation is accepted', {js: true, vcr: true, driver: :selenium} do |
##Setting database_cleaner
It will lead a problem when we run javascript test, refer from RSpec doc:
drivers which run the server in a different thread may not share the same transaction as your tests, causing data not to be shared between your test and test server.
The problem is when running javascript, activerecord may delete database before javascript test finish.
We can use database_cleaner
to do truncation
instead of transaction
. Manual create and destroy records.
1 | RSpec.configure do |config| |