rspec Parte 2 – Testando controllers

Bom dia Pessoal.

Continuando a serie de posts sobre rspec. Estou me acostumando com essa ferramenta, mas de cara já posso dizer que é fantástica, pois você consegue agilizar alguns testes como validar se os cotrollers estão respondendo como esperado, sem a necessidade de dar um refresh no browser.

Hoje irei mostrar como testar controllers.

Pelo que andei pesquisando há um grande debate quando se trata de testar controllers ou não. No meu caso eu acho valido, mas esta é a minha opinião. Isso assegura que todas as rotas e comportamentos da aplicação estejam corretos.

No meu exemplo estarei testando também os acessos ao banco usando a gem FactoryGirl para criar objetos fake. Nós estamos usando também a gem Devise para realizar as autenticações. Vamos lá.

Vou utilizar o projeto toPlay como exemplo, eu não me atenho a detalhes no teste dos controllers somente valido se estes estão respondendo como o esperado (formato, redirect, etc). Quando necessário utilizo o FactoryGirl para criar os objetos para teste.

Meu controller:

class AnswerController < ApplicationController
  def get_answer
    @answer = Alternative.find(params[:answer_id])
    respond_to do |format|
      format.json { render json: { is_correct: @answer.correct } }
    end
  end
end

Basicamente este controller me responde se a alternativa escolhida é a correta, simples. O que eu testo neste caso:

- Crio os objetos para teste nesse caso, o exercicio e uma alternativa correta e incorreta.

RSpec.describe AnswerController, :type => :controller do

  let(:exercise){ FactoryGirl.create(:exercise) }
  let(:correct){ FactoryGirl.create(:alternative) }
  let(:incorrect){ FactoryGirl.create(:alternative_incorrect) }

Descrevo o metodo a ser testado

  describe "GET #get_answer" do

Dou um contexto, neste caso, user não logado

  context 'user not logged' do

E os comportamentos esperados

it 'should redirect user' do
  sign_out
  get :get_answer, { answer_id: correct.id , format: :json }
  expect(response).to be_redirect
end

Neste caso o controller me responde com JSON então eu testo um retorno Html e Json. Não espero um retorno HTML então deve dar um erro.

    context 'when request html' do
      it {
        expect{
          get :get_answer, { exercise_id: exercise.id, answer_id: correct.id }
        }.to raise_error ActionController::UnknownFormat
      }
    end

Testo os retornos para uma resposta certa e uma errada.

    context 'when given a correct answer' do
      before :each do
        sign_in
        correct.correct = true
        correct.save
        get :get_answer, { answer_id: correct.id , format: :json }
      end

      it{ expect(response).to be_success }
      it{ expect(response.content_type).to be_eql 'application/json' }
      it{ expect(response.body).to be_include '"is_correct":true' }

    end

    context 'when given a incorrect answer' do
      before :each do
        sign_in
        incorrect.correct = false
        incorrect.save
        get :get_answer, { answer_id: incorrect.id , format: :json }
      end

      it{ expect(response).to be_success }
      it{ expect(response.content_type).to be_eql 'application/json' }
      it{ expect(response.body).to be_include '"is_correct":false' }

    end

O código completo pode ser visto em:

https://github.com/CristianOliveiraDaRosa/toPlay/blob/master/spec/controllers/answer_controller_spec.rb

Neste modelo, você pode reparar que são testes simples, pois como comentei não me atenho a muitos testes de controller, prefiro apenas validar rotas e respostas esperadas.

Espero ter ajudado.

Quando usar Mocks e Stubs?

Bom dia Pessoal.

Continuando os estudos sobre TDD e BDD, estes dias me venho a questão:
- Quando usar Mocks/Stubs?
- Quando não usar?

Então pensei, isso é uma boa questão, pois se você exagerar no uso deles seus testes podem se tornar fakes, desnecessários e/ou confusos.

O que são Mocks

Segundo Martin Flower, são instancias de objetos reais, mas treinados para dar retornos esperados. Para utiliza-los você precisa de um framework, por exemplo no Java temos o Mockito, EasyMock entre outros.

