Testes on Rails
Como testar?
gem install rspec
describe 'In my calculator' do context 'when plus 1 to 2' do it 'should return 3' do expect(Calculator.sum(1, 2)).to eq 3 end endend
Teste{ }
Como testar código que depende de tempo?
gem install timecop
➔ Tenha controle do tempo ao executar os seus testes;
➔ Você consegue literalmente viajar no tempo;
➔ Poderíamos até prever o Bug do Milênio;
{ }Tempo fixo
def start @started = Time.nowend
it 'should save the initial time' do Timecop.freeze do auction.start expect(auction.started).to eq Time.now endend
Teste
{ }Variação de tempo
def bid(inc) return false if (Time.now - @started) > 120 @value += incend
describe 'after 2 minutes' do it 'should not accept bids' do auction.start
Timecop.travel(Time.now + 120) do expect(auction.bid(300)).to be_falsey
end endend
Teste
Como testar dependência de APIs?
Dificuldades
➔ O seu código depende do retorno da API
➔ Você estará testando também a API externa
➔ A requisição HTTP pode demorar (ou não funcionar…)
➔ Você não tem total controle do retorno da requisição
def self.my_ip req = get 'http://httpbin.org/ip' parse = JSON.parse(req.body) parse['origin']end
it 'should get my ip' do expect(ExternalApi.my_ip).to eq '192.168.1.1'end
Teste
{ }Código
gem install webmock
➔ Criar mock das requisições HTTP
➔ Se você esquecer de alguma ou tiver dúvidas de como criar, ele sugere para você
➔ Isole totalmente o seu código de interferências externas
def self.my_ip req = get 'http://httpbin.org/ip' parse = JSON.parse(req.body) parse['origin']end
it 'should get my ip' do stub_request(:get, "http://httpbin.org/ip"). with(:headers => {'Accept'=>'*/*', 'User-Agent'=>'Ruby'}). to_return(:status=>200, :body=>'{"origin": "192.168.1.1"}') expect(ExternalApi.my_ip).to eq '192.168.1.1'end
Código
Teste
{ }
Fixtures?!?
Dificuldades
➔ Manter vários arquivos YAML
➔ Gerenciar relacionamentos entre as models / fixtures
➔ “Acoplamento” com o AR
➔ Fixtures dinâmicas
# spec/fixtures/users.ymlfoo: name: Foo last_name: Bar
it "is composed of first name" do user = users(:foo) expect(user.name).to eq(“Foo”)end
Código
Teste
{ }
# spec/fixtures/users.ymlfoo: id: 1 name: Foo last_name: Bar
it "is composed of street name" do address = addresses(:foo)
expect(address.street).to eq(“Foo Street”) expect(address.user.name).to eq(“Foo”)end
Código
Teste
{ }# spec/fixtures/addresses.ymlfoo_address: street: Foo Street number: 10 user_id: 1
gem install factory_girl
# spec/factories/users.rbFactoryGirl.define do factory :user do name “Foo” endend
it "is composed of first name" do user = FactoryGirl.create(:user) expect(user.name).to eq(“Foo”)end
Teste
{ }
# spec/factories/foo.rbFactoryGirl.define do factory :user do name “Foo” end
factory :address do street “Foo Street” association :user, factory: :user endend
{ }
Mais algumas coisas legais
#build
#create
#attributes_for
#build_stubbed
#hooks
Como escolher as Gems para meu projeto?
ruby-toolbox.com
rubygems.org
https://github.com/webgoal/tests-on-rails