Brincando com PhantomJS e CasperJS

Esses dias usei o PhantomJS para converter uma imagem em SVG para PNG, e gostei bastante, tanto que dei uma olhada mais a fundo em como ele pode ser usado. E umas das formas é para testar aplicações.

Com o Phantom você pode testar de forma headless, ou seja, sem usar a interface gráfica, o que resulta numa diminuição do tempo dos testes.

Mas ele por si só não é um framework de teste, portanto quando usado pra testar você geralmente vai querer usar algum framework de teste como o Jasmine.

Pra minha brincadeira eu acabei usando apenas o CasperJS, que abstrai o PhantomJS visando a execução de testes. Assim sendo ele nos dá funções de navegação, preenchimento de campos, screenshot, etc.

Casper

Após instalar o PhantomJS e o CasperJS (versão 1.1 beta 1). Dei uma olhada nos samples do Casper, e usei o “googletesting.coffee”, para entender como ele funciona, e fiz uma pequena mudança, para capturar um screenshot no último teste, como pode ser visto no código abaixo:

Como vocês podem ver, a declaração do teste é bem similar a qualquer xUnit da vida.

Portanto, se você tiver procurando formas de testar usando Javascript/CoffeeScript, o PhantomJS pode te ajudar com certeza, e o CasperJS pode ser uma opção dentre as várias existentes.

Se quiser saber mais, sobre o PhantomJS o projeto é bem documentado, portanto dê uma olhada na doc e pra saber do CasperJS, veja a documentação e principalmente os samples.

Escrevendo testes melhores com o Watir

Vimos no último post sobre o Watir, como melhorar os nossos testes usando o Rspec.

Já nesse post, iremos vê como melhorar os testes que escrevemos, utilizando um helper criado pelo Jeff Morgan.

Mas antes disso, deixa eu contar uma breve história sobre os nossos testes.

O Twitter mudou e quebrou os nossos testes

Como vocês devem ter notado, o Twitter recentemente (coisa de 1/2 meses), mudou a página de login. E a alteração também afetou os ids de alguns elementos da página, como por exemplo, o do text field do login e senha.

Os posts já foram atualizados, mas o que ocorreu é interessante pra ilustrar a fragilidade dos testes que dependem da interface.

Pode parecer estranho, mas tanto testar como desenvolver front-end são tarefas complicadas, principalmente Web (só lembrar das várias tecnologias usadas numa interface Web e os vários navegadores existentes). A sensação e de que quando falamos de sistemas front-end, pisamos num chão mais gelatinoso, e qualquer mudança faz ele tremer.

Para evitar o que ocorreu, o ideal é a equipe de desenvolvimento NÃO MUDAR o id dos elementos,  afinal de contas, para o usuário tanto faz se o text field tem o id username ou login, mas para os Testadores isso importa, e muito. Aliás, para ajudar na nomeação desses ids, estabelecer um padrão pra equipe ou boas práticas pode ajudar.

Bem era isso, agora vamos falar do helper que irá melhorar os nossos testes.

Melhorando os testes

Esse helper é uma mão na roda pra quem utiliza o Watir, com ele vamos passar a escrever menos código e será mais fácil de manter os nossos testes.

O helper mágico que estou falando é o seguinte:

module WatirHelper
  # A helper class to make accessing web elements via Watir easier.
  # All methods take an identifier parameter.  This parameter is
  # an array of hashes that are used to identify an element on the
  # page.  On elements that support multiple attributes you can
  # provide multiple identifiers.
  #
  # This module assumes there is a @browser variable available.

  def self.included(cls)
    cls.extend ClassMethods
  end

  module ClassMethods
    # adds three methods - one to put data in a text field, another
    # to fetch that data, and another to return the actual text_field.
    #
    # Example:  text_field(:first_name, {:id => "first_name})
    # will generate the 'first_name', 'first_name=', and
    # 'first_text_field' methods
    def text_field(name, identifier)
      define_method(name) do
        @browser.text_field(identifier).value
      end
      define_method("#{name}=") do |_value|
        @browser.text_field(identifier).value = _value
      end
      define_method("#{name}_text_field") do
        @browser.text_field(identifier)
      end
    end

    # adds three methods - one to put data in a hidden field, another
    # to fetch that data, and a third to return the hidden field.
    #
    # Example:  hidden(:first_name, {:id => "first_name})
    # will generate the 'first_name', 'first_name=' and
    # 'first_hidden' methods
    def hidden(name, identifier)
      define_method(name) do
        @browser.hidden(identifier).value
      end
      define_method("#{name}=") do |value|
        @browser.hidden(identifier).set(value)
      end
      define_method("#{name}_hidden") do
        @browser.hidden(identifier)
      end
    end

    # adds three methods - one to select an item in a drop-down,
    # another to fetch the currently selected item, and another
    # to return the select_list.
    #
    # Example:  select_list(:state, {:id => "state"})
    # will generate the 'state', 'state=' and 'state_select_list'
    # methods
    def select_list(name, identifier)
      define_method(name) do
        @browser.select_list(identifier).value
      end
      define_method("#{name}=") do |value|
        @browser.select_list(identifier).set(value)
      end
      define_method("#{name}_select_list") do
        @browser.select_list(identifier)
      end
    end

    # adds three methods - one to check, one to uncheck and
    # a third to return a checkbox
    #
    # Example: checkbox(:active, {:name => "is_active"})
    # will generate the 'check_active', 'uncheck_active', and
    # 'active_checkbox' methods
    def checkbox(name, identifier)
      define_method("check_#{name}") do
        @browser.checkbox(identifier).set
      end
      define_method("uncheck_#{name}") do
        @browser.checkbox(identifier).clear
      end
      define_method("#{name}_checkbox") do
        @browser.checkbox(identifier)
      end
    end

    # adds three methods - one to select, another to clear and
    # another to return a radio button
    #
    # Example:  radio_button(:north, {:id => "north"})
    # will generate 'select_north', 'clear_north', and
    # 'north_radio_button' methods
    def radio_button(name, identifier)
      define_method("select_#{name}") do
        @browser.radio(identifier).set
      end
      define_method("clear_#{name}") do
        @browser.radio(identifier).clear
      end
      define_method("#{name}_radio_button")  do
        @browser.radio(identifier)
      end
    end

    # adds three methods - one click a button, another
    # to click a button without waiting for the action to
    # complete, and a third to return the button.
    #
    # Example:  button(:save, {:value => "save"})
    # will generate the 'save', 'save_no_wait', and
    # 'save_button' methods
    def button(name, identifier)
      define_method(name) do
        @browser.button(identifier).click
      end
      define_method("#{name}_no_wait") do
        @browser.button(identifier).click_no_wait
      end
      define_method("#{name}_button") do
        @browser.button(identifier)
      end
    end

    # adds three methods - one to select a link, another
    # to select a link and not wait for the corresponding
    # action to complete, and a third to return the link.
    #
    # Example:  link(:add_to_cart, {:text => "Add to Cart"})
    # will generate the 'add_to_cart', 'add_to_cart_no_wait',
    # and 'add_to_cart_link' methods
    def link(name, identifier)
      define_method(name) do
        @browser.link(identifier).click
      end
      define_method("#{name}_no_wait") do
        @browser.link(identifier).click_no_wait
      end
      define_method("#{name}_link") do
        @browser.link(identifier)
      end
    end

    # adds a method that returns a table element
    #
    # Example:  table(:shopping_cart, {:index => 1})
    # will generate a 'shopping_cart' method
    def table(name, identifier)
      define_method(name) do
        @browser.table(identifier)
      end
    end

    # adds two methods - one to return the text within
    # a row and one to return a table row element
    #
    # Example: row(:header, {:id => :header}) will
    # generate a 'header' and 'header_row' method
    def row(name, identifier)
      define_method(name) do
        @browser.row(identifier).text
      end
      define_method("#{name}_row") do
        @browser.row(identifier)
      end
    end

    # adds a method to return the text of a table data <td> element
    # and another one to return the cell object
    #
    # Example:  cell(:total, {:id => "total"})
    # will generate a 'total' method and a 'total_cell'
    # method
    def cell(name, identifier)
      define_method(name) do
        @browser.cell(identifier).text
      end
      define_method("#{name}_cell") do
        @browser.cell(identifier)
      end
    end

    # adds a method that returns the content of a <div>
    # and another method that returns the div element
    #
    # Example: div(:header, {:id => "banner"})
    # will generate a 'header' and 'header_div' methods
    def div(name, identifier)
      define_method(name) do
        @browser.div(identifier).text
      end
      define_method("#{name}_div") do
        @browser.div(identifier)
      end
    end

    # adds a method that returns the content of a <dd>
    # and another method that returns the dd element
    def dd(name, identifier)
      define_method(name) do
        @browser.dd(identifier).text
      end
      define_method("#{name}_dd") do
        @browser.dd(identifier)
      end
    end

    # adds a method that returns the content of a <dl>
    # and another that returns the dl element
    def dl(name, identifier)
      define_method(name) do
        @browser.dl(identifier).text
      end
      define_method("#{name}_dl") do
        @browser.dl(identifier)
      end
    end

    # adds a method that returns the content of a <dt>
    # and another that returns the dt element
    def dt(name, identifier)
      define_method(name) do
        @browser.dt(identifier).text
      end
      define_method("#{name}_dt") do
        @browser.dt(identifier)
      end
    end

    # adds a method that returns the content of a
    # <form> element and another that returns the
    # form element
    def form(name, identifier)
      define_method(name) do
        @browser.form(identifier).text
      end
      define_method("#{name}_form") do
        @browser.form(identifier)
      end
    end

    # adds a method that returns a the content of a
    # <frame> element and another that returns the
    # frame element
    def frame(name, identifier)
      define_method(name) do
        @browser.frame(identifier).text
      end
      define_method("#{name}_frame")  do
        @browser.frame(identifier)
      end
    end

    # adds a method that returns an image <image> element
    def image(name, identifier)
      define_method(name) do
        @browser.image(identifier)
      end
    end
  end

  def content
    @browser.text
  end

  def visit_page(page_url)
    @browser.goto(page_url)
  end

  def page_title
    @browser.title
  end

  def wait_for_page
    @browser.wait
  end
