BT
x A sua opinião é importante! Por favor preencha a pesquisa do InfoQ sobre os seus hábitos de leitura!

Sua aplicação está pronta?

Postado por Gil Zilberfeld , traduzido por Diogo Carleto em 23 Jan 2014 |

Questão simples, resposta difícil.

Entregamos software na maior parte das vezes cumprindo prazos e tentamos espremer todo o esforço de desenvolvimento e testes para cumprir esse prazo. Priorizamos o que pensamos ser importante, e uma vez que nossa aplicação alcance certo nível de qualidade, estamos prontos pra produção (go live). Tendemos a assumir que terá ao menos mais uma versão (release) no futuro, desde que não estamos totalmente felizes com o que liberamos. Mas mesmo quando entregamos, podemos dizer o quão preparada está nossa aplicação? Contamos com nossos testadores para obtermos esse feedback, mas para o bem do produto e sua qualidade devemos envolver todas as pessoas nesse processo.

Neste artigo, discutiremos diferentes maneiras que podemos testar aspectos de aplicações modernas para lançar um aplicativo que funcione. Entretanto, seu trabalho "regular" não é o de testar. A qualidade da aplicação não pode ser corrigida no final. Nosso objetivo é construir e assegurar a qualidade ao longo de todo o processo de programação.

Uma breve história dos testes

As coisas costumavam ser fáceis, antes tínhamos testadores como um grupo funcional em nosso projeto de desenvolvimento. Os desenvolvedores tinham certeza que as coisas funcionavam. Como os projetos se tornaram maiores, as aplicações se tornaram mais complexas e as datas de lançamentos mais apertadas. Uma vez que programadores sempre foram escassos e agora mais ainda, eles foram pressionados a desenvolver mais funcionalidades em menos tempo. Os bugs estão ocupando o terreno da grande "Crise da Qualidade". Precisávamos de exterminadores.

Os testadores seriam os exterminadores. Durante o processo de passar a responsabilidade, os testadores se tornaram os guardiões para impedir que os bugs deixem a construção. Infelizmente, essa ideia não funcionou. As aplicações são muito complexas e com muitos cenários para os testadores cobrirem totalmente. Mesmo quando a automatização foi introduzida, os testes podem precisar do mesmo tempo que o desenvolvimento original. E os bugs continuam lá fora em abundância.

Durante os últimos anos, principalmente em paralelo a expansão das metodologias ágeis, ficou claro que as mudanças no ecossistema impossibilitam deixar os testes para o fim. Além disso, a mudança do software instalado, para o cliente-servidor, para a nuvem e aplicações mobile, fez a decisão, se uma aplicação está "pronta para o mercado", muito mais desafiadora.

Testar hoje em dia é complexo

Frequentemente referimos os testes como uma fase importante em alcançar software entregável. Mas se pensar sobre isso, os testes se tornaram tão penetrantes no processo de desenvolvimento, definitivamente não é um "período" ou um "trabalho", mas um conjunto de habilidades que está espalhada por organizações de desenvolvimento de produtos.

Aqui está um exemplo aparentemente simples de que, testar não é somente verificar se o trabalho está funcionando como especificado originalmente. Suponha que no determinado requisito: 3 falhas na autenticação da aplicação irá bloquear o usuário. Isso parece bastante simples, mas uma vez que começamos a investigar, temos mais dúvidas, o que é uma falha? O que acontece depois do bloqueio? Estes requisitos "invisíveis" podem não ter sido especificados, mas devem ser incluídos uma vez que entendemos o contexto.

Vamos mais adiante: temos todos os requisitos bem definidos, como testamos todos eles? Não pode testar o sistema em produção, então queremos a funcionalidade testada em alguns servidores de pré-produção. É necessário executar testes de integração que configure os casos, execute os passos no cenário, valide se as coisas realmente funcionam, e deixe as informações como encontrou. Também podemos testar estes casos em nível unitário, aonde simulamos (mock) o banco de dados e chamadas de ambiente.

Isso é somente um simples requisito, e tudo é feito antes do testador colocar suas mãos na aplicação.

Feedback contínuo

O modelo V é considerado obsoleto em equipes ágeis, mas até hoje ele carrega o conceito fundamental que, para cada etapa do processo há um ponto de teste para verificar a operação.

Hoje chamamos eles de "feedback contínuo". Eles podem ser descritos pelo ciclo Planejar-Realizar-Testar-Corrigir de Deming:

Em desenvolvimento ágil tentamos executar estas iterações o mais rápido possível. O que dá errado no projetos waterfall é que as iterações são enormes e o ciclo de feedback se estende por semanas, meses e até anos. No entanto, cada programador que compila seu código a cada poucos minutos sabe disso: quanto menor o ciclo melhor.

Temos várias opções para invocar essas iterações em diferentes situações. Entretanto, quando temos que verificar as funcionalidades em execução, caímos na realidade.

