Testando o Twitter com o Watir

No último post, vimos como instalar o Watir e escrever um teste usando ele.

Neste iremos nos aprofundar mais no Watir e para isso nada melhor do que testar.

Após a leitura do post, você estará sabendo:

  • Como modelar os seus testes utilizando orientação a objetos;
  • A importância de utilizar orientação a objetos nos seus testes;
  • Novos métodos da API do Watir;
  • Como fazer asserções de eventos assíncronos (AJAX).

Contexto

A equipe do Twitter ficou sabendo que existe uma comunidade brasileira que manja muito de Teste de Software.  Então, decidiram terceirizar para nós, a automação de alguns testes do Twitter.

Embora a parte da equipe do Twitter ter feito essa solicitação não seja verdade (hehe), somos pró-ativos, não somos?

Nossa missão é testar a funcionalidade de enviar uma mensagem no Twitter, o bom e velho “tweetar”. Os cenários de teste que temos são os seguintes:

  • Enviar uma mensagem válida;
  • Enviar uma mensagem repetida;
  • Enviar uma mensagem com mais de 140 caracteres;
  • Enviar uma mensagem em branco.

Típicos testes de sistema, então vamos colocar a mão na massa!

Como iremos modelar os testes?

Lembra do nosso primeiro teste usando o Watir? Ele é simplesmente um script de teste. Podemos muito bem fazer todos os nossos testes daquela maneira. Porém, vamos usar um pouco a nossa imaginação, para entender como o nosso mundo pode estar, se seguimos essa abordagem.

Temos mais de 100 testes, todos espalhados em scripts de teste, alguns contém só algumas linhas, outros são quase uma dissertação. Todos eles são gerenciados por um script mestre, que chama os scripts de teste e vai armazenando os resultados, para depois “printar” na tela.

Eu chamo o cenário acima de CAOS.

Automatizar os testes dessa maneira, é criar uma bola de neve que só irá aumentar, aumentar e um dia ninguém mais irá consegui movimentar ela. E aí vão culpar a ferramenta que é um lixo, ou a aplicação sob teste, quando na verdade o culpado é a própria equipe, que deu maior importância na criação dos testes, mas que acabou se esquecendo de organizar/estruturar a criação deles.

Além disso, o cenário acima mostra claramente uma reivenção da roda sem nenhuma necessidade: o gerenciamento dos testes. Hoje há muitas ferramentas que podem fazer isso para nós, no ecossistema Ruby, temos o TestUnit e o Rspec, por exemplo.

Uma abordagem mais efetiva, é utilizar orientação a objetos ao modelar os testes. Desta maneira será muito mais fácil dá manutenção no código e reutilizar-lo.

Como iremos aplicar OO nos nossos testes?

Como você sabe (se não sabe, deveria saber – leia esse livro e/ou essa apostila para aprender), a orientação a objetos é uma forma de organizar o nosso código, que nos orienta a trabalhar com objetos (não dá para ficar explicando conceitos de OO neste post, pois ele iria ficar enorme e minha explicação não seria melhor que a do Matt ou do pessoal da Caelum).

No nosso caso, uma página seria um objeto. Faz sentido não faz? Afinal, uma página contém atributos (os elementos HTML) e ações (as funcionalidades que ela provê).

Todos os nossos testes sehrão feitos numa mesma página, a página home do Twitter , portanto iremos instanciar o objeto HomePage da classe HomePage.

A primeira versão da nossa classe HomePage contém os seguintes métodos:

  • visit – acessa a home page do Twitter (twitter.com);
  • login – fará login no Twitter;
  • type_message – digita uma mensagem;
  • tweet – clica no botão para enviar uma mensagem;
  • message_exists? – verifica se uma mensagem existe na timeline;
  • alert_message_exists? – verifica se uma mensagem existe na página;
  • tweet_button_is_disable? – verifica se o botão para enviar a mensagem está desabilitado.

Falta alguma coisa, não falta não?

Os atributos da nossa classe.

Isso mesmo, mas vamos deixar eles de lado no momento, para não complicar demais o entendimento do nosso exemplo, afinal estamos começando, então vamos com calma e deixar eles para uma refatoração em um futuro post.

Você irá notar que, ao invés, de interagir com os atributos da classe HomePage, os nossos métodos estão usando o objeto browser para lidar com os elementos da página. Ou seja, abstrair os atributos da home page do Twitter, é luxo para a nossa primeira versão.

Testando o Twitter

Vamos parar com o blá-blá e ir para o código. Primeiro a classe que iremos utilizar nos nossos testes:

require 'rubygems'
require 'watir'
#require 'firewatir' => se você estiver no Linux/Mac