end

Os comentários feitos pelo Jeff já explicam muito bem o que esse helper faz. Mas mesmo assim deixa eu dá uma explicação rápida, sobre a magia por de trás dele: Basicamente ele facilita a definição dos elementos da página. Provendo tanto o setter quanto getter dos elementos que iremos interagir durante o teste, além de prover o objeto do próprio elemento.

Pra utilizar esse helper, basta fazer o include, o que irá fazer com que a classe HomePage “ganhe” todos os métodos dele, como por exemplo o método page_title, que irá retornar o título da página que está aberta.

Abaixo está como ficou o código dos nossos testes com a utilização desse helper.

require 'rubygems'
#require 'watir'
require 'firewatir'
require 'lib/watir_helper.rb'

module Twitter

  class HomePage
    include WatirHelper

    HOME_PAGE = 'twitter.com'

    link(:tweet_button, :class => 'tweet-button button')
    link(:tweet_button_disable, :class => 'tweet-button button disabled')
    text_field(:username, :name => 'session[username_or_email]')
    text_field(:password, :name => 'session[password]')
    text_field(:editor, :class => 'twitter-anywhere-tweet-box-editor')
    button(:sign_in_submit, :class => 'submit button')
    div(:message, :class => 'tweet-text')

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

    def visit
      @browser.goto(HOME_PAGE)
    end

    def login(username, password)
      self.username = username
      self.password = password
      self.sign_in_submit
    end

    def type_message(message)
      self.editor = message
      self.editor_text_field.fire_event('onMouseDown')
    end

    def tweet
      self.tweet_button
    end

    def message_exists?(message)
      @browser.wait_until {self.message_div.text == message}
    end

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

    def tweet_button_is_disabled?
      @browser.link(self.tweet_button_disable_link.exists?)
    end

  end
end

O que ganhamos utilizando esse helper, você pode estar se perguntando. Basicamente duas vantagens.

Definição mais simples dos elementos web

Ganhamos três métodos  pra cada elemento:

  • um pra setar o valor do elemento (setter): self.username =
  • outro pra retornar o valor do elemento (getter): self.username
  • e por fim um que retorna o próprio objeto do elemento: username_text_field (podemos utilizar qualquer método do objeto TextField)
  • o NOME_DO_SEU_ELEMENTO_text_field é para o caso do elemento ser da classe TextField. Se for um div, seria _div, se fosse um button seria _button e assim vai.

Manutenção mais controlada

Como você viu no começo do post, não é difícil a gente precisar dá manutenção nos nossos testes, e definindo desta forma os elementos que utilizamos, precisamos alterar apenas em um lugar eles.

Por exemplo, se a classe do div com o tweet mudou de tweet-text para apenas tweet, basta mudar a definição desse div, ficando assim: div(:message, :class => ‘tweet’)

Ambas vantagens são mais evidentes ainda, quando temos suítes maiores de testes.

Qualquer dúvida a respeito do uso do helper ou do próprio Watir, abuse e use dos comentários. Lembrando que o helper, foi disponibilizado pelo Jeff Morgan no seu GitHub.

O projeto completo deste post, está disponível no meu GitHub. Aliás, você pode vê a evolução do projeto navegando pelas tags do projeto.

Abraços!

Melhorando os testes com o Rspec

No post anterior, utilizamos o excelente Watir (estou gostando mesmo dele), para testar um pouco o Twitter.

Neste iremos melhorar o código dos testes, como foi prometido.

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

  • O que é o Rspec;
  • Como escrever os seus testes com o Rspec;
  • Porquê utilizar o Rspec é uma boa ideia.

O que é o Rspec?

O Rspec é um framework de testes de unidade, assim como o JUnit. Porém ele vai além de apenas fornece um conjunto de métodos para os seus testes, e nos fornece uma DSL para descrever os compartamentos esperados do sistema[1], ou seja, ao invés, de ter apenas “um monte” de asserts, temos “um monte” de asserts dentro de exemplos executáveis, a diferença é sútil, mas faz um boa diferença.

Watir + Rspec = HAVEFUN

Os testes do último exemplo possuem um código bem ruim. Os problemas maiores dele são:

  • Repetição de código;
  • Testes fortemente acoplados;
  • Mal organizado.

Utilizando o Rspec podemos combater esses problemas. E lembre-se, não é porquê o código é para realizar testes, que ele pode ser feito de qualquer jeito, muito pelo contrário, devemos sim seguir boas práticas, como por exemplo os princípios SOLID.

Vamos agora direto vê como ficam os testes usando o Rspec:

require 'spec_helper'

USERNAME = 'YOUR USERNAME'
PASSWORD = 'YOUR PASSWORD'
MESSAGE = 'Watir rocks!'
MESSAGE_WITH_MORE_THAN_140_CHARACTERS =  "testing characters limit. 140 characters is the  characters limit. Are you pass? not yet? not? not? when are we pass? now? We break the limit!"
TWITTER_REPEATED_MESSAGE = 'Whoops! You already said that...'

describe Twitter::HomePage do

  before(:all) do
    @home_page = Twitter::HomePage.new
    @home_page.visit
    @home_page.login(USERNAME,PASSWORD)
  end

  it "send a message when it is valid" do
    @home_page.type_message(MESSAGE)
    @home_page.tweet
    @home_page.message_exists?(MESSAGE).should be_true
  end

  it "return a error messagem when try to send a repeated message" do
    @home_page.type_message(MESSAGE)
    @home_page.tweet
    @home_page.alert_message_exists?(TWITTER_REPEATED_MESSAGE).should be_true
  end

  it "don't allow to send a message when it contains more than 140 characters" do
    @home_page.type_message(MESSAGE_WITH_MORE_THAN_140_CHARACTERS)
    @home_page.tweet_button_is_disabled?.should be_true
  end

  it "don't allow to send a message when it is blank" do
    @home_page.type_message('')
    @home_page.tweet_button_is_disabled?.should be_true
  end

end

O que achou? Bem melhor que aquela “massaroca“, não é mesmo?

E viu só como o código ficou até mais simples. Prova que fazer da forma correta, é diferente de fazer da forma complicada.

O que mudou?

Antes tínhamos um código com muito repetição, é só olhar os vários ifs e elses para perceber que algo não estava certo. Agora usando o Rspec, temos os próprios métodos dele ao nosso dispor. E como você pode vê, o nosso código é praticamente um texto corrido.

Caso essa seja a primeira vez que você vê um código usando o Rspec, segue uma explicação abaixo sobre ele:

  • Primeiro estamos fazendo require de um helper, que apenas faz require da nossa classe HomePage (mais por organização);
  • No describe estamos passando a classe que iremos testar (Twitter é o módulo e HomePage é a classe) e um bloco (tudo dentro do do até o end lá do final é bloco que estamos passando);
  • O before contém passos que serão executados antes do teste (pré-condições), no nosso caso estamos logando no Twitter, antes de todos os testes. Ou seja, ele é executado apenas uma vez, e não antes de cada teste;
  • Depois temos os nossos exemplos/testes, cada um com uma asserção no final.

O que não mudou

Os nossos testes continuam com um bom nível de acoplamento/dependência, e isso costuma não ser bom. É só observar o segundo teste, ele depende do primeiro para funcionar, caso o primeiro teste falhe, o segundo provavelmente vai falar também.

No entanto, eu acabei optando por manter desta maneira, não por preguiça, mas sim porquê vejo que se o primeiro teste falha, o segundo deve falhar mesmo.

É mais uma escolha por deixar mais simples, embora eu goste da ideia de deixar os testes “atômicos”.

Organização e execução dos testes

Como você deve lembrar, temos a nossa classe HomePage, que ainda vai continuar da forma que está.

Continuamos usando ela, só que agora não temos tudo num mesmo arquivo. Temos agora um projeto, que segue a seguinte estrutura:

  • -> lib
    • -> twitter
      • home_page.rb
  • -> spec
    • -> twitter
      • home_page_spec.rb
    • spec_helper.rb

Resumindo: na pasta lib temos a classe HomePage, que prover os métodos para facilitar a criação e reutilização dos testes, que estão na pasta spec. Ambas as pastas twitter, existem pois podemos criar testes para outro site, e separar ele em outra pasta.