Os feedbacks curtos não acontecem "por acaso", precisamos colocar eles em prática e faze-los funcionar. O intermitente "compile agora" é possível por que:

  • Temos ferramentas que tornam isso possível. Compiladores são eficientes, fornecendo um monte de feedback rápido;
  • Sabemos que o feedback funciona, então criamos um sistema no qual o feedback é fornecido, nos programamos para pressionarmos o botão "compilar" a cada poucos minutos. Até sentimos que estamos andando fora da pista quando não obtemos feedback em tempo hábil.

Isso só funciona quando o código compila relativamente rápido. Quanto mais eficiente e leve um compilador é, se o compilador demora horas, isso não é rápido o suficiente. Não faremos isso tão frequentemente, não teremos o feedback e voltaremos a estaca zero.

Feedback rápido através de isolação

Para ter um ciclo de feedback mais curto, precisamos cortar custos. Por exemplo, para contornar os longos ciclos de compilação, podemos executar compilações incrementais. Ao invés de ficar esperando toda a compilação terminar, compilamos somente as partes que mudaram. Isto é gerenciamento de risco: Sacrificamos a qualidade do feedback pela velocidade do feedback. Existe uma chance do sistema se comportar diferente após uma compilação total, mas supomos que não vai haver muita diferença. Sob essa suposição, encurtamos o ciclo do feedback.

A ideia de isolar partes dos sistemas e processos para obter feedback mais rápido não é nova e aparece muito durante o desenvolvimento. Podemos até não usar esse termo (como no caso da compilação incremental), mas ele está sendo usado em outros cenários, aonde queremos verificar o feedback mais rápido.

Verificação e isolação

Construindo a aplicação certa: O maior desperdício é a construção do produto errado. O desenvolvimento do produto começa com a identificação dos requisitos certos, muitas vezes antes mesmo de ter um protótipo interativo. As pessoas responsáveis pelo produto usam todos os tipos de ferramentas, incluindo mockups, desenhos e então protótipos para coletar requisitos e feedback, verificar se o desenvolvimento está no caminho certo, ou pivô (no jargão lean startup) - mudar a direção, coletar feedback novamente e finalmente voltar para o caminho certo.

Observe que est verificação é diferente do antigo modelo V de verificação de requisito: estamos verificando se construímos o que o cliente precisa, ao invés verificar se os requisitos especificados foram construídos corretamente. No começo, não precisamos de uma aplicação viva. Mais tarde, essa coleta de dados não para. Os dados de uso continuam a ser recolhidos em sistemas vivos, para o desenvolvimento e melhoria contínua.

Testes unitários funcionais: Este é o exemplo essencial para o uso de isolamento, uma vez que grande parte das funcionalidades não podem ser testadas rapidamente sem serem isoladas. Quer utilize frameworks de mocking, containers de injeção de dependência, ou simples TDD e dependências abstratas; se trata de isolamento do que é testado no ambiente. A ideia por traz dos testes unitários é obter feedback rápido, por isso, faz sentido ter ferramentas para conseguir isso.

Olhando além do processo de teste de unidade e o que ele tenta alcançar, encontraremos fundação de construções isoladas dentro do software (por exemplo, seguindo os princípios SOLID) tendo outros benefícios. Costumamos olhar para a manutenibilidade de uma aplicação como a capacidade da equipe de desenvolvimento para adicionar recursos, corrigir bugs ou mudar o design. Sem o mecanismo de feedback rápido dos testes, estes processos tornam-se arriscados e demorados.

Testes de integração funcional: Testes unitários são similares aos resultados obtidos da construção incremental: feedback rápido em troca do aumento do risco inerente a não testar os fluxos de trabalho completos no sistema. Testes de integração são mais similares a construções totais dessa forma: coletamos o feedback de maior qualidade ao custo de ser mais lento. Configurar e executar testes pode consumir tempo, mas eventualmente eles fornecem uma visão melhor do desempenho do sistema.

Às vezes, tentamos encurtar os tempos, isolando vários aspectos do sistema, a fim de acelerar o feedback. Então podemos querer simular a operação do navegador e executar os fluxos de trabalho sob a Interface do Usuário (UI), incluindo o código do banco de dados. Ou podemos querer executar os testes em uma Interface Gráfica do Usuário (GUI), mas sem afetar o banco de dados, jogando com a equilíbrio entre a qualidade e a velocidade de feedback.

Testes de comunicação: Embora esse seja um caso especial de testes de integração, testes de comunicação requerem uma menção especial e uma história pessoal: Uma década atrás, minha equipe estava desenvolvendo um software para um excelente hardware. A comunicação era baseada em TCP e UDP. O problema era que o hardware ainda não tinha sido construído. Claro que poderíamos ter esperado ele chegar, mas queríamos fazer progresso. Decidimos a estrutura e informações da mensagem, link de comunicação e resumindo, e manipulação de erros para construir um simulador de rede. Na época não era automatizado, era uma aplicação exibindo qual informação foi recebida, e poderia enviar mensagens de volta para nosso software se requisitado. Depois adicionamos algumas automatizações para diferentes cenários, como troca de mensagens.

Ter um simulador não só acelerou o desenvolvimento e a integração - nos deu feedback sobre como foi desenvolvido o componente de comunicação, notou quando algo estava quebrado e também foi usado como uma ferramenta de referência.