class HomePage

  HOME_PAGE = 'twitter.com'

  def initialize
    @browser = Watir::Browser.new
  end

  def visit
    @browser.goto(HOME_PAGE)
  end

  def login(username, password)
    @browser.text_field(:name, 'session[username_or_email]').value = username
    @browser.text_field(:name, 'session[password]').value = password
    @browser.button(:class, 'submit button').click
  end

  def type_message(message)
    @browser.text_field(:class, 'twitter-anywhere-tweet-box-editor').value = message
    @browser.text_field(:class, 'twitter-anywhere-tweet-box-editor').fire_event("onMouseDown")
  end

  def tweet
    @browser.link(:class, "tweet-button button").click
  end

  def message_exists?(message)
    @browser.wait_until {@browser.div(:class, 'tweet-text').text == message}
  end

  def alert_message_exists?(message)
    @browser.wait_until {@browser.text.include? message}
  end

  def tweet_button_is_disabled?
    @browser.link(:class, "tweet-button button disabled").exists?
  end

end

Aí está a nossa classe bonitona. Nela conseguimos abstrai várias ações que podemos fazer na página home do Twitter, desde preenchimentos até verificações de elementos.

Antes de irmos para os nossos testes propriamente ditos, vamos dá uma olhada nos métodos da API do Watir que estamos usando pela primeira vez:

  • @browser.text_field(:class,  ‘twitter-anywhere-tweet-box-editor’).value – no nosso primeiro teste usamos o set para preencher o text_field, agora estamos usando o value, simplesmente porque o set tem um bug no Firewatir (se você está testando usando o IE, e assim usando o Watir e não o Firewatir, não terá esse problema), e uma das formas de contornar ele, é usar o value;
  • @browser.text_field(:class,  ‘twitter-anywhere-tweet-box-editor’).fire_event(“onMouseDown”) –  o fire_event possibilita disparar um evento num elemento. No caso nosso seria como se a pessoa estivesse com o mouse em cima do text_field para digitar a mensagem e clica nele. Precisamos fazer isso, pois só assim o botão (que na verdade é um link) para “tweetar” será habilitado, uma vez que ele depende do disparo desse evento Javascript;
  • @browser.wait_until – o Watir é bem espertinho quanto a espera para carregar a página, esperando realmente ela carregar, e assim não precisamos ficar doidos adicionando sleeps. Porém ele não é mágico e com o wait_until podemos esperar a nossa mensagem aparecer na timeline, tendo ele um timeout de 60 segundos, o que é muito bom, pois não queremos esperar infinitamente. Estamos usando ele, pois a nossa mensagem aparece na timeline de forma assíncrona (AJAX), ou seja, a página não é carregada novamente, e então não podemos utilizar um @browser.text.included?(‘nossa mensagem’);
  • @browser.link(:class, “tweet-button button disabled”).exists? – este método é auto-explicativo, ele verifica se o elemento existe ou não na página. Estamos usando ele, pois a forma de descobrir se o link para “tweetar” a mensagem está habilitado ou não, é através da classe css do link, que quando desabilitado também terá a classe disabled.

Feitas as devidas explicações, vamos vê como ficam os nossos testes utilizando a classe HomePage:

USERNAME = 'SEU USUÁRIO NO TWITTER'
PASSWORD = 'A SUA SENHA NO TWITTER'
MESSAGE = 'testando o Twitter'

MESSAGE_WITH_MORE_THAN_140_CARACTERS = 'testando o limite de caracteres na mensagem no  Twitter, chegou? ainda nao? nao? nao? ainda nao? quando vamos chegar? estamos perto? chegamos!'

TWITTER_REPEATED_MESSAGE = 'Whoops! You already said that...'

#Teste 1 - Enviar uma mensagem válida

home_page = HomePage.new
home_page.visit
home_page.login(USERNAME,PASSWORD)
home_page.type_message(MESSAGE)
home_page.tweet

message = 'O teste enviar uma mensagem válida'
if home_page.message_exists? MESSAGE
 puts "#{message} PASSOU"
else
 puts "#{message} FALHOU"
end

#Teste 2 - Enviar uma mensagem repetida

home_page.type_message(MESSAGE)
home_page.tweet

message = 'O teste enviar uma mensagem repetida'
if home_page.alert_message_exists? TWITTER_REPEATED_MESSAGE
 puts "#{message} PASSOU"
else
 puts "#{message} FALHOU"
end

#Teste 3 - Enviar uma mensagem com mais de 140 caracteres

home_page.type_message(MESSAGE_WITH_MORE_THAN_140_CARACTERS)

message = 'O teste enviar uma mensagem com mais de 140 caracteres'
if home_page.tweet_button_is_disabled?
 puts "#{message} PASSOU"
else
 puts "#{message} FALHOU"
end

#Teste 4 - Enviar uma mensagem em branco

home_page.type_message('')

message = 'O teste enviar uma mensagem em branco'
if home_page.tweet_button_is_disabled?
 puts "#{message} PASSOU"
else
 puts "#{message} FALHOU"
end

Com certeza os nossos testes ficaram bem melhor utilizando a classe HomePage, em comparação se a gente fosse fazer sem ela. No entanto, eles estão BEM RUINS, em comparação com os testes do próximo post. 😀

A intenção dos posts não é dá “a melhor” solução de bandeja, afinal o melhor da jornada da automação dos testes (e de qualquer outra jornada), é justamente o caminho, se eu mostrasse logo no primeiro post a solução final, a gente não ia entender os motivos pelos quais ela é uma solução melhor que as anteriores. Talvez até seria possível entender, mas evoluindo aos poucos, irá ficar muito mais clara a diferença desses testes porcos, para os da solução final.