Por exemplo, se a gente for testar o Google, podemos criar uma pasta google, dentro de lib e spec. E aí na primeira ficarão as classes para os nossos testes e na segunda os testes em si. Tá vendo só como fica bem organizado, mesmo quando começarmos a ter muitos arquivos e pastas.

Passada a explicação sobre a organização do nosso projeto, vamos vê o díficil comando para rodar os nossos testes. Basta digitar: rspec spec/twitter/home_page_spec.rb

Só isso mesmo. Os testes serão executados e você verá em seu terminal/prompt o resultado dos testes.

Melhor que isso, só isso:

rspec spec/twitter/home_page_spec.rb -f h > resultado.html

Agora temos o resultado dos testes numa bela página em HTML. :)

Por que usar o Rspec?

Após mostrar um exemplo sem o Rspec e outro com, deve ter ficado bem clara a diferença das duas abordagens.

Não apenas estamos evitando reiventar a roda, como estamos utilizando um roda muito bem testada e amplamente usada. O Rspec é hoje, a ferramenta número 1 para muitos desenvolvedores Ruby, e mesmo a gente não precisando de muitos recursos que o Rspec pode fornecer, como por exemplo mocks, ele atende muito bem a nossas necessidades, que são básicas. Além disso, deixa os testes muito mais claros, e assim fica mais fácil para você ou uma outra pessoa dá manutenção mais pra frente.

Lógico que ele não é a única boa opção, temos por exemplo, o TestUnit que é muito bom por sinal, e se a gente quiser deixar mais alto nível ainda os nossos testes, podemos usar o Cucumber.

A mensagem que quero passar, é que poderíamos muito bem ter continuado a escrever os nossos testes daquela forma antiga, porém há formas melhores de automatizar os nossos testes. E isso não é sobre fazer “bunitinho” pra publicar num post, e sim a respeito de fazer “bunitinho” para tornar o seu trabalho mais fácil a médio e longo prazo.

O projeto

O projeto do post está disponível no meu Github (a versão 1.1 é a desse post – o link já vai pra ela). Para você utilizar ele, basta fazer clone do projeto (git clone git@github.com:FabricioFFC/watir_tests.git – necessário ter o git instalado).

Com o projeto em mãos, instale o Bundler (gem install bundler) e depois rode o comando bundle install, para instalar o Watir e o Rspec. Não se esqueça, que caso você queira testar usando o Internet Explorer, será necessário alterar dois arquivos: Gemfilehome_page.rb. Em ambos, comente a linha require firewatir e descomente a linha require watir.

Se tiver alguma dúvida ou problema para rodar os testes, só avisar nos comentários. E sugestões, críticas e opiniões sobre o projeto são bem-vindas também.

Até a próxima.

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

OBS.: Ainda não testei no Windows, só no Ubuntu. Mas não deve ter diferenças. Se alguém encontrar algum problema, avise por favor.

[1] http://blog.davidchelimsky.net/2007/05/14/an-introduction-to-rspec-part-i/

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. :D

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.

Conheça o Watir

O objetivo deste post é fazer uma introdução a ferramenta Watir (mesma pronúncia de water). Como sendo uma introdução, irei abordar o básico do básico, até porque a minha experiência com o Watir são de menos de 1 hora.

Ao terminar a leitura deste post, você estará sabendo:

  • O que é o Watir
  • Porquê usar o Watir
  • Como instalar o Watir
  • Realizar um teste básico com o Watir

O que é o Watir?

Primeiro a resposta curta de quem não conhece muito: Um Selenium desenvolvido em Ruby, cujo seus testes também serão escritos em Ruby.

Agora uma resposta apoiada no conteúdo da página oficial do Watir: O Watir é uma ferramenta para você testar aplicações Web, sob a licença BSD. Ela é um conjunto de bibliotecas em Ruby que permite você automatizar os seus testes. Você escreve os seus testes em Ruby e pode rodá-los no IE, Firefox, Chrome, Safari e Opera.

Ou seja, a minha primeira resposta é válida, porém está longe de ser a mais completa. No entanto, de início vamos com ela, afinal só iremos ter uma melhor resposta usando o Watir. :)

Por que usar o Watir?

Os motivos para usar o Watir são [1]:

  • É uma ferramenta open source e não há custos para usar;
  • A comunidade do Watir está crescendo e é muita ativa;
  • Ele usa Ruby, uma linguagem de script moderna e completa e que possui uma baixa curva de aprendizado (em comparação com Java, por exemplo);
  • Ele suporta qualquer aplicação web, não importando a linguagem na qual ela foi desenvolvida;
  • O Watir suporta múltiplos browsers e diferentes plataformas;
  • Ele é poderoso, fácil de usar e ainda é bem leve.

Como instalar o Watir

Para instalar o Watir o único pré-requisito é ter instalado o Ruby (versão 1.8.6 ou 1.8.7). Portanto vamos instalar, lembrando que os próximos passos foram feitos no Windows (se você usa Linux, vá no tópico Instalando no Linux):

  1. Instale o Ruby 1.8.7-p334 (saiba mais em RubyInstaller);
  2. Ao iniciar a instalação, logo após aceitar os termos, marque os dois checkboxes (“Add Ruby executables to your PATH” e “Associate .rb and .rbw files with this Ruby installation”) e clique em Install;
  3. Ao terminar a instalação, vá no prompt de comando (ctrl+r e depois digite cmd) e digite os seguintes comandos:
    • ruby -v (deverá retornar a versão do Ruby que foi instalada, ex: ruby 1.8.7)
    • gem -v (deverá retornar a versão do RubyGems que foi instalada, ex: 1.5.2)
    • irb (deverá entrar no irb – o shell interativo do Ruby), dentro dele escreva:
      • puts “hello world”
    • depois digite exit para sair do irb.

Se tudo deu certo, parabéns o Ruby foi corretamente instalado e de quebra você escreveu um Hello World em Ruby. ;)

Agora vamos instalar o Watir:

  1. No prompt do Windows digite: gem install watir

Pronto só isso, se nenhum erro ocorreu, já temos o Watir instalado. Caso algum erro tenha ocorrido, consulte o último tópico Erros comuns.

Realizando um teste com o Watir

Segue abaixo, um screencast mostrando como realizar um teste simples com o Watir (assistir em 720p é recomendado). Estarei fazendo o teste usando o irb:

O teste executado foi baseado no exemplo do site oficial do Watir, para vê outros exemplos acesse essa página.

Você pode fazer o mesmo teste na sua máquina, de duas formas:

  • Pelo irb, como fiz no vídeo, informando cada “comando” no irb;
  • Ou de uma forma mais fácil, baixando esse arquivo, que contém todo o script de teste completo. Além dos código que foi informado no irb, tem também vários comandos e puts, para facilitar o entendimento do código. Lembrando que após baixar o arquivo, é só executar o watir_example.rb, que um prompt abrirá e nele serão “printados” os passos e também o resultado do teste.

Conclusão

Como pudemos ver no vídeo, o Watir interage diretamente com o browser. Nós só precisamos conhecer a API dele, para podermos criar os nossos próprios testes, e é claro também um pouco de Ruby irá ajudar.

Resumindo, o que precisamos saber para criar o nosso próprio teste usando o Watir é o seguinte:

  • O valor da propriedade name dos elementos que iremos ter que interagir para poder fazer os passos do nosso teste (o desenvolvedor pode passar essa informação para você, ou você pode encontrar usando o Firebug);
    • Numa rápida pesquisa, parece que existem IDEs de record-play (estilo o Selenium IDE) para o Watir, porém nenhuma é mantida oficialmente.
  • A API do Watir, basicamente conhecer quais são os métodos que podemos usar, quando usar e quais parâmetros passar;
  • A linguagem Ruby, mas calma não precisa aprender toda a linguagem de uma vez, vá com calma, comece primeiro com exemplos básicos (como esse que mostrei) e vá incrementando eles.

Bem é isso. Qualquer dúvida, crítica ou sugestão, sintam-se à vontade em deixar nos comentários.

Instalando no Linux

Para instalar o Ruby, Rubygems e Watir no Linux, preparei um script (testado no Ubuntu). Basta baixar ele, alterar a permisão (chmod +x watir_installation.sh) e rodar o script com sudo (sudo ./watir_installation.sh).

Uma coisa que muda no script do teste, é que ao invés, de fazer o require no watir, você irá fazer o require no firewatir (require firewatir), que é o driver para o Firefox. Além disso, você terá que instalar esse plugin no Firefox. Maiores detalhes, é só conferir o procedimento de instalação que está disponível no site do Watir (lá tem para quem usa Mac também).

Erros comuns

Erro: ERROR:  While executing gem … (Errno::ENXIO)

Solução:

  • Vá no diretório C:\Ruby187\bin (ou no local que você especificou para instalar o Ruby na sua instalação);
  • Faça uma cópia do arquivo gem (para fazer backup);
  • Edite esse mesmo arquivo (gem), alterando o seu conteúdo para o que está aqui.

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

Fonte:

[1] http://watir.com/

Automação de testes funcionais

