Lapidando ruby

download Lapidando ruby

If you can't read please download the document

Transcript of Lapidando ruby

Lapidando Ruby

A Work in Progress

Maurcio Eduardo [email protected]@mauricio_szabohttp://mauricioszabo.wordpress.com

Nesta Apresentao...

subject { You.new }Ruby.new.should be_false

knowledges.should include(RSpec)

should be_open_to_new_ideas

Por qu?

Aquela jovem uma das menos ignorantemente aparvalhadas formas de vida orgnica que eu j tive a profunda falta de prazer de no ser capaz de evitar encontrar

No Teremos...

Boas prticas

Prefira instncia

Entenda Ruby

Seja claroLogo - TO

Seja preciso

TESTES!

Ruby no ...

Perla.size == 0 or abort

PHPfor element in array

Javaarray.size.times { |i| element = array[i] }

Basic, Cobol, Pascal, C...a = create_person(:name => 'Foo')save_person(a)

Rescue Me!

(Estes cdigos so equivalentes!)

No Abuse da Linguagem

Ruby ajuda muito, mas use com moderaoyield sobre yield sobre yield sobre...Difcil de entender, e LENTO

No use coisas que podem depender da implementao de RubySe for necessrio fazer isso, ISOLE-AS e TESTE-AS INTENSIVAMENTE!

Evite depender de comportamentos no-documentadosreturn array.delete_if { |e| ... }

Evite Efeitos Colaterais

Se voc puder chamar um mtodo duas vezes e ele retornar o MESMO valor, melhor!

DEFina Direito!

Cdigo deve ser escrito como um jornal

No Seja Menos Claro

Flags?

Idente Tudo...

...MAS...

...Evite Identar

Floats?

Imprecisos

SPECs vo falharuse should be_close

Melhor ainda, use BigDecimal

No Modifique os Parmetros

OCP e MonkeyPatch

Classes devem ser ABERTAS para adio e FECHADAS para modificaoModificar mtodos legal, mas a maior fonte de problemas

TDD e BDD

Diferenas?

Como testar, e o qu testar?

Como manter a clareza?

Como evitar testes frgeis?

Como facilitar os testes?

BDD

No so testes, so comportamentosO teste um efeito colateral

Sapir-Whorf, ou Linguistic RelativityMesmo conceito usado pelo RSpec

Mesmo conceito por trs do Ruby

O que , afinal, um unit test?Ou um unit?

RSpec

person.old?.should == trueperson.old?.should be_true

person.should be_old

person.childs.size.should == 10person.should have(10).childs

array.size.should == 5array.should have(5).itens

RSpec on Rails

WTF???

Seja explcito...

Mas seja implcito!

Lembre-se SEMPRE do que voc est descrevendo!

Mocks

Muito usados nos Controllers do RailsQuando eu te perguntar, da prxima vez, exatamente quem voc, me responda um teste, ok?

Voc est testando, ou est escrevendo o cdigo final?

Mocks

Um aluno precisa escolher disciplinaseu SEI que um aluno estar logado...

eu SEI que o aluno estar cadastrado...

eu SEI que haver uma ou mais disciplinas...

mas NO SEI qual o cdigo.

Custom Matchers

Custom Matchers

Facilite seus testes!

O que os dois a seguir tem em comum?stub_model

Factories

Crie suas facilidades!stub_rest, talvez?

http://github.com/defunkt/fakefs

Ler - Scripted GUI Testing with Ruby

Mais uma coisa

Reek (gem install reek)Procura por smells em seu cdigo

Bom quando se est iniciando

Flog (gem install flog)Procura por cdigo torturado

Bom de ser usado em qualquer situao

Metrics_fuPlugin para Rails, incorpora Flog, Reek, RCov, etc...

Consideraes

Ler:Clean Code, Robert Martin

Design Patterns, GoF

Quando estiver programado:Melhorar sempre o cdigo

Cuidado com o termo melhorar

Evite:Comentrios explicando o que o cdigo faz

Dvidas?

The Power and Philosofy of Ruby: http://bit.ly/aMFAmj (Matz)

A new look at Test-Driven Development: http://bit.ly/7nYyhD (Dave Astels)

Clean Code: http://bit.ly/bUzV7k (Robert Martin)

Design Patterns in Ruby: http://bit.ly/9bKRQV (Russell Olsen)

Scripted GUI Testing with Ruby: http://bit.ly/a0etMC (Ian Dees)

def dupla_negativa pessoa_nao_tem_nome = @pessoa.nil? || @pessoa.nome == '' raise ArgumentError, 'Pessoa no possui nome' if pessoa_nao_tem_nome ...enddef atualizar_filhos return nil if @pessoa.nil? @pessoa.filhos.each { |filho| salvar_filho(filho) }end

def salvar_filho(filho) filho.pai = @pessoa filho.save!endprivate :salvar_filhodef atualizar_filhos if @pessoa.nil? || @pessoa.feminino? return nil else @pessoa.filhos.each do |filho| filho.pai = @pessoa filho.save! end endenddef salvar(params = {}) deve_deletar = params.delete :deletar deletar_parametros(params) if deve_deletarenddef salvar(params = {}) params = params.dup deve_deletar = params.delete :deletar deletar_parametros(params) if deve_deletarend

class ActiveRecord::Base def self.name return 'NAME' endend@pessoa = [email protected](false) #False??? Salva mas no salva?@pessoa = [email protected] :without_validations@pessoa = [email protected]_without_validationsputs 10/101.0 #0.0990099009900990.099009900990099 == 10/101.0 #falseit 'deve conseguir escolher a disciplina' do session['aluno'] = 'teste' aluno = Factory :aluno, :login => 'teste' disciplina = Factory :disciplina post :escolher, :disciplinas => [disciplina.id] aluno.should have(1).disciplinaenddescribe Aluno do before do @aluno = Factory.stub :aluno end

context 'com dados vlidos' do before do @aluno.stub!(:save).and_return(true) end

it 'deve...'describe Aluno do context 'com dados vlidos' do it 'deve...' do stub_aluno end end

def stub_aluno @aluno = Factory.stub :aluno @aluno.stub!(:save).and_return(true) endend

describe Sensor do it 'deve piscar se estiver muito quente' do @forno.muito_quente! @sensor.should be_blinking endendSpec::Matchers.create :be_a_valid do |who| match do |person| person.send(who).valid? end

failure_message_for_should do |person| "Expected person #{person.name} to be a valid #{who}" end

failure_message_for_should_not do |person| "Expected person #{person.name} to not be a valid #{who}" endenddescribe Person do it 'should create a valid student' do @person = Person.new(:student_data => { :grade => 1 }) @person.should be_a_valid(:student) end

it 'should create a invalid employee' do @person = Person.new @person.should_not be_a_valid(:employee) endenddef dividir(a, b) begin resultado = a / b rescue return nil end return resultadoenddef dividir(a, b) return a / b rescue nilenddef dividir(a, b) return a / brescue return nilendit "renders a list of people" do render response.should have_tag("tr>td", "name".to_s, 2)endit "assigns all people as @people" do Person.stub(:find).with(:all).and_return([mock_person]) get :index assigns[:people].should == [mock_person]enddef imprimir formatacao = formatar(:padrao) preparar_pagina(formatacao)end

def formatar_pagina(tipo) ...endprivate :formatar_pagina

def preparar_pagina(formatacao) ...enddef dupla_negativa unless [email protected]? && @pessoa.nome == '' ... else raise ArgumentError, 'err... bem... bom...' endenddef somar_numeros(a, b) @c += 1 return a + b + @cenddef somar_numeros c = @c + 1 return a + b + cend