De qualquer modo, já atendemos a demanda que foi solicitada pelo pessoal do Twitter (hehe). O que iremos vê no próximo post, será como melhorar o código dos nossos testes, utilizando o Rspec. Até lá!

Observações

  • Disponibilizei no meu Gist, o código completo do post: http://bit.ly/ges0xH
  • O código foi testado no Windows com o IE8 e também no Ubuntu usando o Firefox 3.6 (lembrando que para testar usando o Firefox, você tem que usar o firewatir e não o watir).

Saiba mais

Para saber mais sobre o Watir, acesse o meu delicious, lá estou guardando vários links a respeito do Watir, e não deixe de visitar a página oficial do projeto, lá tem vários bons exemplos e explicações.

Fique por dentro das novidades, assine o feed do QualidadeBR.

Bug na criação de listas no Twitter

Estava criando uma lista no Twitter do QualidadeBR (comecei a twittar hoje com ele, num outro post falo sobre o objetivo dele) e me deparei com um erro de usabilidade do Twitter.

Segue abaixo os detalhes do bug:

Título: Não aparece uma mensagem de erro, quando o nome da lista excede o limite de caracteres

Descrição: Não aparece uma mensagem de erro, quando eu tento criar uma lista com um nome longo, mais de 25 caracteres para ser preciso, e a lista não é salva.

Como reproduzir:

  1. Vá na sua página de listas;
  2. Crie ou altere uma lista;
  3. Preencha “List name” com um nome com mais de 25 caracteres (ex: “lista com mais de 25 carac”)

Um bug clássico de usabilidade, que vai contra a primeira heurística do Nielsen “Visibilidade e Estado do Sistema“. Além disso, uma melhoria poderia ser adicionada, seguindo a terceira heurística do Nielsen “Prevenção de Erros“, simplesmente adicionando um texto ao lado do campo, avisando o limite de caracteres, ou de uma forma mais elegante, adicionando uma validação via AJAX (usando o live validation por exemplo).

Em relação ao reporte do bug, ele é bem simples, já que o bug é simples. O maior trabalho é descobrir o limite de caracteres que são aceitos no campo, o que acaba sendo feito na tentativa e erro mesmo.

Abri um ticket no Twitter reportando o bug, porém recebi um e-mail avisando que eles estão de recesso (pena que os bugs não entram de recesso rs), e o ticket acabou sendo fechado (estranho que como resolvido).

Fique por dentro das novidades, assine o feed do QualidadeBR.

O Twitter como meio de comunicação interna

Acredito que a maioria de vocês devem saber da existência, de um tal de Twitter, mas ainda não descobriram uma real utilidade para ele.

De tanto ouvir falar desse Twitter, resolvi ver o que o pessoal tanto faz com nele. E acabei descobrindo que a maioria dos twitteiros (usuários do Twitter) utiliza-o para fazer um auto Big Brother (coisa de doido, neh não!?), principalmente sendo um auto Big Brother da vida pessoal (privacidade é luxo).

Porém, de repente, pensei numa possível utilidade para o Twitter: usar ele para comunicação interna. Afinal, a comunicação interna é de extrema importância em qualquer empresa, e se houver uma nova maneira de torná-la mais dinâmica e acessível, melhor será.

Mas aí surgiu um problema, esse canal de comunicação deve ser privado, e o Twitter é público.

E pesquisando para ver se há alguma maneira de tornar o Twitter privado, descobrir que ele tem uma opção para proteger os meus tweets (nome dado a cada mensagem postada no Twitter). Pronto problema solucionado!

Até começamos a brincar um pouco com ele na empresa. E as primeiras impressões foram boas.

Depois pesquisando um pouco mais sobre o Twitter, encontrei um “irmão” dele, o Yammer, um Twitter para empresas.

Sensacional! O Yammer atingi melhor o objetivo de servir como um meio de comunicação interna, e é mais seguro do que o Twitter.

Ainda não estamos utilizando para valer o Yammer aqui na empresa. Mas acredito que ele possa ajudar na nossa comunicação interna.

Ahh…também acabei entrando nessa onda de Twitter, nele estou falando de tudo um pouco (menos fazendo um auto Big Brother), se alguém quiser conferir, ou melhor me seguir, abaixo se encontra o endereço do meu Twitter pessoal: 🙂

http://twitter.com/FabricioFFC

Dica

Para acompanhar as pessoas e twittar (verbo, ação ou efeito de postar alguma coisa no Twitter), há uma excelente extensão para o Firefox, o TwitterFox, que pode ser obtido no link abaixo:

https://addons.mozilla.org/pt-BR/firefox/addon/5081

Saiba mais

Sobre o Yammer

http://www.yammer.com/

http://www.twitterbrasil.org/2008/10/30/um-twitter-para-empresas/

Sobre o Twitter

http://www.twitterbrasil.org

Fique por dentro das novidades, assine o feed do QualidadeBR.

Assine o feed