A 30ª Mesa Redonda DFTestes, que ocorreu na primeira quinzena de agosto, foi sobre “Automação de testes funcionais”. A mesa redonda gerou bastante discussão, totalizando 29 respostas e tendo 10 participantes, sendo eles: eu, Juraci Vieira, Felipe Silva, Shmuel Gershon, Elias Nogueira, Rodrigo Almeida, Ueslei Aquino, Luiz Gustavo, Fermiano de Queiroz e Roberto Passani.

Segue abaixo, o resumo desta mesa redonda, quem quiser conferir a discussão na íntegra, só acessar esse link.

Vocês acham a automação dos testes funcionais necessária? Se sim, você sempre tenta automatizar os testes funcionais, como?

Segundo o Juraci Vieira:

Certamente é necessária uma vez que os ciclos do desenvolvimento de software estão cada vez mais ágeis e os softwares cada vez mais complexos, para cobrir a complexidade crescente é necessário grande quantidade de casos de teste, e para se adequar ao curto prazo de tempo é necessário executar essa grande quantidade de testes de maneira mais eficiente porém, mantendo a acurácia. Isso é possível com a automação de testes funcionais.

Outra razão para se utilizar automação de testes funcionais seria para investir mais tempo no trabalho de análise do software e desenvolvimento dos casos de testes (para que os mesmos sejam mais eficazes em encontrar defeitos) do que na execução propriamente dita. Digo isso em casos de equipes pequenas de teste como é o meu caso em que sou o analista de testes e o executor dos testes. Isso me poupa tempo pra planejar melhor o que fazer.

O Juraci automatiza os testes funcionais da seguinte maneira:

Eu sempre tento automatizar aqueles casos de testes repetitivos e que exigem bastante atenção, nem sempre você está com a atenção 100% para executar o mesmo teste manual passo a passo, esquecer-se de um detalhe é normal para seres humanos. Prefiro investir um tempo até dez vezes maior para automatizar um caso de teste assim do que executa-lo sempre manualmente com o risco de errar algum passo e mascarar o resultado do teste.

Automatizo utilizando 2 softwares livres AutoIt e QAliber. Tenho um certo domínio sobre o AutoIt e o mesmo satisfaz minhas necessidades. O QAliber tenho estudado a cerca de um mês e logo utilizarei em um projeto “vivo”.

O Felipe Silva também acredita que a automação dos testes funcionais é necessária, e segundo ele é importante para manter a competitividade e consenguir atender as demandas:

Sim, é necessário principalmente para que se possa ser competitivo o suficiente para conseguir manter os atuais e clientes e ganhar novos, a automação também ajuda na qualidade dos testes, uma vez que pode-se concentrar o foco dos testes mais na análise de futuros novos erros do que em regressões, em certos casos é possível automatizar aquilo que ainda está apenas nos requisitos, ganhando agilidade também desde os primeiros ciclos de testes (deixando a “malhar grossa” na automação e a “malha fina” nos testes manuais).

O Felipe Silva compartilhou como ele faz a automação dos testes funcionais, dizendo:

Sim, sempre que possível e viável tentamos planejar a automação, não só de testes funcionais, mas todo tipo de automação que traga bons resultados, nem que só possamos começar a trabalhar nisso só daqui alguns meses, como ferramentas temos QTP (Quick Test Professional), Selenium, o próprio Java, tem coisas que acabam sendo automatizadas com Macros.

Segundo o Shmuel  a automação nem sempre é necessária:

A automação dos testes não é necessária. Ela pode ser vantajosa às vezes, ou prática, ou até mesmo agradável. Mas nem sempre ela é necessária.

Por outro lado, eu tento automatizar testes funcionais, claro. Existem testes que trazem beneficio quando automatizados.

Eu uso batch files, VBScript ou C# quando escrevo minhas automações. Já usei AutoHotKey (“irmão” do AutoIT mencionado pelo Juraci), VB, Ruby e Perl também, mas menos.

O Elias Nogueira destacou a importância de uma análise de viabilidade:

A automação nem sempre é viável, eu mesmo já recebi diversas demandas de clientes internos querendo “firulas” para “melhorar o seu trabalho”, mas de nada traz ganho como um todo para a organização.

Sempre, mas sempre que pensarmos em automação é necessário uma análise de viabilidade. Ela não precisa ser um documento mega extenso e difícil de ler, mas um tempo em que necessitamos avaliar se realmente a automação faz sentido ou traz ganhos em potencial.

Hoje mesmo tive um caso em que a automação solicitada, depois de fazer uma PoC (Prova de Conceito), só iria trazer benefícios após o 42° ciclo de execução, para um sistema que executa 1 ciclo mensal. O Analista de Teste que solicitou isso vê um ganho pra ele, mas eu nao vejo ganho em alocar minha equipe num trabalho que não trará um retorno esperado.

E o Elias, ainda complementou dizendo:

A automação é uma das ferramentas para o Teste, e não deve sempre ser tomado como lei nas empresas. Mas isso, como sempre depende…

Como o próprio Shamuel relatou em suas experiências em automação, podemos utilizar qualquer artifício para automatizar: shell script, AWK, programação pura, ferramentas de automação, etc…

A automação de teste, às vezes, mas atrapalha do que ajuda. Isso se deve a diversos fatores, como o próprio entendimento da automação por parte dos stakeholders (lembrem do gerente sem noção, que acha que a automação é como um “testa aí”, basta dar record-and-play e tudo se resolve), senioridade/conhecimento técnico da equipe e conhecimento de negócio por parte dos Analistas de Teste (sim, se estes não souberem especificar bons testes, estaremos fazendo uma má automação).

O Rodrigo Almeida resumiu bem a sua opinião sobre o assunto, dizendo:

Eu tenho certeza que ela é necessária. Para ter produtividade alta é preciso ter automação. O segredo é saber quais casos de teste escrever e automatizar!

Saber quais são os testes que são necessários ser automatizados é importante segundo o Rodrigo:

Sempre. Desde que o seu ROI seja positivo, ou seja, precisamos automatizar os casos de teste corretos. Casos de teste para telas CRUD de sistemas não precisam ser automatizadas. E eu acho que precisa fazer teste uma vez só na vida para estas telas. O que precisa ter teste automatizado são as funcionalidades do núcleo do sistema, que contém as regras de negócio do sistema que o cliente usa. Se estas regras sofreram algum impacto em alguma mudança realizada no sistema/ERP, só saberemos na execução dos testes funcionais automatizados.

Sobre a necessidade de automatizar testes de CRUD (Create-Read-Update-Delete), o Elias Nogueira acredita que tudo depende da situação, em determinados casos a automação de tais testes pode sim ser fazer necessária:

Em alguns tipos de sistemas o CRUD é o que é mais utilizado (e mail alterado) pelo cliente.

O importante é ter foco no que o cliente realmente usa e também no que ele realmente quer… Se precisar automatizar uma parte ínfima de uma tela ou regra que nunca é utilizada para agradar o cliente, temos que automatizá-la.
Isso é meio “ruim” pra nos, não gostamos, mas é o valor que o cliente vê nisso que nos faz ser vistos com bons olhos e como uma equipe que agraga valor.

O Ueslei Aquino, concorda com o Elias, e expôs uma experiência, falando:

Em uma experiência que tive, o cliente afirmava que “garantindo que, em cada tela do sistema eu consiga Cadastrar, Consultar, Alterar e Deletar, já posso garantir que alguma coisa funciona”. Essa foi a primeira meta colocada pelo cliente para a automatização.
Buscando entender o motivo, fizemos uma busca pelo sistema de chamados da empresa. E um grande número de chamados de cliente eram de relamação de defeitos nestes pontos.
O Ambiente era um ERP com mais de 20 módulos integrados.
Sobre o assunto, o que acho estranho, é que sempre que falamos sobre automação, alguém vem defender os testes manuais. Automação não exclui os testes manuais, aliás, um dos objetivos de automatizar os testes funcionais, é justamente para poder ter tempo para fazer outros testes, afinal não testamos apenas para garantir a “funcionabilidade” dele, há outras cinco características que poderão ser bem importantes para o sistema.
O Luiz Gustavo acredita que a necessidade de automação dos testes funcionais depende de vários fatores: 

De maneira geral:

- Da rotina dos testadores

- Do conhecimento sobre automação da equipe de testes

- Da tecnologia do sistema

- Da ferramenta de automação a ser utilizada (por isso é aconselhável estudar os benefícios de cada ferramenta antes de aplicá-la, sendo assim, não existe ferramenta “ideal” ou “melhor”)

- Do orçamento do projeto

- Se os prazos estão apertados (se não, é melhor fazer os testes manualmente, por motivos óbvios)

- Se possui um ambiente de testes dedicado

Mais especificamente:

- Se as funcionalidades a ser testadas se repetem (Regression Testing)

- Do esforço necessário para preparação do ambiente de testes (a massa de dados pode ser toda amarrada via Regras de Negócio, e isso dá um trabalhão…)

- entre outros.

Para o Fermiano talvez ela não seja necessária, mas pode ser uma possibilidade a ser considerada:

Eu não diria que a automatização de testes funcionais é necessária, mas a atenção para essa possibilidade sim.

Estamos sempre atentos para essa possibilidade, mas os fatores já citados aqui indicam que os testes manuais são mais eficazes e eficientes para a maioria dos casos. Automatizamos sim, mas é uma pequena fração da totalidade dos testes.

