Encontro noSQL Brasil

12.maio.2010
O noSQL Brasil é o primeiro encontro brasileiro que visa apresentar, promover e discutir as tecnologias “noSQL”. Para isso, serão realizadas palestras sobre as diversas abordagens noSQL com exemplos práticos e demonstrações, bem como um painel onde será discutido como e quando utilizar noSQL.

Onde: Hotel Quality Vila Olímpia – Sala Sevilla
Rua Fidêncio Ramos, 420 – Vila Olímpia
São Paulo, SP
[mapa]

Para maiores informações, visite o site do evento


BDD com Rails e Cucumber

03.novembro.2009
Cucumber é um framework de BDD para Rails que permite que sejam escritos testes de maneira muito próxima à linguagem comum do cliente, ou seja, um mesmo documento de testes pode ser compreendido facilmente pelo cliente e pelo desenvolvedor, com o mínimo possível de ambiguidade e ruido.

Para instalar, considerando obviamente que você já tem o Rails instalado, digite

gem sources -a http://gems.github.com
sudo gem install cucumber webrat rspec rspec-rails

No diretório raiz do seu projeto, digite

script/generate cucumber --rspec

E o suporte ao Cucumber será adicionado à sua aplicação, assim como uma pasta /features.

Na pasta features, cria um arquivo com extensão .feature. Por exemplo, manage_users.feature.

Vamos editar o arquivo e começar com a definição da funcionalidade (ou user story, se preferir):

Feature: Manage users
    In order to manage users
    Visitors should be able to
    sign up and change their own stuff

Atenção para a tabulação. Ela é fundamental para o bom funcionamento da ferramenta.

Em seguida, vamos adicionar os cenários possíveis que se aplicam a essa funcionalidade. Nesse caso podemos pensar nas situações que podem ocorrer para gerenciarmos usuários. Futuramente podemos adicionar mais situações que não foram previstas inicialmente e situações que estão causando comportamentos inesperados na sua aplicação.

  Scenario: Add new user
      Given the Visitor wants to signup
      When the Visitor clicks signup
      Then open the signup page

Novamente, atenção para o espaçamento no início de cada linha.

Execute o comando cucumber e você vai ver uma saída parecida com essa:

Feature: Manage users
    In order to manage users
    Visitors should be able to
    sign up and change their own stuff

  Scenario: Add new user              # features/manage_users.feature:6
    Given the Visitor wants to signup # features/manage_users.feature:7
    When the Visitor clicks signup    # features/manage_users.feature:8
    Then open the signup page         # features/manage_users.feature:9
1 scenario (1 undefined)
3 steps (3 undefined)
0m0.297s

You can implement step definitions for undefined steps with these snippets:
Given /^the Visitor wants to signup$/ do
  pending
end

When /^the Visitor clicks signup$/ do
  pending
end

Then /^open the signup page$/ do
  pending
end

O texto em amarelo significa que o teste (step na documentação do Cucumber) ainda não foi implementado.

Dentro da pasta features, tems uma chamada step_definitions. Nessa pasta vamos criar um arquivo manage_users.rb, copie o primeiro trecho em amarelo (Given … end) e cole no arquivo. Apague a linha onde está escrito pending e escreva seu código de teste.
Ele vai ficar assim:

Given /^the Visitor wants to signup$/ do
  #simula a visita do cliente à página principal, onde temos um link escrito "Quero me cadastrar"
  get '/' 
end

Ao executar cucumber novamente, veremos a seguinte saída:

(...)
  Scenario: Add new user              # features/manage_users.feature:6
    Given the Visitor wants to signup # features/manage_users.feature:7
    When the Visitor clicks signup    # features/manage_users.feature:8
    Then open the signup page         # features/manage_users.feature:9

Vemos a linha do step que escrevemos na cor verde, ou seja, o teste passou.

O modo correto de se trabalhar com Cucumber é, assim como em TDD, escrever o teste, dentro de um step, executar e vê-lo falhar. Ao falhar, a linha será apresentada em vermelho. Programe somente o necessário para o teste passar (ficar verde), e passe imediatamente para o próximo step.

Existem formas de se trabalhar com Cucumber em outros idiomas, gerar documentação em HTML e PDF e outros macetes, mas isso vai ficar para um próximo post.

Enjoy 😉


Melhorando a expressividade dos testes unitários com JUnitXtension – Parte 2

26.outubro.2009
Na Parte 1 eu apresentei a motivação da biblioteca JUnitXtension. Recomendo a leitura.

Por que assertNotEquals ao invés de assertDifferent?

Eu poderia ter usado assertDifferent ao invés de assertNotEquals, mas isso poderia nos levar a um problema semântico. Em Java, == (operador de comparação de igualdade) tem um comportamento diferente de equals (método utilizado para checar a igualdade de valores).

No caso de uma String, por exemplo, "foo" == "foo", ou seja, uma String é sempre igual a ela mesma. Porém, se tivermos uma variável foo, contendo “foobar” e outra bar, também contendo “foobar”, estaremos falando de variáveis diferentes, posicionadas em locais diferentes da memória e, na maioria das vezes, com valores também armazenados em endereços diferentes, fazendo com que o uso do operador == retorne falso, mesmo quando ambas contém o valor “foobar”.

Por conta de situações como essa, os objetos Java contém o método equals, que verifica se o conteúdo é igual, e não o endereço onde o conteúdo está guardado. Usando o exemplo do parágrafo anterior, foo.equals(bar) retornaria verdadeiro.

