Sobre as eleições 2010

Estou repassando o vídeo abaixo da palavra de advertência acerca das eleições de 2010 dada pelo Pr. Paschoal Piragine Jr, da Primeira Igreja Batista de Curitiba/PR.

Normalmente não me pronuncio acerca de questões eleitorais, mas diante do momento que estamos vivendo, não diremos, nas palavras do Pr. Piragine, “em quem votar, mas em quem não votar”…

Referência: http://blogdosubira.wordpress.com

Integração Sinatra, Cucumber e Webrat

Sempre que consigo algum tempo tento escrever alguma coisa no blog e desta vez quero mostrar como é fácil o desenvolvimento em BDD no Sinatra usando Cucumber e Webrat. Para quem numca ouviu falar nesses caras vamos as apresentações. 🙂

Quem é esse Sinatra?
Para quem não saber Sinatra é uma linguagem de domínio específico (DSL – Domain Specific Language) para a criação rápida de aplicações web escritas em ruby. Ele mantém uma característica mínima definida, deixando livre o desenvolvedor para utilizar as ferramentas que melhor lhe servir em sua aplicação.

BDD? Cucumber?
BDD ou Behavior Driven Development(Desenvolvimento Guiado por Comportamento) é uma técnica de desenvolvimento Ágil que encoraja colaboração entre desenvolvedores, setores de qualidade e pessoas não-técnicas ou de negócios num projeto de software. O foco em BDD é a linguagem e interações usadas no processo de desenvolvimento de software.

O Cucumber foi criado para permitir que você execute a documentação de funcionalidades de uma aplicação, escritas em texto puro (também conhecidas como “estórias”). Com o Cucumber, isto é uma especificação executável que você pode discutir com seu cliente e então usá-la para verificar o comportamento correto dos testes. Por trás dos bastidores, você faz isto funcionar criando “steps”, que são expressões regulares que executam código em Ruby.

Webrat
Webrat é uma ferramenta fantástica que permite escrever rapidamente testes de aceitação expressivos e robustos para uma aplicação web Ruby. Ele nos fornece entre outras coisas:

  • Simulador de browser de alto nível;
  • Suporta vários frameworks web Ruby;
  • Suporta os mais populares frameworks de teste;
  • Fornece uma API para verificar o HTML gerado usando CSS, XPath, etc.

Depois de feita as devidas apresentações vamos colocar a mão na massa. O primeiro passo é criar o diretório de nosso projeto.

1
2
$ mkdir sinatra-cucumber
$ cd sinatra-cucumber

Vamos acessar a pasta do projeto que acabamos de criar e executar os comandos abaixo para criar a pasta onde iremos definir nossas features.

1
2
$ mkdir features
$ touch features/ola.feature

Obs.: Para quem não conhece o comando touch apenas criou um arquivo vazio.

No arquivo ola.feature escreva o seguinte código:

1
2
3
4
5
6
7
8
9
# language: pt
Funcionalidade: Ver páginas
  Como um usuário qualquer
  Eu quero acessar as páginas do sistema
  Para ter acesso a seu conteúdo
 
  Cenário: Página principal
    Dado que acabei de acessar o sistema
    Então Eu devo ver o texto "Olá, pessoal!"

Vamos executar o cucumber e ver o que acontece. 🙂

1
$ cucumber features/ola.feature

Como era de esperar o teste não passou. Vamos em seguida criar os testes para nossa funcionalidade mais antes iremos criar uma tarefa rake para otimizar a chamada do Cucumber.

1
$ touch Rakefile

O código para nossa tarefa rake que será executada com o comando “rake features” é o seguinte:

1
2
3
4
5
6
require 'rubygems'
require 'cucumber/rake/task'
 
Cucumber::Rake::Task.new(:features) do |t|
  t.cucumber_opts = '--format pretty'
end

Agora sim podemos continuar.

1
2
$ mkdir features/step_definitions
$ touch features/step_definitions/ola_steps.rb

No arquivo ola_steps.rb teremos o seguinte código:

1
2
3
4
5
6
7
Dado /^que acabei de acessar o sistema$/ do
  visit("/")
end
 
Entao /^Eu devo ver o texto "(.+)"$/ do |texto|
  response_body.should =~ Regexp.new(Regexp.escape(texto))
end

Estes dois passos simples fazem uma solicitação a url do nosso aplicativo pelo Webrat e verifica se a resposta contém o texto que estamos procurando.

Abaixo segue as configurações que fazem a integração realmente acontecer. Vamos configurar o ambiente do Cucumber para usar o Webrat.

1
2
$ mkdir features/support
$ touch features/support/env.rb

O conteúdo do arquivo env.rb deve ser o seguinte:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
require 'spec/expectations'
require 'rack/test'
require 'webrat'
 
Webrat.configure do |config|
  config.mode = :rack
end
 
class MyWorld
  include Rack::Test::Methods
  include Webrat::Methods
  include Webrat::Matchers
 
  Webrat::Methods.delegate_to_session :response_code, :response_body
 
  def app
    Sinatra::Application
  end
end
 
World do
  MyWorld.new
end
 
require File.dirname(__FILE__) + '/../../ola'

Agora que temos nosso cenário montado podemos escrever nossa aplicação web com essas simples linhas abaixo:

1
$ touch ola.rb
1
2
3
4
5
6
require 'rubygems'
require 'sinatra'
 
get '/' do
  "Olá, pessoal!"
end

Agora vamos executar mais uma vez o Cucumber e ver os testes passando para ficarmos felizes. 🙂

1
$ rake features

Bom pessoal, o objetivo foi cumprido e espero que tenha ficado claro como é fácil desenvolver em Sinatra usando BDD com Cucumber e Webrat. Sei que o exemplo foi bem simples e abaixo segue o código fonte do projeto e alguma referências para você conhecer mais do assunto.

Código fonte
http://github.com/igocoelho/sinatra-cucumber

Conheça mais
Livro de Sinatra em Português
http://sinatra.tailorfontela.com.br/

Aplicação simples com Sinatra
http://pomoti.com/aplicacao-simples-com-sinatra

BDD com Cucumber, Selenium e Rails
http://www.slideshare.net/cmilfont/bdd-com-cucumber-selenium-e-rails

Introducão ao BDD com Cucumber, RSpec, Webrat e Selenium – Parte I
http://jefferson.eti.br/?p=96

Introducão ao BDD com Cucumber, RSpec, Webrat e Selenium – Parte II
http://jefferson.eti.br/?p=105

Introducão ao BDD com Cucumber, RSpec, Webrat e Selenium – Parte III
http://jefferson.eti.br/?p=139

Screencast Ruby on Rails: Introdução a RSpec e Cucumber
http://vimeo.com/7108280

Gerenciando as dependências com Ruby Tracker

Ruby Tracker é um projeto de apoio à comunidade liderado por Jacob Swanner que tem como objetivo monitorar e informar as dependências entre gems em projetos Ruby.

O Ruby Tracker funciona examinando o projeto e verificando quais gems são utilizadas e principalmente quais versões. Quando for preciso autalizar qualquer gem você será informado quais outras também devem ser atualizadas e para qual versão.

Segue abaixo um vídeo demonstrando melhor o uso da ferramenta:

Para não esquecer: Ruby on Rails Unit Testing Assertions

Basic Assertions

assert(boolean, message)
assert(person.name == “John”, “Name was expected to be John.”)
assert(item.errors.invalid?(:price))

assert_equal(expected, actual, message)
assert_equal(person.name, “John”, “Name was expected to be John.”)
assert_equal(“can’t be empty”, product.errors.on(:price))

assert_not_equal(expected, actual, message)

assert_not_equal(person.name, “Mary”, “Name was Mary and it should not be.”)
assert_not_equal(“is not a number”, product.errors.on(:price))

assert_raise(Exception, message) { block… }

assert_raise(ZeroDivisionError, “Cannot divide by zero!”) { 100 / 0 }
assert_raise(ActiveRecord::RecordNotFound) { Product.find(bad_id) }