Exemplo: Numa etapa da fase de validação usamos um roteiro de testes para os testes de regressão. Esse roteiro possui aproximadamente 200 situações complexas de testes a serem executados, necessitando aproximadamente de 5 dias para ser completado (execução e verificação dos resultados). Não é raro alguém perguntar quando teremos 100% desse roteiro automatizado. A realidade é que apenas 30%, no máximo, desse roteiro poderá ser automatizado.
O Felipe Silva deu a sua contribuição dizendo:
A necessidade automatizar ou não vai do jeito em que as coisas são conduzidas em cada projeto, por exemplo no meu projeto trabalhamos tão corrido que enquanto estamos testando a release atual já estamos estimando e criado cenários e casos de testes para a próxima release, se alguém fosse parar para automatizar regression a próxima release iria atrasar, e as regras mudando toda release, em outras palavras o que chamamos de regression “hoje” tá mais pra “coisas que restaram da release passada”, não conseguimos nem manter os TCs que são super pequenos e nada detalhados, quem dera manter atualizados scripts, aqui vale mais a pena automatizar alguns procedimentos genéricos do que automatizar validações.
Mas tem empresas também em que as pessoas ficam focadas em uma release só, e acompanham o projeto desde a fase de requisitos até a homologação, enquanto os devs nem escreveram os códigos eles tem tempo para fazer um monte de coisa, quando é assim é, se o FW é conhecido é possível até automatizar desde o ciclo 1 paralelamente a implementação (aqui sim vejo ganho na automatização), então assim que a primeira build é gerada deixa-se uma maquina dedicada rodando os scripts dia e noite (se possível em integração contínua), e os testers seguem suas vidas normalmente em suas 8hs diárias executando os testes “pente fino” manuais. Pensando nisso, na release 2 os scripts das funcionalidades da release 1 já estariam lá, então novamente paralelamente a criação do código da release 2 iriam criar os scripts da release 2, se alguma coisa da release 2 quebrar alguma coisa da release 1 espera-se que os scripts da release 1 achem isso enquanto os testers estão focados na release 2. 

Não tenho como ser genérico em tirar uma conclusão geral que automação de testes funcionais em ciclos de regressão sempre são viáveis.

Testes sustentáveis, o que raios é isso?

No início da discussão coloquei que a automação dos testes funcionais é muito importante para se testar de forma sustentável, pois é muito difícil garantir a qualidade de um sistema apenas com testes manuais.

O Shmuel fez considerações pertinentes sobre essa minha colocação, que me fizeram explicar melhor o que seria testar de forma sustentável.

Primeiramente, testes sustentáveis são importantes para podermos garantir a qualidade do sistema a longo prazo. Pois pode ocorrer de precisarmos de esforço X para testar o sistema, no início do desenvolvimento, e 2X para testar o sistema nas etapas finais de desenvolvimento, cenário esse que revela que algo pode estar errado.

Testar de forma sustentável serial algo como testar de forma eficiente, ou seja, com o mínimo de esforço e o máximo de eficiência.

Ou melhor, testar de uma forma que fosse possível garantir um bom nível de qualidade, ao longo de todo o projeto, buscando investir um esforço sempre parecido. Ou seja, garantir a qualidade tanto quando o sistema tem apenas 2 funcionalidades, como quando ele tem 50.

Para tentar explicar o “conceito”: imagine que estamos no ano de 2006 e você trabalha no Google, mais precisamente na célula de desenvolvimento do Google Docs. Como todos sabem, o Google Docs é uma ferramenta que teve o seu desenvolvimento de forma incremental, e você como incubido de testar ele. Você precisará fazer vários testes a cada nova versão, sendo que boa parte destes testes, já foram feitos antes.

Se você fosse testar sempre de forma manual, acabaria entrando numa rotina, que sempre teria mais e mais testes para executar e isto com certeza iria impactar no projeto, uma vez que ou você necessitará de mais pessoas para te ajudar ou o prazo para a entrega será sempre maior, afinal a cada lançamento você terá mais testes para fazer.

Mas você é o Shmuel, uma pessoa consciente e que sabe da importância da sustentabilidade para o Teste de Software, por isso já em 2006 percebe que boa parte dos testes podem ser automatizados, e isso iria aliviar bastante o seu trabalho e você teria tempo para fazer outros testes mais complexos, que poderiam obter novas informações e que necessitariam de análises que um computador não consegue fazer (por exemplo, testes de usabilidade).

A ideia de sustentável seria essa. Meio viajante eu sei, e muito bonita na teória.

Você estuda a viabilidade de automação e planeja, ou simplemente ‘põe a mão na massa’?

O Juraci respondeu dizendo:

Eu estudo sim a viabilidade para cada caso de teste, em um projeto eu tenho casos de teste candidatos a automação. São aqueles repetitivos que serão utilizados em uma futura regressão, testes massantes tais como o mencionado anteriormente, testes que revelaram falhas no software também são candidatos pois mostram o seu valor durante o teste de regressão. Vale destacar que o caso de teste é a base para a automação, é o requisito do “sotftware/aplicativo/script” que será o produto da automação, não adianta ‘colocar a mão na massa’ sem ter os casos de teste bem definidos, pois isto equivale a ter um requisito fraco e que irá acarretar em muito mais transtorno como foi comentado.

O Ferminiano também fazer um estudo antes:

Sim, fazemos um estudo de viabilidade de automatização. Sempre aparece alguém querendo automatizar alguma coisa, pensando que basta apertar um uma tecla e pronto, como já disseram aqui na lista. Um breve estudo de viabilidade mostra que apenas algumas poucas vezes isso é possível.

Bem pessoal é isso, espero que tenham gostado do resumo, que mesmo atrasado não poderia faltar, pois essa discussão foi excelente, aliás, se você quiser saber mais, acesse o link para a página do DFTestes com a discussão na íntegra. ;)

Arquitetura para automação de testes

A 13ª Mesa Redonda DFTestes teve como tema “Arquitetura para automação de testes”, e tivemos 6 respostas e 3 participantes: eu, Elias Nogueira e o Felipe Silva.

A seguir, segue o resumo da discussão, quem quiser acessar a discussão na íntegra, basta acessar esse link.

Quais as atividades de um arquiteto de automação?

Segundo o Elias Nogueira:

As atividades são diversas, vou listar algumas aqui, mas não se restringe somente nisso:

->Criar a arquitetura de automação de testes;
->Criar a estratégia e direcionamento para os testes não-funcionais;
->Levantar/direcionar quais ferramentas podem ser usadas para determinado projeto;
->Sugere melhorias na arquitetura do sistema, para que fique compliance com a aplicação;
->Lidera/coordena uma equipe de automação, dando todos os direcionamento e resolvendo os problemas que os automatizadores tiverem;
->Cria todo o ambiente necessário de hardware e software para a aplicação da arquitetura de automação.

O Felipe Silva fez um comentário a respeito do papel do Arquiteto de Testes:

Não sou arquiteto. Como o Elias disse não é muito comum ver, trabalhar com um arquiteto ou ser um arquiteto de testes, eu particularmente só conheço o Elias, por este motivo não posso me aprofundar no assunto, só deixar minha opinião sobre o que eu penso à respeito.

A minha opinião sobre este papel é que é um papel extremista tecnicamente, digo extremista no sentido de que os skills necessários são diferentes de um skill de um tester funcional, pra quem gosta de programação mas ama testes mais do que desenvolvimento acho que este é o caminho, pra quem não gosta de programação e afins eis aqui o detalhamento do Elias da função para te ajudar saber se você realmente não gosta, pra quem gosta de um pouco de tudo, como eu, pense bem se quer ser um arquiteto ou não.
Uma coisa que gosto muito no cargo de analista de testes é que eu tenho uma liberdade de trabalhar com tudo um pouco, tornando o trabalho menos cansativo, quando eu “acordo para programação” crio scripts de automação ou desenvolvo alguma ferramenta para ajudar o time, quando não “acordo para programação” faço testes manuais, planejamento de cenários, revisão de documentos, casos de testes.

Na minha opinião as atividades que o Elias citou são as principais, destacaria apenas que o Arquiteto de Automação não é o Superman, e levará todo o projeto de automação nas costas, ele pode sim direcionar o rumo da arquitetura, mas todos podem participar e ajudar o mesmo a definir a arquitetura.

Além disso, quando estamos começando um projeto é essencial incluir esse profissional logo nas primeiras reuniões do time de desenvolvimento, pois o trabalho do Arquiteto fica MUITO mais fácil e é MAIS eficiente, quando temos um sistema com uma boa testabilidade.

Quais os conhecimentos que o arquiteto precisa ter para fazer uma boa arquitetura?

O Elias citou vários conhecimentos que um arquiteto necessita ter e disse posteriormente que “não é necessário ter 100% dos conhecimentos listados, mas sim fazer acontecer.”:

Precisa saber sobre muita coisa ao meu ver… Vocês conhecem algum arquiteto de aplicações (Java, .NET, etc..)? Um arquiteto de aplicações deve conhecer sobre diversas tecnologias, padrões, etc… sendo um profissional com o perfil muito técnico.