Sendo assim, para comparação entre objetos, assertDifferent deveria checar se o objeto informado é exatamente o mesmo do objeto esperado, o que até hoje ainda não vi acontecer. assertEquals checa se o valor da objeto informado é igual ao valor esperado, o que respeita a idéia inicial de uma asserção.

Por outro lado, em Java existe o conceito de tipos primitivos, que são números, bytes, caracteres e valores booleanos (true, false). Como um tipo primitivo não é um objeto, não existe a preocupação de termos um mesmo valor em endereços de memória diferentes, então uma comparação entre foo=42 e bar=42 é sempre verdadeira. Nesse caso sim o uso de assertDifferent faria sentido, mas causaria uma bela confusão por causa da sujeira que mais e mais asserções redundantes traria. Quando tratamos de números, podemos tanto dizer que 42 é diferente de 0 como podemos dizer também que 42 não é igual a 0. Então fica o assertNotEquals e não se fala mais nisso =)

Se interessou pela idéia? Você encontra os mesmos problemas e quer conhecer mais? A biblioteca está na versão 0.1.1 e pode ser encontrada no Google Code. Críticas construtivas são sempre bem vindas.

Keep testing =)

P.S.: Agradecimentos públicos à minha esposa e ao Fábio Serra pelas revisões nesse post


Melhorando a expressividade dos testes unitários com JUnitXtension – Parte 1

23.outubro.2009
Qual dos códigos é mais simples de ler?

Código A

assertFalse(foo.equals(bar));

assertFalse(foobar == 2);

Código B

assertNotEquals(foo, bar);

assertNotEquals(foobar, 2);

Inicialmente criado apenas como um projeto para me auxiliar no trabalho a escrever testes mais simples de ler, resolvi compartilhar no Google Code a biblioteca, atualmente na versão 0.1.1.

A principal motivação foi de criar novas asserções que melhorem a expressividade, mesmo que redundantes, para que o desenvolvedor não tenha que escrever códigos auxiliares limitados à API padrão do JUnit.

Internamente o próprio JUnit trabalha dessa maneira. Praticamente todas as demais asserções são abstrações sobre assertTrue, no máximo adicionando alguma formatação diferenciada para que o resultado e um teste falho seja legível.

Ao invés de, por exemplo, escrevermos assertFalse(0 == 1), podemos escrever assertNotFalse(0, 1). Ao invés de assertTrue(x > 0), podemos simplesmente escrever assertGreaterThanZero(x) e assim por diante.

Outra vantagem diz respeito à cobertura de testes. Em alguns casos, quando se usa assertFalse(x == 0), o algoritmo que calcula a cobertura vai informar que essa linha foi apenas parcialmente testada. Na verdade queremos apenas testar se x é igual a zero, mas se você persegue os 100% de cobertura, esse tipo de problema obriga a criar código extra apenas para manter a cobertura do código satisfatória. Utilizando assertNotEquals(0, x), ou o teste passa ou não passa, reduzindo para apenas duas as opções possíveis, limpando o código e aumentando automagicamente a cobertura.

Se interessou pela idéia? Você encontra os mesmos problemas e quer conhecer mais? A biblioteca está na versão 0.1.1 e pode ser encontrada no Google Code. Críticas construtivas são sempre bem vindas.

Keep testing 😉

P.S.: Agradecimentos públicos à minha esposa e ao Fábio Serra pelas revisões nesse post


Detox

21.agosto.2009
Desenvolvedor também tem vida pessoal.

Finalmente tirei férias e vou aproveitar o tempo livre para casar, ter um(a) filho(a), tomar um pouco de sol, escrever um artigo, montar uma palestra e, se sobrar tempo, escrever uma aplicação de OCR só pelo tesão de programar.

Bom final de Agosto e bom início de Setembro a todos e lembrem-se, crianças: Winners write tests 😉


RESTful Rails automático

02.julho.2009
Solução OO para fazer sua aplicação Rails trabalhar de modo RESTful:

application_controller.rb:

  def index
    begin
      if request.post?
        create
      elsif request.get?
        read
      elsif request.put?
        update
      elsif request.delete?
        delete
      end
    rescue NameError
      respond_to do |format|
        format.html {render :text => "<h1>Forbidden</h1>", :status => 403}
      end
    end
  end

E no arquivo routes.rb:

  map.connect ':controller/:id'
  # map.connect ':controller/:action/:id'

Como funciona?

Uma aplicaçao Rails RESTful funciona, basicamente, utilizando o método HTTP como verbo e a URI como substantivo.

Ao invés de algo do tipo http://application:3000/user/view/1, com REST você usa http://application:3000/user/1 para pegar os dados, atualizar ou apagar, mudando apenas o método HTTP da chamada.

Porém, por padrão, o Rails entende as requisições como sendo /controller/action/id, por isso a alteração no arquivo routes.rb, para fazer com que o segundo parâmetro seja o ID, já que quem define a action é o próprio método HTTP.

Dependendo do método utilizado, será executada uma action padronizada que será escrita no seu próprio controller, usando o conceito de sobrescrita de métodos. Caso você não escreva qualquer uma das actions, será exibida uma mensagem de erro padrão, permitindo que você foque somente no desenvolvimento do que for necessário.


Scott Adams was right

03.junho.2009
dilbert2

De volta ao Brasil, e de volta à programação normal.

A propósito, um desafio geek. Refatore o código abaixo:

do {
} while (window[++scan] == window[++match] && window[++scan] == window[++match] && window[++scan] == window[++match] && window[++scan] == window[++match] && window[++scan] == window[++match] && window[++scan] == window[++match] && window[++scan] == window[++match] && window[++scan] == window[++match] && scan < strend);

Simples 😛