Exemplo:

   @Test
   public void testGivenNewBehaviorForToStringWhenCastItShouldReturnNewReturn()
   {
      // given
      String resultExpected = "New Return";
      MyObject instance = Mockito.mock(MyObject.class);
      Mockito.when(instance.toString()).thenReturn(resultExpected);
      
      // when
      String result = instance.toString()
      
      // then
      assertEquals(resultExpected, result);
    }

O que são Stubs

Segundo Martin Flower, são implementações de interfaces com retorno esperados para testes de integração.

Veja o exemplo, vamos supor que temos a seguinte interface:

  public interface IJob {
    public String getResult();
  }

E uma classe usando ela:

class Worker {
  private IJob job;
  
  public void setJob(IJob job)
  {
     this.job = job;
  }

  public String work()
  {
     return job.getResult();
  } 
}

Seu teste usando Stub seria assim:

 class WorkerTest extend TestCase {
     @Test
     public void testGivenNewJobWhenWorkItShouldReturnJobDone()
     {
         // given
         String resultExpected = "Job done.";
         Worker worker = new Worker();
         worker.setJob(new StubJob());

         // when
         String result = worker.work();         

         // then
         assertEquals(resultExpected, result);
     }

     class StubJob implements IJob {
         @override 
         public String getResult()
         {
            return "Job done.";
         }
     }
 }

Quando devo usar?

Teste Unitário , como o proprio nome diz, é o teste da classe/funcionalidade/comportamento esperado. Se para testar isso, você tem que se preocupar muito com dependências, acesso a banco, webservice, configurações e isto irá influênciar no resultado, talvez a saída seja o uso de mocks/stubs para emular estes retornos e testar só as funcionalidades da classe que possui estas dependências.

Quando usar um e quando usar outro?

Segundo Dave Sayer em seu artigo para spring.io (Artigo em Inglês):

Seu teste deve ser fácil de ler e manter, então utilize a ferramenta que mais se adapte a estas duas necessidades. Caso o teste começe a ficar complexo dificultando o entendimento do que está sendo testado, talves seja o momento de repensar ele.

Abraços

Bower e Rails. Pode isso Arnaldo?!

Bom dia Galera.

Há um tempo atrás descobri o bower desde então venho utilizando muito ele, pois como os demais gerenciadores de dependencias que temos em outras linguagens, este também é uma mão na roda! Ele é o mesmo que o bundler é para o rails, Maven é para o Java, etc.

Hoje vou mostrar uma maneira fácil de integrar toda a funcionalidade do bower com a agilidade do Rails. Existe gems para realizar esta integração como a https://github.com/stve/bower entre outras, mas neste tutorial eu vou fazer no braço.

Bower install

Vamos por a mão na massa. Você vai precisar:

  • -Node.js instalado

Ubuntu

$ apt-get install node

Mac

$ homebrew install node
  • -Bower installado via node.js
$ npm install -g bower
  • -Rails é claro.

Crie sua aplição:

$ rails new app_with_bower
$ cd app_with_bower
$ bundle install

Inicie o bower na sua aplicação:

$ bower init

Ele irá lhe fazer uma serie de perguntas sobre a aplicação, logo apos isto ele vai gerar um bower.json com dados sobre ela:

{
  "name": "BlaBla",
  "version": "0.0.01",
  "homepage": "https://github.com/CristianOliveiraDaRosa/Bla",
  "authors": [
    "Cristian Oliveira <contato@cristianoliveira.com.br>"
  ],
  "description": "Bla bla bla",
  "moduleType": [
    "node"
  ],
  "keywords": [
    "Gamification",
    "Math",
    "Statistics"
  ],
  "license": "MIT",
  "private": true,
  "ignore": [
    "**/.*",
    "node_modules",
    "bower_components",
    "test",
    "tests"
  ]
}

Como default o bower instala todas as dependencias em bower_components, primeiro vamos alterar isso e colocar em uma pasta mais “Rails like”. Ou seja, em “app/assets/components”.
Crie um arquivo chamado .bowerrc para setar configurações ao Bower:

{
   "directory": "vendor/assets/components"
}

Perfeito está configurado.

Configurações no Rails

Para que o Rails “enxergue” os componentes que o bower irá instalar na pasta que configuramos anteriormente precisamos alterar o “/config/application.rb”:
Adicione ao final:

    config.assets.paths << Rails.root.join('vendor','assets', 'components')