Ao contrário do que muitos pensam também, ele também conhece (ou deve conhecer) do negócio, justamente para montar uma arquitetura com base nas necessidades de negócio.

Alguns conhecimentos necessários de modo genérico:

->Conhecer de automação de teste em todos os níveis (óbvio); :P
->Conhecer pelo menos mais que uma linguagem de programação, e ser bom pelo menos em uma;
->Conhecer sobre arquitetura de aplicações e design patterns;
->Conhecer a linguagem SQL, sendo bem mais que um simples ‘select’ (PL/SQL por exemplo);
->Conhecer sobre Sistemas Operacionais e virtualização;
->Conhecimentos avançados em Teste de Software;
->Conhecer uma gama de ferramentas de todos os níveis (de apoio, unitário, integração, funcional e aceitação);
->Conhecer muito bem Diagramas UML e ER, pois a base de uma arquitetura de automação desenhada se dá por essas ferramentas.

Realmente, é uma lista bem grande mesmo de conhecimentos que o arquiteto necessita, mas vejo que além de todos os conhecimentos citados pelo Elias (concordo com todos), ele necessita ter um bom senso e uma boa visão do todo.

E falo isso, pois com todo esse arsenal de conhecimento adquirido, ele pode querer construir uma bomba atômica para matar uma mosca.

A visão do todo é sempre importante de ter em mente, pois às vezes podemos esquecer dela, e acabar desviando do caminho que deveríamos seguir.

Desenvolver uma ferramenta própria ou utilizar uma ferramenta do mercado?

O Elias deu a sua opinião dizendo:

Isso é um discussão boa. Eu creio que hoje em dia não há necessidade de criar uma ferramenta própria para a maioria de trabalhos que são de mercado (aplicações comerciais, bancárias, COTS, etc…).
Hoje existem muitas ferramentas pagas e opensouce/free que suprem essa necessidade, e quando precisamos de customizações, ou nós mesmo fazemos em uma free/opensource (se é que já alguém não fez) ou pagamos/baixamos plugins que suprem a nossa necessidade de customização.

Claro que existe o contraponto. Há uns 2 meses eu dei aula de automação para um desenvolvedor que fazia softwares para controle de radares e mísseis, uma coisa totalmente atípica. Como aplicar automação para um tipo de sistema desses?
Resposta: é necessário desenvolver um!a

Existe também empresas que querem desenvolve suas próprias ferramentas: frameworks de automação, issue tracker, etc… E isso não é errado. Na verdade não existe certo ou errado, existe o que é o melhor para a organização.

Minha opinião então fica:
Se não existe nenhuma diretriz que a empresa tenha que desenvolver uma ferramenta: compre ou adote uma
Se existe uma diretriz para que a empresa crie uma ferramenta: desenvolva, e fique atendo as ferramentas opensources, pois você pode (dependendo da licença da ferramenta) utilizá-la como base para a sua.
Minha empresa faz algo “não usual” de aplicações comercias: desenvolva uma ferramenta, se isso for realmente de ajudar. Mas lembre-se de que isso pode não ter um retorno imediato.

A resposta dessa pergunta depende muito da natureza do projeto, e é uma das primeiras que o arquiteto deve buscar responder.

No meu caso atual por exemplo:

  • Estou utilizando o Selenium para criar uma API, que possa ser utilizada pelos testadores (ainda estou estudando como os testadores irão utilizar essa API, minhas opções são: JUnit, easyb e Concordion). Ou seja, optei por criar uma ferramenta própria, só que utilizando outras ferramentas já existentes no mercado; :)
  • Já em um outro projeto o desenvolvedor criou uma aplicação que executa os testes criados por nós, mas ela possibilita apenas executar as ações, e agora estamos criando uma aplicação que automatiza toda a execução dos testes (pré-condições, ações e verificações). Neste caso, optamos por uma ferramenta própria.

Quais os maiores problemas dessa área?

Para o Elias os maiores problemas são:

O maior problema é de, na maioria das vezes, não termos essa cargo tão bem definidos, ou termos pessoas que ocupam esse tipo de cargo que não são tão preparadas tecnicamente, o que pode fazer da automação um negócio caro, pois ele pode ser arquitetado e construído da maneira errada.

Também as empresas necessitarem deste tipo de profissional explicitamente. É bem pouco comum acharmos uma vaga como esta no mercado.

E a principal é o conhecimento de uma pessoa que se propõe a ser um Arquiteto de Automação. São muitos conhecimentos que temos que ter para desempenhar essa função, além dela ser a função mais técnica dentro da área de Teste de Software. E sabemos que muitas pessoas ‘não gostam de ser técnicas’ dentro da área.

Eu colocaria também o Arquiteto de Automação em Teste de Software nas reuniões de pré-venda com o cliente e, posteriormente, em contato com os arquitetos da empresa que está contratando estes serviços. Isso pode poupar muita dor de cabeça em “negócios mal vendidos” e pode realmente mostrar o que pode e o que não pode ser feito para o projeto.

Ao invés de Arquiteto de Automação, eu diria que o profissional é um Arquiteto de Teste. Para mim toda a pessoa que se diz “Arquiteto de Teste” deve ter estes conhecimentos.

Eu destaco os seguintes:

  • A testabilidade dos sistemas sob teste, principalmente nos casos de sistemas legados;
  • É uma área bem recente, por isso ainda não temos cargos bem definidos;
  • Difícil encontrar bons profissionais;
  • Nos caso de arquiteturas de automação de testes, é necessário primeiro convencer as pessoas que a automação é viável e pode ajudar a minimizar/resolver os problemas enfrentados, e isso muitas vezes não é uma tarefa fácil.

E vocês pessoal, alguém aqui é arquiteto? Alguém gostaria de virar um? Quais as suas opiniões sobre o assunto?

O Felipe Silva deu a sua resposta dizendo:

Eu acho que eu gostaria sim de ser um arquiteto, gosto muito da parte técnica, trabalho muito com muito com isso também (por que eu quero), porém meu medo atualmente seria assumir um papel menos flexível no sentido de poder fazer de tudo um pouco, o que faz o serviço mais saudável ao meu ver.

Não sou. É uma possibilidade no mínimo interessante, eu diria. :D

Se já é difícil encontrar um bom Analista de Teste no mercado, encontrar um bom Arquiteto de Teste é mais difícil ainda. E isso ocorre por uma série de fatores, dentre os quais eu destaco três:

  • Acredito que boa parte dos companheiros de profissão, costumam ter a sua atuação mais voltada para a parte de Validação (negócio). Sendo assim, acabam indo em direção a área Gerencial (pensando em uma carreira em Y);
  • Ser um arquiteto é difícil, e você não se torna um, da noite para o dia (vide tempo necessário de experiência para essa vaga, por exemplo). Como o Elias e o Felipe disse, tal profissional necessita de diversos conhecimentos, e de forma sólida, e além é claro de boa experiência na área (lembrando que experiência é diferente de tempo na área);
  • O mercado ainda não sabe bem o que quer. Isso, infelizmente, é ainda uma realidade no mercado brasileiro, vide discussões já ocorridas no DFTestes sobre descrições de vagas de emprego.

Pra encerrar, acho importante a pessoa não buscar uma carreira simplesmente pelo status do cargo, você deve buscar a carreira que te dá mais satisfação profissional. Aliás, essa coisa de cargo na nossa área, na maioria das vezes, só serve para preencher no contrato ou na carteira.

Bem pessoal é isso.Continuem de olho na lista do DFTestes, pois sempre há assuntos bem interessantes lá, e poderão haver novas respostas nessa mesa redonda.

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

Quando automatizar?

A décima Mesa Redonda DFTestes teve como tema “Quando automatizar?”, e foi uma mesa redonda bem agitada, com 32 respostas (até o momento desse post) e a participação de 12 pessoas, sendo elas: eu, Elias Nogueira, Jonathan Rodrigo, Felipe Silva, Ueslei Aquino, Rodrigo Almeida, Milton Vopato, Marcelo Andrade, Shmuel Gershon, Rafael Porfirio, Sarah Pimentel e Jorge Diz.

Segue abaixo, o “resumo” da décima Mesa Redonda DFTestes, mais uma vez lembrando, que se você se interessa pelo assunto, é altamente recomendável a leitura da discussão na íntegra. ;)

Quando automatizar?

Segundo o Elias Nogueira:

Quando automatizar no sentido que não seja testes funcionais:

=> Qualquer tarefa repetitiva que gaste muito tempo no processo de teste
- Quando gastamos muito tempo criando/formatando Casos de Teste
- Quando gastamos muito tempo colhendo e gerando métricas dos testes

Quando automatizar no sentido de testes funcionais:

=> Testes de regressão
=> Smoke Tests
=> Tarefas repetitivas
=> Funcionalidades críticas do software
=> Testes com cálculos matemáticos

O interessante é que existe pelo menos um tipo de teste que somente pode ser feito automatizado (excluindo-se Portugal): o teste de performance. A base do teste de performance não é somente executar um teste e capturar o tempo de resposta, mas medir diversas outras variáveis que vão compor uma série de informações que juntas poderão dar uma visão de performance da aplicação. (Para maiores informações, consultar o Fabio Martinho) :)