assert_nothing_raised(Exception, message) { block… }

assert_nothing_raised(ZeroDivisionError) { 100 / [0,1].max }
assert_nothing_raised(ActiveRecord::RecordNotFound) { Product.find(good_id) }

assert_nil(object, message)

assert_nil( product, “Expected product to be nil.” )
assert_nil( Wine.find(:first, :conditions => ‘id = 1000’) )

assert_not_nil(object, message)

assert_not_nil( product, “Product should not be nil.” )
assert_not_nil( Wine.find(:first, :conditions => ‘id = 1’) )

assert_valid(activerecord_object)

same as: assert(object.valid?)
assert_valid(@person)
assert_valid( Wine.find(1) )

flunk(message)

always fails immediately; same as: assert(false, message)
flunk(“Quantity should not be greater than 100”) if quantity > 100
flunk(“Either user or account should be valid”) unless user.valid? || account.valid?

Advanced Assertions

assert_match(pattern, string, message)
assert_match(/^\d,\d{3},\d{3}$/, “1,000,000”, “Should match this format.”)

assert_no_match(pattern, string, message)

assert_no_match(/\d{3},\d{2}$/, “1,000,000”, “Should not match this format.”)

assert_in_delta(expected_float, actual_float, delta, message)

assert_in_delta(100.0, price, 20.0, “Price should be between 80.00 and 120.00”)
assert_in_delta(2, length, 1, “Length should be 1-3 feet.”)

assert_instance_of( klass, object, message )

assert_instance_of( User, person, “person should be an instance of User” )

assert_kind_of( klass, object, message )

assert_kind_of( User, person, “person should be a kind of User” )
assert_kind_of( Class, User, “User should be a kind of Class” )

assert_respond_to( object, symbol, message )

Instances only respond to instance methods, classes only respond to class methods
assert_respond_to( person, :full_name, “No response to full_name” )
assert_respond_to( User, :custom_find, “No response to custom_find” )

assert_throws(expected_symbol, message) { block… }

assert_throws(:done, “Array should be empty”) { throw :done if [].empty? }

assert_nothing_thrown(message) { block… }

assert_nothing_thrown(“Array should not be empty”) { throw :done if [1].empty? }

Rare Assertions & DEFAULT EROR MESSA GES

assert_same( expected, actual, message)
same as: assert_equal(expected, actual)
assert_same( person.name, “John”)

assert_not_same( expected, actual, message)

same as: assert_not_equal(expected, actual)
assert_not_same( person.name, “Mary”)

assert_operator( object1, operator, object2, message )

same as: assert( object1.operator(object2) )
assert_operator( 1000, :<, 2000, “Expected 1000 to be less than 2000” )
assert_operator( user, :old_enough?, Time.now(), “User should be old enough”)

assert_send([receiver, symbol, arg1, arg2], message)

same as: assert( receiver.message(arg1, arg2) )
assert_send([product, :decrement_inventory, qty], “Decrement should succeed”)

From: /activerecord/lib/active_record/validations.rb

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
@@default_error_messages = {
:inclusion => “is not included in the list”,
:exclusion => “is reserved”,
:invalid => “is invalid”,
:confirmation => “doesn’t match confirmation”,
:accepted => “must be accepted”,
:empty => “can’t be empty”,
:blank => “can’t be blank”,
:too_long => “is too long (maximum is %d characters)”,
:too_short => “is too short (minimum is %d characters)”,
:wrong_length => “is the wrong length (should be %d characters)”,
:taken => “has already been taken”,
:not_a_number => “is not a number”,
:greater_than => “must be greater than %d”,
:greater_than_or_equal_to => “must be greater than or equal to %d”,
:equal_to => “must be equal to %d”,
:less_than => “must be less than %d”,
:less_than_or_equal_to => “must be less than or equal to %d”,
:odd => “must be odd”,
:even => “must be even”
}

Referência:
http://www.nullislove.com/2008/02/20/testing-in-rails-part-10-assertions/