Três amigos (Three Amigos) é uma técnica de discussão e definição de algo que será feito, podendo ser uma feature, incremento ou correção.
O termo surgiu no meio ágil em 2009 com o principal objetivo de colher pontos de vista de diferentes perspectivas e áreas:
negócio: geralmente representado pelo analista de negócio ou dono do produto;
desenvolvimento: representado pelos desenvolvedores, arquitetos;
e teste: representador pelos engenheiros de teste.
Apesar de chamar 3 amigos, essas discussões podem, e por diversas vezes devem, conter mais que literalmente somente 3 pessoas.
Por quê utilizar essa técnica?
Obter opiniões compartilhadas de diferentes expertises ajuda a definir melhor o que deve ser feito, evitando mau entendidos e falhas de comunicação.
Além disso, utilizar essa técnica contribui nos seguintes aspectos:
Definição de “qual o problema queremos resolver?”: muito antes de criar código, wireframes ou mesmo testes, é necessário entender bem o que precisa ser feito. Se não entendemos qual o problema queremos resolver com a nova funcionalidade ou correção, corremos um grande risco de entregar algo totalmente fora do real ou pretendido (Alguém aí já passou por isso? ver uma função ser discutida, desenvolvida, testada, e ao final do ciclo não ter nada a ver com o inicialmente pretendido);
Definição de pronto para ser desenvolvido (Definition of Ready): como sabemos se algo está bem definido o suficiente para começar a ser desenvolvido? o que entendemos por pronto para ser desenvolvido? – já discutimos, detalhamos o que deve ser feito, descrevemos em algum lugar, colocamos as estimativas e está pronto para ser pego por algum desenvolvedor para ser desenvolvido;
O mais comum é utilizar nas reuniões de refinamento de backlog (grooming/pbr).
Mas nada impede o uso dessa técnica durante o desenvolvimento – para sanar dúvidas de algo que está sendo desenvolvido, ou também depois que algo foi desenvolvido – para traçar melhores formas de teste. Pode ser utilizada até antes mesmo de uma reunião formal para definição de itens do backlog.
O intuito é ter sempre pessoas advindas de diferentes áreas discutindo e chegando a um consenso sobre o que deve ser feito.
Como isso influencia na qualidade do produto
A participação de testers desde as fases mais iniciais do ciclo de desenvolvimento é sempre benéfico pois eles serão capazes de levantar questões sobre testabilidade e sobre a qualidade do que deve ser produzido.
Além disso, as discussões que levam em consideração diferentes pontos de vista são mais ricas para originar cenários de uso.
Mais contribuições significam uma maior cobertura de possíveis cenários, possibilidades e restrições.
Com base nessa informação, os testers podem então aprender mais sobre o que cada área espera do software e traçar casos de teste mais eficazes, contribuindo para uma melhor qualidade do produto.
Pensei comigo: como assim? é praticamente dizer que meu trabalho não deveria existir. Quase ofendido, chateado, magoado, tipo criança quando xinga a mãe.
Mas respirei fundo, fiz cara de ser humano altamente maduro e evoluído e segui em frente. Porém, essa ideia não me saiu da mente tão rápido ou facilmente.
Sempre vejo esses questionamentos como oportunidades de crescimento. Defendo sempre que testers devem saber tudo de tudo. Quanto mais soubermos melhor seremos no que fazemos. Pontos de vista contrários são ótimos para nos confrontar quanto ao que sabemos e evoluir.
E essa “pulga atrás da orelha” me levou a grandes discussões sobre o assunto com alguns excelentes engenheiros de software tanto daqui quanto dos USA. Não foram discussões no sentido programa do ratinho ou programa da tarde mal sentido. Pelo contrário, o objetivo foi racionalizar sobre o que foi dito, pedindo esclarecimento e tentando ver pelo ponto de vista do outro.
Existe sim quem defenda que o teste está morrendo (ou morto, para os mais catastróficos).
Gostaria de dizer que após muito refletir, concordo em partes.
Concordo que o teste totalmente manual, da forma como era feita totalmente isolada e somente após a construção do software não seja mais adequada no mundo agile.
Além de automatizar para agilizar, precisamos estar integrados e remando para o mesmo objetivo, juntos, e com informação propagada igualmente nas equipes desde o inicinho da produção de alguma funcionalidade.
Em um mundo ideal testers realmente não deveriam existir. Em um mundo ideal não existem bugs. Os desenvolvedores realizam todos os testes unitários e de integração perfeitamente, respeitando as restrições das frameworks. As complexidades de integração entre componentes do software não geram novos defeitos. Não há falhas de comunicação nem especificação entre as diversas partes da equipe, localmente ou espalhadas pelo globo. Mas além disso, e principalmente:
O MUNDO IDEAL NÃO EXISTE
Se você já escreveu uma redação ou qualquer outro texto na vida, sabe bem que mesmo que o façamos com toda a atenção, revisemos diversas vezes sempre escapa algum erro.
Basta que uma outra pessoa leia nosso texto uma única vez que essa pessoa encontre esses erros e pontos de melhoria que não enxergaremos nas diversas revisões.
Simplesmente porque temos o viés de quem produz uma obra, de defender o que produzimos e isso torna difícil um olhar imparcial sobre nossa própria produção.
Quando testamos nós mesmos as linhas de código que produzimos, mesmo que de forma inconsciente, tendemos a fazer testes de confirmação ao invés de testes destrutivos como um tester faria.
É uma diferença de mindset mesmo. O mindset do teste é destrutivo enquanto o mindset do desenvolvimento é construtivo. Dois objetivos inerentemente diferentes, apesar de complementares que buscam produzir software de qualidade.
Fazer software é muito parecido com escrever texto. Só isso, tudo isso, muito mais que isso. É tentar traduzir da cabeça das pessoas as suas necessidades para o mundo da programação. Do abstrato das necessidades para o abstrado do código solucionando os problemas reais.
E essa atividade está sujeita a erros. Muitos erros. Vários erros!
“Partes que foram feitas independentes e testadas e que funcionam sozinhas deveriam funcionar bem juntas”
Essa afirmação parece ser verdade mas infelizmente para o mundo do software não é. Para quem conhece engenharia de sistemas isso não é de se assustar. Mas para quem nunca ouviu falar disso, procure saber sobre propriedades emergentes dos sistemas.
A complexidade que temos que lidar ao produzir grandes produtos de software escaláveis, distribuídos, confiáveis e tolerantes à falhas é enorme. E em cada etapa – requisitos, projeto, desenvolvimento, integração, teste – mais e mais erros são inseridos no processo de produção.
Frente a isso, a conclusão é:
o teste de software não morreu, e sinceramente não o vejo morrendo tão cedo. O teste evoluiu, da mesma forma como os processos, ferramentas e linguagens também evoluíram.
E continua extremamente relevante em um mundo altamente competitivo com clientes cada vez mais experientes e exigentes por experiências de usuário maravilhosamente desenvolvidas.
Já se perguntou porque devemos testar os softwares que criamos? Afinal, qual o objetivo do teste de software?
Geralmente quando fazia essa pergunta para minhas turmas de alunos ou amigos de computação, a primeira coisa que respondem é:
“a gente testa para ver se funciona”
Essa resposta não está errada, mas também não está inteiramente certa. Ela está incompleta e esconde a natureza real do teste.
Dizemos que o teste possui a natureza destrutiva.
Diferentemente do desenvolvimento, que possui a natureza construtiva, dizemos que o teste de software possui a natureza destrutiva.
Parece meio dramático isso, mas o motivo primordial do teste de software não é demonstrar que algo funciona, mas demonstrar que esse algo possui problemas!
Isso quer dizer que o mindset do desenvolvimento e teste são inerentemente diferentes. Claro que ambos devem estar focados na qualidade final e primando um produto que funcione da melhor forma possível e agregue o maior valor possível para os clientes.
Mas no momento do teste, o foco é diferente de quando estamos desenvolvendo. No teste, executamos os programas justamente procurando aqueles casos que podem ter sido esquecidos na hora de fazer os requisitos ou de programar o produto. Procuramos por combinações que causarão comportamentos fora do comum, esperado, normal e seguro do produto.
Assim, o objetivo do teste de software é fazer o programa falhar, revelando defeitos que causam isso.
O objetivo secundário é mostrar que o software funciona de acordo com o esperado
Além de procurar por defeitos, o teste também serve para verificar se o que foi acordado foi de fato desenvolvido corretamente. Verificamos se os requisitos foram implementados de acordo com o que foi pedido.
Essa demonstração de funcionar conforme o esperado para alguns casos é chamado por vezes de exercício do “happy path” (caminho feliz). Caminho feliz porque estamos apenas mostrando que aquele produto funciona bem para aquelas entradas que colocamos.
Importante notar que apesar de ser possível demonstrar que o produto funciona para determinadas entradas, não temos condições de demonstrar que o produto funciona bem para absolutamente todos os conjuntos de entradas e combinações possíveis (salvo para domínios bem pequenos) dada a natureza infinita das possibilidades que essas entradas assumem.
E é exatamente por isso que existem as técnicas de teste, para nos ajudarem a criar casos de teste que sejam relevantes e que demonstrem o maior número de defeitos possível quando executado, mesmo sem exercitar todas as possíveis combinações de entradas de um software.
Além disso, erros no software podem causar tragédias e custar vidas
Veja alguns exemplos em que catástrofes foram causadas por erros de software:
Ainda hoje vejo muita confusão em torno do termo framework (ou arcabouço em português, mas ninguém usa esse termo em português. Eu sempre lembro de calabouço quando falo arcabouço).
É comum as pessoas confundirem biblioteca com framework, dentre outras confusões e dificuldades de explicar de forma simples o que é um framework.
Vou tentar desmistificar isso de uma vez por todas e de uma forma que espero que sera fácil lembrar:
Uma framework é um conjunto de componentes e regras para se fazer algo.
Não é algo exclusivo de computação nem de testes de software pois existem frameworks de gerência de projetos, processos de software, atendimento de usuário, desenvolvimento de alguma habilidade humana, etc.
No caso de frameworks de programação, elas podem ou não conter bibliotecas (lembrando que bibliotecas são pedaços de código bem desenvolvidos, testados e confiáveis para aproveitarmos nos nossos projetos e não precisar fazer tudo na unha do zero). As frameworks podem ser server side, client side, ambos, e por aí vai.
Exemplos: Rails, que é uma framework de ruby; spring que é uma framework de Java; Zend, Cake, que são frameworks de PHP.
Assim, uma Framework nada mais é do que “um jeito” de se fazer algo usando algumas ferramentas.
O que é uma framework de automação de teste de software?
Se uma framework, de forma geral, é “um jeito de se fazer algo usando alguns componentes”, o que é uma framework de testes automatizados? o que ela precisa conter?
Para montarmos uma framework de testes automatizados devemos pensar em quais componentes (programas que nos ajudarão a realizar os testes) e quais as regras que esses programas definirão sobre a forma com que escreveremos nossos testes.
Assim, nossa framework de teste é o conjunto dos programas necessários (cucumber, selenium, capybara, watyr, phantomjs, Rspec…) para realizar os testes juntamente com as regras de como esses testes serão escritos.
O formato de se escrever os testes depende então das ferramentas que usamos para montar nossa framework de teste.
Por exemplo, se em nossa framework usamos Cucumber, é certo que precisaremos ter uma pasta específica para colocar nossas features e os step definitions dessas features, pois isso é uma regra do Cucumber.
E assim por diante, para cada ferramenta que escolhemos usar na framework.
Exemplo de framework de automação de teste de software usando Ruby
Para exemplificar mais detalhadamente, suponha que estamos definindo uma framework para realizar testes automatizados web, e que queremos usar a linguagem Ruby para escrever os testes automatizados.
Assim, um exemplo de framework de testes automáticos usando ruby como linguagem poderá conter os 4 elementos a seguir:
1. Cucumber: para escrever as features (cenários) dos testes de uma forma mais próxima da linguagem humana, usando BDD e também para coordenar os testes. O cucumber funciona como um maestro, controlando a execução dos testes. Se quiser entender mais sobre essas histórias, basta ler esse texto aqui onde falo sobre isso;
2. Rspec: para dar mais poder às verificações e comparaçõs que realizaremos (Ex: eu espero que o texto do botão curtir do facebook seja “curtir”);
3. Capybara: para facilitar a mudança entre os drivers que de fato executam os testes nos browsers, fazendo com que os testes tenham baixo acoplamento nas camadas mais baixas (não sejam dependentes dos drivers que de fato executam as ações nos browsers);
4. Selenium: driver dos testes;
Além dessas ferramentas que se tornam padrão para todo teste que escrevemos a partir da definição da framework, ainda é possível a inclusão de varias outras bibliotecas (gemas no caso de ruby) para ajudar no teste, quando necessário.
Podemos por exemplo variar os drivers, e ao invés de usar Selenium, usar Rack::Test no lugar do selenium, ou ainda incluir gemas para lidar com JSON, XML, etc.
O importante na hora de definir uma framework de testes automatizados é que o conjunto das ferramentas escolhidas para compor a framework auxilie na escrita e manutenibilidade desses testes e não seja motivo de confusão para a equipe tornando os mais complicados e ineficientes.
Conclusão
Viu que não tem segredo a definição de framework? espero que a partir de agora você possa não ter mais medo das frameworks, seja lá onde for usá-las.
Além disso, que tal usar os 4 elementos indicados acima para selecionar e montar sua própria framework de testes automatizados de software?
Deixa aí nos comentários quais as ferramentas estão presentes na sua framework de teste =}
Além disso, um bom vídeo para começar com a área de testes é esse aqui:
Duas definições bem recorrentes no meio do teste são validação e verificação. Apesar de estarem intimamente ligadas, e contribuírem com o esforço de teste, são atividades diferentes.
Segundo Offutt:
Validação: é o processo de avaliação do software, realizado ao final do processo de desenvolvimento, que garante a conformidade com sua intenção de utilização;
Verificação: é o processo de determinar quando os produtos de uma determinada fase do processo de desenvolvimento preenchem os requisitos estabelecidos durante a fase anterior.
“um elemento específico de um artefato de software que um caso de teste deve satisfazer ou cobrir”.
Diferentemente dos requisitos do software (que são funções que o usuário espera que o produto tenha para satisfazer suas necessidades), podemos pensar nos requisitos de teste como as condições do software a serem testadas. Ou seja, as possibilidades de entradas e ações a serem testadas.
Em outras palavras, podemos entender os requisitos de teste como as condições que determinado software deve satisfazer, ou ainda, as variações de determinada função que teremos que verificar (testar) desse software.
Por exemplo em uma função simples de cadastro, podemos ter os seguintes requisitos:
Cadastrar dados de usuário;
Alterar dados de usuário;
Remover dados de usuário;
Imprimir dados de usuário.
Apesar de ser um exemplo bem simples de CRUD, esses seriam os requisitos de teste mais básicos dessa função. Assim, os casos de teste criados, deveriam verificar cada uma deles.
Os requisitos de teste podem ser derivados (criados, obtidos) a partir de diferentes fontes de informação como: documento de requisitos, documentos de modelagem, código fonte da aplicação sob teste, e até mesmo conversando-se com os analistas responsáveis e donos do produto.
É com base nesses requisitos de teste que os casos de teste são gerados. Dessa forma, o conjunto de teste deve ser criado para satisfazer, se possível, todos os requisitos de teste. O “se possível” na frase anterior é dito pois podem haver requisitos de teste que sejam inalcançáveis em um produto de software de modo que seja impossível satisfazê-los.