Se falarmos em linhas ágeis (Jorge, por favor complemente), basicamente 90% dos testes são automatizados, em virtude da agilidade na entrega, conhecimento de negócio da equipe e conhecimento da equipe em ferramentas.

A respeito do comentário do Elias  sobre automação em linhas ágeis, eu penso que ela ocorre não em virtude da agilidade na entrega, e sim para garantir a qualidade na entrega, e principalmente, para garantir um desenvolvimento sustentável.

Na minha opinião os testes em nível unitário e integração também, que devem ser feitos pelos desenvolvedores, também são testes que devem ser executados de forma automática.

É bom lembrar que automação dos testes é um sonho de muitos profissionais da nossa área, porém ele pode passar a ser um pesadelo, se não for tratado de forma séria e madura (uma boa literatura sobre isso é o paper do Bret Pettichord – Seven Steps to Test Automation Success).

Pensando em uma equipe de Teste de Software, que realiza testes de sistemas, a automação é muito bem-vinda, quando há um grande volume de re-trabalho/testes de regressão.

Já pensando em uma equipe de Desenvolvimento de Software, os testes automatizados são de extrema necessidade, pois como costumam dizer, se você não escreveu testes para o seu código, você já está produzindo código legado.

Agora falando na linha ágil, a automação dos testes é essencial, olhando para o quadrante, percebemos que apenas os testes do terceiro quadrante são feitos de forma manual.

Dentre as razões citadas no livro Agile Testing, da Lisa Crispin e da Janet Gregory, estão:

  • Teste manual é demorado;
  • Reduzir a probabilidade de erros das tarefas de teste; (a tradução tá bem ruim, o original é assim: Reduce Error-Prone Testing Tasks)
  • Liberar tempo para fazer o trabalho o seu trabalho da melhor forma;
  • Prover uma rede de segurança, se eu fizer uma mudança no código eu terei os testes, que irão me avisar se eu quebrei algo;
  • Prover feedback cedo e frequente; (para mim está é a melhor razão) :D
  • Os testes que direcionaram a codificação (ex.: TDD e BDD) podem fazer mais do que isso (ex.: se tornam testes de regressão);
  • Os testes provem documentação, aliás, são uma excelente documentação;
  • ROI, com o passar do tempo o esforço gasto na automação dos testes se paga.

A respeito do quadrante de Marick o Jorge Diz tem uma opinião diferente:

Não é bem isso, os quadrantes de Marick têm a ver com a ênfase na automação. Mesmo para os testes do quadrante superior direito (crítica do produto / voltados ao negócio) é possível ser auxiliado por ferramentas de automação. Em outros quadrantes, não se descarta o teste manual. Na prática, apenas os testes de unidade (quadrante inferior esquerdo) são inviáveis sem automação.
É bom lembrar que no modelo de teste ágil, testes são pensados não apenas como mecanismo de detecção de defeitos, mas que também é analisado seu papel de especificação do comportamento do sistema e suporte à equipe de desenvolvimento. Requisitos, testes e exemplos são aspectos diferentes das mesmas especificações. De fato, esta semana bloguei sobre isso.
A respeito sobre a automação no contexto ágil , o Jorge Diz falou que:
Você não consegue ciclos curtos de entrega se tiver que orçar um ciclo de teste manual. Você não consegue qualidade se não tiver testes que podem ser rodados à vontade. Você precisa escrever e executar os testes junto com o sistema sendo desenvolvido para encurtar o ciclo de comunicação
com o cliente e não perder tempo e esforço com mal-entendidos.
No entanto, a ênfase em automação chegou a ser exagerada. Hoje, a comunidade ágil começa a valorizar os conceitos da escola context-driven,
que dá mais importância a testes manuais e exploratórios

Para o Jonathan Rodrigo precisamos ter maturidade e precisamos levar em consideração a quantidade de ciclos de testes que teremos, para que a automação possa ocorrer:

E em uma fábrica de teste se automatizarmos um caso de teste ou uma funcionalidade de forma incorreta (com dúvidas referente aos requisitos) iremos produzir evidências erradas com muito mais velocidade gerando assim um grande prejuízos, como por exemplo a desconfiança do trabalho da fábrica pelo cliente causando assim a perca do mesmo.

Porém se for bem planejada a automação e for executada conforme o planejamento o projeto será um sucesso, pois realmente automatizar diminui os custos e aumenta a velocidade da produção, claro se tudo estiver bem definido e sem sobras de dúvidas, pois se não estiver bem definido os custos podem aumentar e trazer grandes prejuízos.

Termino respondendo a pergunta:

Automatizar quando? Quando tiver maturidade, processo para suportar a automação e quando for identificado que iremos executar o teste mais de 4 ciclos, pois em meu ponto de vista não vale o investimento da automação  em caso de teste que será executado menos de 4 ciclos.

O Felipe Silva acredita que devemos automatizar os testes quando:

1. Quando autorizado pelo cliente
2. Quando viável (ganhar tempo ou redução de custos/recursos)
3. Quando tiver ferramenta e gente capaz de usá-la (“um tolo com uma ferramenta continua sendo um tolo”)

Creio que essas 3 respostas são a base de todas as outras.

1. Pode parecer estranho, mas no meu caso estamos proibidos pelo cliente de automatizar testes funcionais.

2. O fato ganhar tempo OU reduzir custos é a alma de qualquer automação, pois ganhar tempo significa ganhar dinheiro (“tempo é dinheiro”), reduzir custos e recursos é bom também, nem sempre andam juntos, as vezes vale a pena gastar um pouco mais para ter uma entrega mais rápida. Poder alocar recursos em outras atividades que envolvam qualidade (quando se pensa em automação industrial não tiveram tantas vagas na área de qualidade para o número de operários trabalhando o que gerou desemprego), é aqui que cabe a maturidade.

Automação não substitui teste manual e não encontra um percentual de defeitos maior do que o manual, pelo contrário, gráficos mostram que testes manuais encontram mais defeitos que automatizados, pois quando se está lidando e interagindo diretamente com o sistema você consegue pensar (ver) uma situação que até então não tinha pensado apenas lendo um requisito.

Sabendo disso, diria que automatizar com sabedoria é fazê-lo pensando em um teste que tenha como alvo testar parte do sistema, pois pensar que você irá automatizar 100% dos testes é ilusão (assim como é ilusão dizer que você tem certeza que 100% dos defeitos foram encontrados em qualquer tipo de testes), fazendo assim, após ter o script fazendo uma rotina de testes “óbvios” pode-se então focar em testes melhor elaborados no qual tenha que pensar com malícia para imaginar um caminho que consiga quebrar o sistema, pensar em uma situação ainda não prevista por ninguém. Salvo alguns casos como já citado pelo Elias em que manual não é viável (testes de performance, que envolvam cálculos, etc)

3. Ter ferramenta não significa comprar a mais cara no mercado, significa ter uma ferramenta que te gere resultados. A ferramenta “abc” usada pela maior empresa do mundo “fgh” não faz dela a melhor para você, e a melhor para você neste projeto pode não ser a melhor no outro projeto, não ser a melhor também não significa que não serve, se o resultado final gerado é pósito então vale a pena, o único fato é que se outra ferramenta daria um resultado positivo maior pode-se rever/calcular/viabilizar ou não uma mudança de ferramenta.

Tendo a ferramenta vem o mais o importante – antes de comprar a ferramenta é lógico – que é saber utilizá-la, e sabendo usar! Também não adianta nada ter um time expert no assunto e uma ferramenta excelente para ficar na “prateleira”, infeliz é o “chefe” que pensa que vai comprar uma ferramenta e você vai se virar para colocar ela para funcionar, treinamentos e capacitação são necessários.

Saber fazer um script bom não significa que a pessoa está fazendo da melhor maneira possível, quanta gente já não disse “era só isso? quer dizer que você só colocou essa linha de código e já faz tudo isso? nossa antes eu fazia…..”

Automação é um projeto, não parte de um projeto e deve ser tratada como tal, com líder de projeto, desenvolvedor, pessoas responsáveis pela qualidade do que está sendo criado/mantido, cronograma e orçamento.

Na minha opinião além de analisar se será viável (ganhar tempo ou redução de custos/recursos) automatizar o teste X eu também preciso analisar se o teste X será mais eficaz se automatizado ou não, pois executar ele de forma automatizada precisa, pelo menos, garantir a mesma qualidade da execução manual.

Ou seja automação deve pelo menos, garantir a mesma qualidade que os testes manuais, afinal de nada adianta ter um monte de suítes de testes automatizadas se elas não testam nada. ;)

A respeito da viabilidade da automação dos testes (citada pelo Felipe), é preciso também levar em consideração o sistema sob teste, pois se eu automatizar hoje, o teste X, que testa a funcionalidade Y, e amanhã a funcionalidade Y mudar, essa mudança poderá quebrar o meu teste X.

O Ueslei Aquino compartilhou um pouco da sua experiência, relacionado ao assunto da mesa redonda:

Imaginem o que é assumir um departamento de “testes” com missão de torná-lo um departamento de “Qualidade” (Garantia e Controle de qualidade) com 9 profissionais que nunca tiveram um treinamento em testes. A visão do cliente em relação ao setor era… “este setor não me gera resultados financeiros positivos e eu tenho aqui a ferramenta X que 2 pessoas que passaram por aqui não conseguiram implantar, fique com ela 2 meses estudando e depois me apresente o cadastro Y sendo testado por ela.”

Diante do conhecimento, procurei mostrar que sem ter pessoas treinadas, processo e metodologia de teste definidos, documentação de teste… iniciar automação poderia não ser a solução, mas um tiro no pé. Mas, sem sucesso para minhas colocações… a intenção era automatizar os testes e assim poder vender serviço de teste, ou seja, vender para os clientes do próprio sistema poderem utilizar e testar as aplicações e assim gerar resultados financeiros positivos ao setor.

Parece loucura né… mas é a mais pura verdade. Ou seja, eu estava construindo um legado de teste, com uma aplicação que tive que me virar para colocar para funcionar. O Cliente ficou ciente dos riscos, mas quis arriscar…

Diante disso, o que posso dizer do resultado foi… recebi uma proposta irrecusável…saí da empresa e eles continuaram com o processo e inclusive iam começar a aplicar em um cliente que estava implantando o sistema.

O Rodrigo Almeida também compartilhou uma experiência com automação:

Temos uma ferramenta de automação de testes desde 2000. E só em 2008 é que aprendemos como usá-la corretamente.

Tivemos que trocar toda a equipe, contratar pessoas com perfil técnico e conhecimento de lógica de programação.

Mudamos o nosso processo de testes, para podermos automatizar aquilo que era necessário, crítico e kernel dos nossos produtos. Antes a gente automatizava somente as partes periféricas dos produtos, sem impacto efetivo na detecção de defeitos. E os scripts eram criados por pessoas que não conheciam de programação/lógica. Os resultados eram terríveis.

Então, a decisão de quando automatizar foi baseada nas seguintes premissas: É parte do núcleo do sistema? É usado por vários clientes? Faz parte do processo funcional do cliente? Se sim para  uma ou mais de uma pergunta, então automatiza.

Com a mudança radical feita em 2008, saímos de uma média de erros mensal na ordem de 140 erros para uma média de 50 erros/mês em 2009. Não alteramos nada no processo de desenvolvimento. Somente criamos um processo novo de automação de testes funcionais. Não fazemos testes de performance, somente automatizamos testes funcionais e executamos os testes já gravados (teste de regressão).

Com uma equipe correta, ou seja, com conhecimento em programação, conseguimos diminuir nosso ciclo de testes que eram de dois meses, isto mesmo, dois meses, para 12 horas! Somente otimizando os scripts já gravados.

Para o Milton Vopato devemos automatizar quando:

Na minha opinião, a automatização é positiva e é uma tendência para ganho de eficiência. Quando automatizar? acredito que quando você processos mapeáveis, tipo execução em batch, performance, lista de informações padrões, etc. Este tipo de validação economiza tempo para regressões, mas quero chamar atenção a outro ponto de quando automatizar. quando pensamos em quando automatizar, pensamos para que e no processo como um todo, mas acho válido, com uma análise de benefício, criar automatizações parcial do processo de teste funcional também, ex: Hoje validados requisitos funcionais em um XML, então automatizamos a criação do request e agora estamos trabalhando na automatização da leitura de algumas tags na saídas, com isso ganhamos performance e qualidade na execução

O Shmuel lembrou de uma automação que é muito bem-vinda em uma área de Teste de Software:

Me parece que nenhuma resposta comentou em um tipo de automação muito útil: A automação do ambiente.

Em sistemas aonde é necessário configurar a rede o produto e os periféricos de forma específica antes de começar a testar, automatizar o processo de configuração é muito útil.

E além do mais, essa automatização acaba sendo muito apreciada e utilizada por toda a organização, incluindo programadores, pessoal de suporte etc.
Essa automação é legal também porque ela não atrapalha ou influência os testes funcionais.
Já a automação de testes funcionais me da certo medo… :)
É muito fácil exagerar na quantidade te testes automatizados, e é mais fácil ainda exagerar na confiança dada a automação.
Com isso, devo colocar que aonde trabalho temos um sistema de automação bem extenso, e tentamos automatizar todos os testes importantes para serem rodados como regressão.

Para o Rafael Porfirio:

A automação também (ao meu ver) é uma opção quando temos uma certa estabilidade na aplicação em que estamos testando assim como o ambiente em que testamos, por isso em muitos casos a primeira coisa a se automatizar são os ciclos de regressão, visto que já foram testados manualmente e de certa forma atingiu uma certa estabilidade por já ter passado por outros ciclos de teste manual.
Outra coisa que devemos levar em consideração, também é o tempo que se leva para criar (scripts de alto, média ou baixa complexidade) e também para se dar manutenção….se você tem uma aplicação onde a cada release seu script deve ser recriado….talvez não seja viável a automação…

Ainda assim, muito é importante ressaltar que um teste automatizado jamais substitui teste manual. Pois assim como desenvolvedores não conseguem fazer todo o codigo 100% correto, como testers podem confiar em sua própria programação para um script?

A Sarah Pimentel fez considerações bem interessantes sobre o tema:

Eu sou bem adepta a processos, não como forma de burocratizar, mas como forma de organizar.

Então pra mim a primeira coisa é ter um processo para decidir isso. E essa decisão se dá em cima de viabilidade de automação.

Trabalhei em uma empresa que tinha uma equipe de automação separada da dos testes funcionais (eles também fazem testes funcionais, mas são especialistas em automação). Quando uma equipe solicitava a automação dos seus testes tinha que responder um questionário inicial para que a equipe de automação avaliasse a viabilidade desse projeto. Por que isso? Porque ao contrário do que muitos pensam nas empresas automatizar ao invés de ser a solução dos seus problemas pode ser mais um gerador de problemas.

Algumas considerações:

Você está automatizando porque você acha que vai encontrar mais erros?

Não vai. O processo automatizado tende a encontrar cada vez menos erros e até mesmo em determinado ponto, não encontrá-los. De tanto rodar os mesmos testes a aplicação fica estável naquele ponto e dificilmente aparecem erros ali.

Você acha que pode automatizar a sua aplicação a qualquer momento e que essa investida é suficiente?

Há dependências de interface gráfica. Se o desenvolvedor mudar “só um negocinho”, pode ser que o teste tenha que sofrer manutenção.
Também vale ressaltar a excelente comunicação do negócio com os desenvolvedores e os testers porque se mudanças no negócio forem discutidas no café e implementadas sem que os testers saibam, o teste também não vai funcionar.

Testes automatizados precisam ser testados?

Obviamente que sim. São programas. Se foram escritos por testers ou desenvolvedores não quer dizer que não possam ter erros. Automatizar precisa passar (rapidamente, claro) pelos mesmos estágios que o desenvolvimento de qualquer outro software. Com base na especificação ele será construído e alguém precisa validá-lo.

Amanhã tá pronto?

:D Não! :P

Automatizar requer tempo. Você está disposto a esperar? Quando estiver pronto, você vai ter tempo de utilizar? Por quanto tempo? Compensa?

Dá pra automatizar qualquer coisa?

Bom, não sou expert em automação para dizer que não. Tem um monte de gente na lista que sabe mais que eu pra falar isso, mas sei que tem coisa que é tão complexa que não vale a pena “perder” esse tempo (da forma como foi colocado na observação acima)

O desenvolvedor participa da automação?

Pode ser que seja necessário envolver o time de desenvolvimento para fazer algum ajuste (testability). A equipe de dev dispõe dessa alocação para ajudar?

Enfim. Depois de tudo isso, eu queria dizer que automatizar é legal sim! :D Só que é uma coisa que tem que ser planejada com tanto carinho quanto qualquer outro software.

Para o Jorge Diz:

A implantação de testes automatizados cria uma dinâmica diferente, para bem ou para mal. Se dependermos exclusivamente de testes manuais, a cada mudança necessária do sistema há o dilema de incorrer em um custos e prazos significativos para cada ciclo de teste: é extremamente difícil para um gestor avaliar o risco de não testar. A gestão tende a ser mais conservadora em melhorias do sistema (por conta do custo das mudanças), e a manter ciclos longos de entrega de funcionalidades.

Com testes automatizados, o gestor consegue ter informações mais confiáveis. para decidir, e diminuir muito o investimento a cada ciclo. Testes automatizados são uma forma de seguro contra diversos riscos, e ajuda a que as mudanças necessárias ao negócio possam ser implementadas. Oportunidades de negócio deixam de ser perdidas.

Bem pessoal é isso. Continuem de olho na lista do DFTestes, pois sempre há assuntos bem interessantes lá, e poderão haver novas respostas nessa mesa redonda.

Saiba mais

Segue abaixo, algumas publicações que foram referenciadas sobre o assunto, durante a mesa redonda:

Apresentação: 4° Encontro Mensal ALATS: Automação de Testes, Mitos e Verdades

Livro: Implementing Automated Software Testing: How to Save Time and Lower Costs While Raising Quality

Livro: Automated Software Testing: Introduction, Management, and Performance

Livro: Agile Testing

Fórum: SQA Forums – Automated Testing

Artigo: Seven Steps to Test Automation Success – Bret Pettichord

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