Requisitos não funcionais: Era uma vez, tínhamos somente que nos preocupar com a qualidade. No entanto, percorremos um longo caminho, e hoje temos mais algumas preocupações, como:

  • Extensibilidade: Alguns frameworks são projetados para serem estendidos e customizados. Geralmente fornecemos aos usuários APIs que permitem estender a funcionalidade de forma que não previmos. Quando queremos tornar nosso sistema extensível, construímos simuladores (e as vezes componentes reais) que usam a extensibilidade e verificamos se funciona.
  • Segurança: Às vezes temos requisitos de segurança rígidos para nossas aplicações, mas na maioria das vezes a segurança é um adendo e o nível de dificuldade a ser feito é determinado unicamente pelo desenvolvedor individual. Podemos fazer avaliação das ameaças, utilizando ferramentas de análise estática de código ou tendo profissionais de fora avaliando a aplicação. Infelizmente varreduras de segurança completas só podem ser realizadas em ambientes de produção. A menos que tais ambientes existam em um ambiente de testes, significa que os testes aconteceram no último minuto em servidores de produção.
  • Escalabilidade e desempenho: Especialmente com servidores de aplicações, precisamos avaliar a capacidade de nossa aplicação, não somente em responder grandes quantidades de requisições, mas também quanto ele pode executar quando os pedidos crescerem ainda mais. Usamos ferramentas para testes de estresse do sistema, que fornece feedback para verificarmos como o sistema está se comportando. Mais uma vez, preferimos saber com antecedência, de modo a realizar estes testes em um sistema isolado, em vez de nos servidores, que afetam os usuários reais.
  • Disponibilidade e confiabilidade: O desempenho do sistema é importante, mas a disponibilidade para uma grande quantidade de usuários também. Além disso, gostaríamos de avaliar a capacidade da aplicação de resistir e se recuperar de desligamentos. Usamos ferramentas de estresse para verificarmos o que acontece em servidores isolados para obter feedback no comportamento da nossa aplicação para esses casos.
  • Portabilidade: No mundo móvel, gostaríamos de testar nossa aplicação em vários dispositivos. Cada um pode ter um diferente sistema operacional, memória, resolução e capacidades. A capacidade de testar em vários dispositivos torna-se um desafio a cada novo dispositivo que chega ao mercado. Enquanto continuamos lutando em como fazer isso efetivamente no curto período de tempo que temos; estamos indo na direção de emuladores. Emuladores de software substituem dispositivos físicos, e fazem com que nossas aplicações funcionem em vários dispositivos.

Experiência do usuário: Em última análise, não há substitutos para usuários humanos. Aqui é aonde os testadores entram. Testadores fornecem a voz do cliente, respondendo questões como: Isso é útil? Posso alcançar meus objetivos? Aqui é aonde testamos o sistema realmente.

Enquanto o resto dos testes é automatizado, testes manuais exploratórios é a última parte do quebra-cabeça. Quando os testadores aprovam, é hora do go live.

Conclusão

O desenvolvimento de produtos é complexo e arriscado. Queremos ter certeza que estamos construindo as funcionalidades certas, garantir que funcionem corretamente, e preparar a aplicação para o desastre e sucesso. Com a compreensão de que quanto antes obtermos o feedback melhor, mais e mais aspectos podem ser testados antes de publicarmos em produção para obtermos nossa resposta: Sim, ele está pronto.

Sobre o autor

Gil Zilberfeld tem desenvolvido software desde criança. Com vinte anos de desenvolvimento de software comercial, ele tem vasta experiência em metodologias e práticas de software. Gil é o gerente de produto na Typemock, trabalhando como parte de uma equipe ágil em uma empresa ágil, criando ferramentas para desenvolvedores agéis. Ele promove testes unitários e outras práticas de design, métodos agéis práticos e algumas ferramentas incrivelmente legais. Além de seus webinars on-line mensais, Gil também fala em conferências internacionais sobre testes unitários, TDD e práticas ágeis e comunicação. E no seu tempo livre, ele atira em zumbis para se divertir. Gil escreve em seu blog sobre diferentes temas ágeis, incluindo: processos, comunicação e testes unitários.

Olá visitante

Você precisa cadastrar-se no InfoQ Brasil ou para enviar comentários. Há muitas vantagens em se cadastrar.

Obtenha o máximo da experiência do InfoQ Brasil.

Dê sua opinião

HTML é permitido: a,b,br,blockquote,i,li,pre,u,ul,p

Receber mensagens dessa discussão
Comentários da comunidade

HTML é permitido: a,b,br,blockquote,i,li,pre,u,ul,p

Receber mensagens dessa discussão

HTML é permitido: a,b,br,blockquote,i,li,pre,u,ul,p

Receber mensagens dessa discussão

Dê sua opinião

Conteúdo educacional

Feedback geral
Bugs
Publicidade
Editorial
InfoQ Brasil e todo o seu conteúdo: todos os direitos reservados. © 2006-2014 C4Media Inc.
Política de privacidade
BT