Here we go!

Dentro da pasta da sua aplicação instale um componente qualquer. Uma dica, se você não sabe o nome completo do componente use o comando “search” ele vai te dar algumas opções.

$ bower install sweetalert

*Essa é uma biblioteca muito boa para alertas em js #ficadica.

E é só adicionar no seu html normalmente ou de uma maneira mais elegante fazer um require em /assets/javascripts/application.js

//= require jquery
//= require jquery_ujs
//= require foundation
//= require sweetalert/lib/sweet-alert 
//= require_tree .

$(function(){
 ...bla
})

Era isso enjoy!

Entendendo o rspec – Parte 1

Olá Pessoal.

Recentemente peguei um job onde o desenvolvedor que iniciou o projeto trabalhava com testes com rspec. Então resolvi aproveitar a oportunidade para aprender um pouco mais sobre o assunto. Pesquisei bastante até entender seus conceitos.

Segundo a documentação do rspec, ele foi desenvolvido para compreender os aspectos do BDD(Behaviour Driven Development) algo como “Desenvolvimento voltado ao Comportamento” uma variação do TDD, desenvolvimento voltado a testes. Ambos Processos de desenvolvimento ágil. É por isso, que no rspec utilizam-se palavras como “Behaviour” ao invés de “Teste” e “Exemplo” ao invés de “Método”.

Pré requistos:

  • Ruby 1.8.4 ou maior
  • A última versão da gem RSpec (3.0.3)

Instale o rspec

 
   $ gem install rspec

Crie os Comportamentos Esperados.

Para seguir a risca os conceitos do BDD é necessário que você crie os comportamentos esperados antes de implementar de fato a lógica. Vamos ao exemplo:

Crie um arquivo carro_spec.rb inicialmente com:

   
   describe Carro do
   end

e execute o spec:

   
   $ spec carro_spec.rb

Provavelmente ele dara o seguinte retorno:

  ./carro_spec.rb:1: uninitialized constant Carro (NameError)

Pois ainda não declaramos a classe Carro. Sendo assim crie um arquivo chamado carro.rb com o conteudo:

    class Carro
       @is_on

        def initialize
    	   @is_on = false
        end

        def start
       	    @is_on = true
        end

	def on?
	    @is_on
	end
    end

E declare-o:

require 'carro'

    describe Carro do
        it ":expect be on to run" do
            carro = Carro.new
            expect(carro).to be_on(true)
        end
    end

E execute novamente:

$ spec carro_spec.rb -fdoc

Carro
  expect not be on
  expect be on to run

Finished in 0.022865 seconds

2 example, 0 failures

Acredito que seja auto explicativo. Você vai criando situações de comportomentos e após suas implementações para suprir os specs. Simples e eficiente.

Abração.

Série de Videos sobre UML

Bom dia Pessoal.

Recentemente me deparei com esta série de videos criadas pelo Derek Banas. Estes tutoriais são muito bons e simples de entender, porem todos são em Inglês. Vale a pena dar uma olhada:

A ferramenta que ele utiliza é a UMLet

UML – Use Cases

UML – Activity Diagrams

UML – Class Diagram

Neste link você pode ver todas os videos da série totalmente de graça!
https://www.youtube.com/watch?v=OkC7HKtiZC0&list=PLGLfVvz_LVvQ5G-LdJ8RLqe-ndo7QITYc

Att.
Cristian Oliveira

Bug do Facebook-sdk para Android

Bom dia Pessoal.

Recentemente enquanto desenvolvia o protótipo do Ivokee, tive diversos casos de erros com o Facebook-SDK relatados pelos usuários, principalmente quando usavam o aplicativo com a rede 3G. Verificando os logs descobri que este era um bug do proprio SDK do Facebook, ao fazer download da imagem do perfil e por algum motivo ocorria um erro, este a descrição do erro era “baixada” do servidor, mas não havendo resposta era retornado nulo a variavel “stream”, pois acredito que o mesmo não foi feito para trabalhar com a nossa maravilhosa 3G.

O trace do erro:

java.lang.NullPointerException at java.io.Reader.(Reader.java:65) at java.io.InputStreamReader.(InputStreamReader.java:65) at com.facebook.internal.ImageDownloader.download(ImageDownloader.java:248) at com.facebook.internal.ImageDownloader.access$1(ImageDownloader.java:205) at com.facebook.internal.ImageDownloader$DownloadImageWorkItem.run(ImageDownloader.java:356) at com.facebook.internal.WorkQueue$1.run(WorkQueue.java:118) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1068) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:561) at java.lang.Thread.run(Thread.java:1096)

Fiz um fork do projeto e corrigi este erro. Enviei um Pull Request deste meu fork ao pessoal do Facebook aqui.

Caso tenham interesse segue fork corrigido:

https://github.com/CristianOliveiraDaRosa/facebook-android-sdk.

Grande abraço.

Cristian Oliveira

Google Translate Grátis com Java

Bom dia Pessoal.

Algum tempo atrás no projeto Ivokee, aplicativo para android, precisei realizar translates para testes e para criar um protótipo. Porem o google não disponibiliza a API do Translate sem custo.
Se não me engano, não era nada muito caro, mas como estavamos fazendo um protótipo preferi procurar uma solução Free.

Procurando em foruns e grupos descobri uma url onde era possível baixar traduções do translate.google.com então criei uma classe para acessar esta url e realizar o download desta tradução em real time, com uma performance muito boa.

Para conseguir os códigos faça:

  git clone git@github.com:CristianOliveiraDaRosa/jafregle.git

Ou baixe diretamente em:

jafregle

 

Abraços
Cristian Oliveira

Orientação a Objeto com Python – Parte 1

Bom dia, Pessoal. Eu sempre desenvolvi em .Net e Java e nestas linguagens meio que obtive um certo “modelo” de como são tratadas os aspectos de orientação a objeto, pois nas duas o tratamento é bem parecido (não é igual) e o conceito de OO para ambas são bem reforçados. O Python, por outro lado, tem uma forma bem peculiar de tratar estes aspectos, o que pode causar um pouco de estranheza em quem está vindo do java ou .net por exemplo. Vamos as diferenças: No Java

package testes;

public class Veiculo {
	
	private String marca;
	private String cor;
	
	public Veiculo(String pMarca)
	{
		   this.setMarca(pMarca);
	}

	public String getMarca() 
	{
		return marca;
	}

	public void setMarca(String pMarca) 
	{
		this.marca = pMarca;
	}
	
	public void mudaCor(String pNovaCor)
	{
		this.cor = pNovaCor;
	}
}

Esta mesma classe em Python:

class Veiculo(object):
  
   def __init__(self, pMarca):
       self.marca = pMarca
       self.cor   = ""

   def muda_cor(self, pNovaCor):
       self.cor = pNovaCor

Vamos a algumas explicações e experiências que tive falando e trabalhando com outros programadores. Python não é Java logo não é necessário (Salvo poucas exceções) definir setter e getter, mas é possível faze-lo. Os atributos do objeto podem ser acessado diretamente, isto poupa tempo e processamento.

Porque foi definido “Veiculo(object)”?

Esta é a forma de dizer que a classe Veiculo descende da classe Objeto. Vamos supor que possua a classe Carro e fosse filho da classe Veiculo, logo sua declaração seria “Carro(Veiculo)”. Tudo em Python é um objeto e descende da class object.

O que é o “__init__(self, pMarca)”?

Esta é a forma de declaração do método de instância. Neste caso, esta forçando a dizer qual é a marca do veiculo no momento de instanciar o novo objeto.

O que é este “self” nos métodos?

É a forma que se está dizendo como você irá realizar o processo no objeto, por exemplo mudar a cor do Veiculo. Significa o veiculo está mudando a própria cor. Pode ser utilizado desta forma também:

uno = Veiculo("Fiat") #Jaba to ganhando uma grana nesta propaganda! Valeu Fiat!
uno.muda_cor("azul");

print "MARCA: %s COR: %s" % (uno.marca, uno.cor)

#ou assim

uno = Veiculo("Fiat")
Veiculo.muda_cor(uno, "azul")

print "MARCA: %s COR: %s" % (uno.marca, uno.cor)

Acesso as variaveis de instancia e de classe.

Execute o código abaixo que você vai entender:

class Veiculo(object):
  
   # este atributo sera visivel e compartilhado entre todas as instancias inclusive quando alterado.
   cor_classe   = "preto" # Ford style: "qualquer cor desde que seja preto" 
 
   def __init__(self, pMarca):
       self.marca           = pMarca
       # Este atributo somente sera visivel para a instancia.
       self.cor_instancia   = self.cor_classe

   def muda_cor(self, pNovaCor):
       self.cor_instancia = pNovaCor

   def show(self):
       print "MARCA: %s COR DEFAULT: %s COR CUSTOMIZADA: %s" % (self.marca, self.cor_classe, self.cor_instancia)

def main():
    uno = Veiculo("Fiat")
    uno.show() # MARCA: Fiat COR DEFAULT: preto COR CUSTOMIZADA: preto
   
    uno.muda_cor("amarelo")
    uno.show() # MARCA: Fiat COR DEFAULT: preto COR CUSTOMIZADA: amarelo

    # Alterei a propriedade para todas as instancias.
    Veiculo.cor_classe = "Laranja"

    palio = Veiculo("Fiat")
    
    print "Palio"
    palio.show() # MARCA: Fiat COR DEFAULT: Laranja COR CUSTOMIZADA: Laranja

    print "Uno"
    uno.show()  # MARCA: Fiat COR DEFAULT: Laranja COR CUSTOMIZADA: amarelo
   
#executa o codigo
main()

Todos estes arquivos para testes podem ser encontrados em meu GitHub no repositório my_lab. http://github.com/CristianOliveiraDaRosa/my_lab

Ambiente de Desenvolvimento com Sublime-Text e Anaconda

Boa noite Pessoal

Para facilitar no desenvolvimento vou utilizar uma ide que gosto já utilizava para PHP agora com Python estou gostando mais ainda da versatilidade desta IDE.

Para instalar:

sudo apt-get install sublime-text

Anaconda é o plugin para sublime que habilita o Intellisense para Django. Para “intala-lo” baixe o projeto do github:

git clone https://github.com/DamnWidget/anaconda.git Anaconda

Acesse e copie a pasta “Anaconda” para “/home/cristianoliveira/.config/sublime-text-3″

cp -avr Anaconda /home/cristianoliveira/.config/sublime-text-3/

É isto ai!
Ambiente pronto para por a mão na massa!

Preparando ambiente Django + Postgresql no Ubuntu Trusty (LTS)

Boa noite pessoal.

Como estou de computador novo e tive que reinstalar todas as minhas ferramentas neste PC, pensei em compartilhar um pouco da facilidade que é trabalhar com o Linux e, desmistificar um pouco este sistema tão bom. E como terei que faze-lo novamente no servidor da AWS, servirá de guia para mim mais tarde hehe.

Venho do Ubuntu 12.04, versão anterior LTS(Long Time Support). Agora é o Ubuntu 14.04 Trusty. Logo de cara não gostei muito pois ao instalar Chrome ele reclamava da “libappindicator1″.

Para resolver isto é só utilizar este comando:

sudo apt-get install libappindicator1 libindicator7

Bom vamos lá

Ferramentas que serão instaladas:

  • Python
  • Django
  • Postgresql

Python e Django

O Ubuntu Trusty já possui tanto o Python 2.7.6 como o 3.4 , bem como o Django 1.6.

Para verificar use:

cristianoliveira@system:~$ python --version
Python 2.7.6

cristianoliveira@system:~$ python3 --version
Python 3.4.0

Postgresql

Este é um banco de dados relacional muito utilizado em aplicações Web. Irei utilizar este banco por pura preferência.

Para instala-lo:

apt-get update
sudo apt-get install postgresql postgresql-contrib

Após para acessar o usuário postgres:

sudo su - postgres

Uma vez utilizando o usuário postgres, é possível criar o banco de dados:

  createdb meubanco

Acessando o banco de dados

  psql meubanco

Agora você está acessando o banco com a role “postgres” pode executar DDL e DML normalmente.

Para quem gosta de um ambiente mais visual:

sudo apt-get install pgAdmin3

Mais detalhes

https://www.digitalocean.com/community/tutorials/how-to-install-and-use-postgresql-on-ubuntu-12-04

Abraço!