# Apostila Teste de Software - Coti Informática ## Tipos de Testes: ### Teste de caixa-preta: Seu objetivo é descobrir situações em que o software não se comporta de acordo com as suas especificações, sem se preocupar com os seus aspectos estruturais. Deve ser derivada de uma série de condições de entrada para que o programa seja testado com foco em seus requisitos funcionais, sendo que essas entradas podem ser válidas ou não. O analista não tem acesso ao código fonte e desconhece a estrutura interna do sistema. É também conhecido como teste funcional, pois é baseado nos requisitos funcionais do software. O foco, nesse caso, é nos requisitos da aplicação, ou seja, nas ações que ela deve desempenhar. Para mostrar quais problemas que esse tipo de teste rastreia, podemos citar alguns exemplos: * Data de nascimento preenchida com data futura; * Campos de preenchimento obrigatório que não são validados; * Utilizar números negativos em campos tipo valor a pagar; * Botões que não executam as ações devidas; Enfim, todo tipo de falha funcional, ou seja, falhas que contrariam os requisitos da aplicação. Há que se destacar, contudo, que existe um elemento comum aos dois tipos de teste. Tanto no teste de caixa branca quanto no teste de caixa preta, o analista não sabe qual será o comportamento da aplicação ou do alvo de teste em uma determinada situação. A imprevisibilidade de resultados é comum aos dois casos. ### Teste de caixa-branca: Testa cada caminho no software pelo menos uma vez utilizando técnicas específicas para executar decisões lógicas e ciclos em seus limites operacionais, assegurando, assim, a validade de suas estruturas de dados. O analista tem acesso ao código fonte, conhece a estrutura interna do produto sendo analisado e possibilita que sejam escolhidas partes específicas de um componente para serem avaliadas. Esse tipo de teste, também conhecido como teste estrutural, é projetado em função da estrutura do componente e permite uma averiguação mais precisa do comportamento dessa estrutura. Perceba que o acesso ao código facilita o isolamento de uma função ou ação, o que ajuda na análise comportamental das mesmas. ### Teste de unidade: O teste unitário é focado nos menores blocos ou unidades de um sistema e tem o objetivo de facilitar a depuração e apresentar um paralelismo no processo de teste, executando o teste em vários módulos simultaneamente. É considerado como um auxílio para a codificação do software, podendo ser projetado até mesmo antes do código fonte, pois, através de informações do projeto, podem ser estabelecidos casos de teste que devem ser ligados a um conjunto de resultados aguardados. Os testes de unidade instituem um escopo restrito no qual se focalizam as estruturas de dados e a lógica interna de processamento; ### Teste de integração: Ao integrar os componentes ou unidades, deve ser verificado se trabalham corretamente em conjunto, com os dados exatos (entrada e saída) e no tempo esperado. Devido à complexidade de algumas interações, a localização dos erros pode se tornar um problema, que pode ser resolvido com a utilização de uma abordagem incremental, isto é, integrando um conjunto mínimo de componentes e testando-os até que todos estejam devidamente integrados; ### Teste de validação: Logo após o término dos testes de unidade e integração, se inicia o teste de validação, que consiste em um conjunto de testes que deve comprovar a conformidade com os requisitos e se as características e especificações do produto estão de acordo com o esperado, tendo como foco as operações que são visíveis ao usuário final; ### Teste de sistema: O software é somente uma das partes de um sistema computacional e o teste de sistema reúne uma série de testes que tem o objetivo de exercitar todas as partes do sistema, obtendo a garantia de que todos seus elementos funcionam adequadamente. Existem alguns testes específicos que fazem parte do teste de sistema, sendo os mais utilizados e eficientes os seguintes: recuperação, segurança, esforço, desempenho e disponibilidade. ### Teste do Desenvolvedor O Teste do Desenvolvedor denota os aspectos de design e implementação de teste mais apropriados para a equipe de desenvolvedores que projetou e implementou o software. Faz contraste com o Teste Independente. Na maioria dos casos, a execução do teste ocorrerá inicialmente com o grupo de teste do desenvolvedor que projetou e implementou o teste, mas os desenvolvedores criam seus testes de maneira que fiquem disponíveis aos grupos de teste independente para execução. Tradicionalmente, o teste do desenvolvedor foi projetado principalmente em termos de teste unitário, com níveis variáveis de ênfase no teste de integração—dependendo muito da cultura e outras questões contextuais—com ênfase menos freqüente em outros aspectos do teste. Essa abordagem tradicional apresenta riscos à qualidade do software nessas importantes questões de teste, que geralmente surgem na fronteira dessas distinções e costumam ser ignoradas pelos diferentes grupos destinados a enfatizar cada "nível". A melhor abordagem consiste em dividir o esforço de trabalho para que haja uma sobreposição planejada. A natureza exata dessa sobreposição baseia-se nas necessidades do projeto individual. É recomendável criar um ambiente em que o desenvolvedor e os testadores independentes compartilhem uma única visão de qualidade. ### Teste Independente e dos Envolvidos : O Teste Independente denota o design e a implementação de teste mais apropriados para alguém independente da equipe de desenvolvedores. Essa distinção pode ser considerada um superconjunto que inclui Verificação Independente & Validação. Na maioria dos casos, a execução do teste ocorrerá inicialmente com o grupo de teste independente que projetou e implementou o teste, mas os testadores independentes devem criar seus testes de maneira que fiquem disponíveis aos grupos de teste do desenvolvedor para execução. Uma visão alternativa desse teste independente é que ele representa o teste realizado com base nas necessidades e problemas de vários envolvidos, por isso é chamado de Teste dos Envolvidos. Essa é uma distinção importante: ajuda a incluir um conjunto de problemas do envolvido maior que o conjunto considerado tradicionalmente como, por exemplo, equipe de suporte técnico, instrutores técnicos, equipe de vendas, além de clientes e usuários finais. Como comentário final, a noção de testes do cliente do XP está relacionada a essa categorização de teste independente no RUP. ### Teste de Aceitação O teste de aceitação do "Usuário" normalmente é a ação de teste final anterior à implantação do software. O objetivo do teste de aceitação é verificar se o software está pronto e pode ser usado pelos usuários finais para executar as funções e as tarefas para as quais o software foi criado. Há outras noções de teste de "aceitação", geralmente caracterizadas por uma entrega de um grupo ou equipe para outro. Por exemplo, um teste de aceitação de build é o teste realizado para aceitar o encaminhamento de um novo build de software do desenvolvimento para o teste independente. **Operabilidade:** Implementação do software visando a qualidade e evitando qualquer impedimento na execução de algum teste; **Observabilidade:** Entradas e saídas de fácil visualização e identificação, além de acessibilidade ao código-fonte; **Controlabilidade:** Maior controle possível das variáveis e estados do software; **Decomponibilidade:** Modularização do software em unidades que possam ser tratadas e testadas de forma independente; **Simplicidade:** Construção de uma codificação padronizada e simples; Estabilidade: as alterações realizadas no software não devem tornar nenhum teste já existente inválido; devem ser pontuais e controladas. Além disso o software deve apresentar boa capacidade de recuperação de falhas; **Compreensibilidade:** A arquitetura do software é de fácil compreensão assim como sua documentação, que deve ser organizada e precisa. ### Testes de Automacao: 1. **Confiável:** O teste automatizado executa sempre os mesmos passos, enquanto o testador pode esquecer algum passo e como resultado o defeito pode não ser reproduzido ou omitido; 2. **Reutilizável:** É possível reutilizar testes em diferentes browsers e versões sem que haja a necessidade de interferência humana, além de poder ser executado cada vez que o aplicativo for alterado; 3. **Melhor Cobertura:** Testes de regressão podem cobrir a maioria dos recursos da aplicação, o que é mais difícil de ser feito manualmente dependendo do tamanho da aplicação e do tempo disponível para executá-la; 4. **Programável:** É possível utilizar linguagem de programação sofisticada para melhorar o script automatizado. Isso pode acontecer em casos como aplicações web que usam informações ocultas ou outras informações que são impossíveis ou difíceis de verificar manualmente. ## O que é BDD(Behaviour Driven Development): Behavior Driven Development (BDD ou ainda uma tradução Desenvolvimento Guiado por Comportamento) é uma técnica de desenvolvimento Ágil que encoraja colaboração entre desenvolvedores, setores de qualidade e pessoas não-técnicas ou de negócios num projeto de software. Foi originalmente concebido em 2003, por Dan North como uma resposta à Test Driven Development (Desenvolvimento Guiado por Testes), e tem se expandido bastante nos últimos anos. O foco em BDD é a linguagem e interações usadas no processo de desenvolvimento de software. Desenvolvedores que usam BDD (Behavior-Driven developers) usam sua língua nativa em combinação com a linguagem ubíqua (ubiquitous language) usada no processo de desenvolvimento de software. Isso permite que os desenvolvedores foquem em por quê o código deve ser criado, ao invés de detalhes técnicos, e minimiza traduções entre linguagem técnica na qual o código é escrito e outras linguagens de domínio, usuários, clientes, gerência do projeto, etc. Dan North criou o primeiro framework de BDD, JBehave, em Java, seguido de um framework em Ruby a nível de história chamado RBehave, o qual foi depois incorporado ao projeto RSpec. Ele também trabalhou com David Chelimsky, Aslak Hellesøy e outros para desenvolver o framework RSpec e também escrever "The RSpec Book: Behaviour Driven Development with RSpec, **Cucumber**, and Friends". O primeiro framework baseado em histórias no RSpec foi posteriormente substituído pelo **Cucumber**, desenvolvido principalmente por Alask Hellesøy. ### Práticas de BDD As práticas de BDD incluem: * Envolver as partes interessadas no processo através de Outside-in Development (Desenvolvimento de Fora pra Dentro) * Usar exemplos para descrever o comportamento de uma aplicação ou unidades de código * Automatizar os exemplos para prover um feedback rápido e testes de regressão * Usar deve (should em inglês) na hora de descrever o comportamento de software para ajudar esclarecer responsabilidades e permitir que funcionalidades do software sejam questionadas * Usar dublês de teste (mocks, stubs, fakes, dummies, spies) para auxiliar na colaboração entre módulos e códigos que ainda não foram escritos ### Desenvolvimento de Fora pra Dentro (Outside-In Development) **BDD** é guiado pelos valores de negócios; que é o benefício trazido para o negócio no qual a aplicação está sendo produzida. A única maneira na qual o benefício pode ser percebido é através de interfaces de usuário para a aplicação, comumente (mas nem sempre) a interface gráfica de usuário. Da mesma maneira, cada trecho de código, começando com a interface de usuário, pode ser considerado como sendo um cliente de outros módulos de código no qual a interface é utilizada. Cada elemento de código provê algum comportamento, o qual em colaboração com outros elementos provê o comportamento da aplicação. A primeira parte de código de produção que os desenvolvedores que usam **BDD** implementam é a interface de usuário, pois dessa maneira os desenvolvedores podem se beneficiar com um feedback rápido para saber se a interface está adequada ou não. Através de código, e usando princípios de design e refatoração, desenvolvedores descobrem colaboradores para a interface de usuário, e posteriormente para cada unidade de código. Isso os ajuda a aderirem o princípio de YAGNI, desde que cada trecho de código de produção é requerido pelos negócios ou por outro trecho de código já escrito. **BDD** serve para criar testes e integrar regras de negócios com a linguagem de programação, focando no comportamento do software. **Behaviour Driven Development (ou BDD).** Mostraremos com exemplos práticos como BDD encoraja a colaboração entre desenvolvedores, setores de qualidade e pessoas de negócios em um projeto de software. Neste ciclo, o sistema passa a maior parte do tempo sofrendo alterações. E estas manutenções, sejam elas corretivas ou não, podem melhorar ou piorar o sistema, dependendo da forma que forem implementadas. Pensando neste e em outros problemas, Kent Beck apresentou ao mundo em 2003, através do seu livro “Test-Driven Development”, uma técnica para criar sistemas baseados em testes que visa garantir a qualidade e a funcionalidade do software durante este ciclo. Embora TDD seja uma técnica testada e aprovada por grandes desenvolvedores ágeis, muitas equipes de desenvolvimento ainda caem em algumas armadilhas e mal-entendidos do tipo: por onde começar, o que testar e o que não testar. Isto sem falar que quem escreve os testes são os desenvolvedores, mas quando a equipe de qualidade vai testar, ela se preocupa com o comportamento do sistema e não com os testes unitários. Desta forma, não há comunicação eficiente entre as duas equipes no nível de código. ## Exemplos: ### Exemplo1: Dado: Quais pré-condições devem ser verdadeiras para que eu execute o teste? Quando: Qual ação será executada no sistema que fornecerá o resultado validado? Então: De acordo com a ação disparada qual o resultado esperado? Também podemos utilizar a palavra chave E, quando for necessário adicionar uma sentença positiva, seja para Dado, Quando ou Então. ### Exemplo2: Dado: que sou uma correntista E: tenho R$ 500,00 de saldo na minha conta Quando: eu solicitar um saque de R$ 600,00 E: possuir valor de cheque especial disponível em minha conta Então: devo receber o valor de R$ 600,00 E: minha conta deve ficar com saldo em R$ 100,00 negativos :arrow_right: E o passo a passo? :arrow_right: É necessário? Perceba que já temos na nossa documentação o critério de aceite com a regra de negócio, o contexto com as pré-condições do nosso teste, o cenário que será validado e qual o dado de entrada que junto com uma ação minha disparará um resultado que será positivo ou negativo dependendo do critério de aceite. ### Exemplo 3: Critério de Aceite: quando o usuário acessar a tela inicial do Facebook deverá ser apresentado os campos para novo cadastro e após preenchê-los e clicar no botão “Criar Conta” uma nova conta no Facebook com os dados informados deverá ser criada. Contexto: usuário deve possuir uma conta de e-mail ou número de celular. Cenário: cadastro de nova conta no Facebook Dado: que estou na tela inicial do Facebook Quando: eu preencher os campos de cadastro E: clicar no botão “Criar conta” Então: a mensagem “Conta cadastrada com sucesso” deverá ser apresentada E: serei redirecionado para a página inicial da minha conta no Facebook Perceba que não especificamos passo a passo o que deve ser feito e sim o comportamento de uma história dentro do sistema. Uma boa prática é levantarmos os cenários que serão validados dentro do projeto e então estruturarmos eles utilizando a semântica BDD antes da reunião de planejamento. Dessa forma os cenários podem discutidos com a equipe e apresentados ao Product Owner para garantir que estes estão de acordo com as especificações do escopo. Para entender melhor sobre planejamento de testes clique aqui. Boas Práticas: Os casos devem descrever um comportamento e não um passo a passo; Precisam seguir uma linguagem ubíqua, ou seja, qualquer pessoa que ler entenderá o objetivo; O time integrante do projeto deve ser envolvido no refinamento dos casos; Todos os cenários devem ser independentes; Os casos devem ser validados com o Product Owner **Conclusão:** A escrita de casos de testes é um processo importante na nossa área, pois este provê um documento com todos os cenários de negócio que serão exercitados durante o projeto. Porém, gastamos muito tempo na criação desses documentos aumentando a sua complexidade em termos de manutenção, entendimento, etc. Na era ágil em que estamos desperdício de tempo quase chega a ser um pecado e portanto buscamos aplicar técnicas que nos ajudam a diminuir o tempo das tarefas cotidianas mantendo ou aumentando a qualidade das mesmas. O BDD é uma técnica que inicialmente foi aplicada somente para testes automatizados, mas que pode perfeitamente ser aplicada em testes funcionais. Com a escrita de testes funcionais utilizando semântica BDD conseguimos criar um caso de teste muito mais claro, objetivo e enxuto nos dando muito mais tempo para análise de cobertura dos testes e consequentemente nos dando a oportunidade de melhorar a qualidade do produto entregue.   ## Caso de Teste: Lançamentos de notas e faltas • Condição para o teste: Abrir o formulário Notas e Faltas • Procedimentos Realizados • Resultados Esperados 1. Acessar o menu Notas e Faltas. Abrir a tela Notas e Faltas. 2. Selecionar uma turma Habilitar os campos Período e Disciplina 3. Informar o período de referência. Não prosseguir se for um período inválido. 4. Selecionar uma disciplina. Habilitar o campo Aluno. 5. Selecionar um aluno. Se houver dados cadastrados, habilita a alteração, senão faz a inclusão dos valores para Nota e Faltas. 6. Informar os valores para Nota e Faltas. Aceitar somente dados do tipo decimal e inteiro, respectivamente, senão exibe advertência. 7. Confirmar a alteração ou inclusão, clicando em salvar. Gravar os dados no banco e limpar os campos da tela. 8. Repetir os passos de 2 a 6 e descartar o lançamento clicando no botão cancelar. Não gravar nenhum dado no banco e limpar os campos da tela. 9. Clicar no botão Sair. Fechar a tela de Notas e Faltas   ## BDD no Scrum 1) Uma pessoa pode assumir mais de uma função, ou Papéis diferentes em momentos diferentes. **(Abu):** Em Scrum as equipes são generalistas, todos os integrantes da equipe devem e podem executar vários papeis, conforme a necessidade do projeto 2) Um testador, desenvolvedor e perito em domínio se reúnem com o dono do produto (Product Owner) para entendimento das histórias. Gradualmente as historias são decompostas e quebradas em um conjunto de especificações mais simples. **(Abu):** Quase sempre as historias possuem mais de uma responsabilidade, esta sobrecarga de responsabilidade é o que nos chamamos de “Temas de Historia”. Uma historia com características de “Temas” devem ser quebradas em historias menores. O ideal é que uma historia possua apenas uma responsabilidade. Uma historia com apenas uma responsabilidade pode ser decomposta em “Tarefas” e executadas pela equipe. 3) O dono do produto (Product Owner) decide quais as historias vão ser trabalhadas e detalhadas na iteração. O escopo fechado da iteração não pode ser modificado. **(Abu):** Em Scrum nos falamos que no planejamento da Sprint o Product Owner escolhe os Itens de Backlog que devem ser executados na Sprint. Os itens escolhidos pelo product Owner e comprometidos de serem entregues pela equipe não podem ser modificados. 4) Todos os comportamentos esquecidos pela equipe na iteração atual de trabalho, deve ser deixado para a próxima iteração. Estes comportamentos devem ser priorizados com o Product Owner para a definição da iteração correta de sua execução. **(Abu):** Dentro da execução da Sprint vão ser encontrados novos comportamentos que a equipe não conseguiu identificar na reunião de planejamento da Sprint. Neste caso, estes comportamentos devem ser colocados como novos Itens de Backlog e no momento correto (Planejamento da Sprint) priorizado pelo Product Owner, para ser executado. Não devemos colocar mais Itens de Backlog numa Sprint que já esta negociada, pois corre o risco de não poder ser entregue o que já foi comprometido. 5) Desenvolvimento dos instrumentos de especificações, criação de erros e implementação das funcionalidades. **(Abu):** Neste item a equipe desenvolve os artefatos necessários para o sistema, cria os testes (TDD) para que eles falhem e desenvolvem as funcionalidades esperadas pelo software. Esta é uma técnica de desenvolvimento, onde após os testes terem falhados, nos criamos as funcionalidades que permitam com que os testes cheguem ao resultado esperado. Um desenvolvimento focado a teste faz com que nosso código fique mais simples e principalmente coeso. Eu gosto muito dos testes, eles permitem a identificação e implementação de classes e métodos mais simples. 6) Depois que todos os testes forem passando, a história pode ser demonstrada ao dono do produto (Product Owner). Deve ser realizado testes manuais também. **(Abu):** Em Scrum nos falamos que o Product Owner sempre esta presente e por estar presente ele sabe o que esta sendo entregue ou não. Mas mesmo com a sua presença nos temos uma reunião de Sprint Review, onde nesta reunião é oficializado o que esta sendo entregue e o que não foi possível de ser entregue, bem como a justificativa dos problemas encontrados. Mas o termo “Done” é definido junto com o Product Owner e deve fazer parte do conceito de “pronto” a execução e aprovação de todas as funcionalidades pelos testes. Também deve ser realizado testes manuais, que permitem a avaliação do produto como um “todo”. Fica a minha dica de utilização do software “Selenium” junto com o teste manual, para que este teste manual se torne um teste automatizado. ## Teste Unitario ### Introdução O teste unitário é implementado com base no menor elemento testável (unidades) do software e implica em testar a estrutura interna (como fluxo lógico e de dados), a função da unidade e os comportamentos observáveis. O design e a implementação de testes com ênfase na estrutura interna de uma unidade se baseiam no conhecimento da implementação da unidade (abordagem caixa branca). No entanto, o design e a implementação de testes com a finalidade de verificar os comportamentos observáveis e as funções da unidade não se baseiam no conhecimento da implementação; por isso, são conhecidas como abordagem caixa preta. As duas abordagens são usadas para projetar e implementar os diferentes tipos de testes (consulte Conceitos: Tipo de Testes) necessários para testar as unidades de forma completa e correta. Além das considerações individuais de cada tipo de teste e das duas abordagens mencionadas aqui, existem várias considerações de design e de implementação que se aplicam somente ao teste unitário, a saber: * Operações Herdadas * Classes Abstratas * Polimorfismo Informações adicionais sobre esses tópicos são fornecidas nas seções a seguir. ### Abordagem de Teste Caixa Branca Uma abordagem de teste caixa branca deve ser realizada para verificar a estrutura interna de uma unidade. Teoricamente, cada caminho possível ao longo do código deve ser testado, mas isso só pode ser feito em unidades muito simples. Você deve testar cada caminho de decisão-a-decisão (caminho DD) pelo menos uma vez, pois assim estará executando todas as instruções ao menos uma vez. Em geral, uma decisão é uma instrução if, e um caminho DD é aquele que une duas decisões. Para obter esse nível de cobertura de teste, é recomendável que você escolha os dados de teste de modo que cada decisão seja avaliada de todas as formas possíveis. Use as ferramentas de cobertura de código para identificar o código não experimentado pelo teste caixa branca. O teste de confiabilidade deve ser realizado simultaneamente com o teste caixa branca. ### Abordagem de Teste da Caixa Preta A finalidade de um teste da caixa preta é verificar a função especificada e o comportamento observável da unidade sem que seja necessário saber como a unidade os implementa. Os testes caixa preta se concentram e se baseiam na entrada e saída da unidade. A geração de testes unitários com base na abordagem da caixa preta utiliza os argumentos de entrada e saída das operações da unidade e/ou o estado de saída para avaliação. Por exemplo, a operação pode incluir um algoritmo (requerendo dois valores como entrada e retornando um terceiro como saída) ou iniciar a alteração no estado de um objeto ou componente, como a inclusão ou exclusão de um registro de banco de dados. Ambos devem ser testados por completo. Para testar uma operação, você deve obter casos de teste suficientes para verificar se: * para cada valor aceito utilizado como entrada, um valor apropriado foi retornado pela operação * para cada valor não aceito utilizado como entrada, somente um valor apropriado foi retornado pela operação * para cada estado de entrada válido, ocorre um estado de saída apropriado * para cada estado de entrada inválido, ocorre um estado de saída apropriado Use as ferramentas de cobertura de código para identificar o código não experimentado pelo teste caixa branca. O teste de confiabilidade deve ser realizado simultaneamente com o teste caixa preta. ## Para baixar e instalar: * [JDK 8](https://www.oracle.com/technetwork/pt/java/javase/downloads/jdk8-downloads-2133151.html) :point_left: clique no link * [Chrome Driver](http://chromedriver.chromium.org/downloads) :point_left: clique no link * [Eclipse IDE](https://www.eclipse.org/downloads/packages/release/photon) :point_left: clique no link * [Postman](https://www.getpostman.com/downloads/) :point_left: clique no link ### Chrome Driver É um arquivo executavel que precisamos obter e configurar no programa para que o selenium consiga "controlar" o navegador Google Chrome. Estes drivers tambem existem para outros navegadores como Firefox, Internet Explorer, etc... ## JUNIT Test https://junit.org/junit5/ ![](https://i.imgur.com/kO2sOlH.png) É um framework open-source para construção de testes automatizados em Java, hospedado no Github, em que se verifica as funcionalidades de classes e seus métodos. Além disso, podemos automatizar também a execução de todos os testes de forma que quando há uma nova versão estável do sistema, o framework execute todos os testes para garantir a integridade e estabilidade do que foi desenvolvido. O **jUnit** funciona com base em anotações (Annotations) e essas anotações indicam se um método é de teste ou não, se um método deve ser executado antes da classe e/ou depois da classe. As anotações também indicam se o teste deve ou não ser ignorado e se a classe em questão é uma suíte de teste, ou seja, se a partir desta classe é disparada a execução das demais classes de teste, entre outras anotações menos utilizadas. > Toda classe de teste deve ser criada com a palavra Test no final.[color=red] O teste é uma das partes mais importantes para a garantia da qualidade no desenvolvimento de um software. Testar é assegurar que todas as funcionalidades esperadas estão implementadas corretamente. Testar é descobrir falhas/bugs para que sejam corrigidas até que a versão final atinja a qualidade desejada. Testar é validar se uma parte do software está pronta para ser disponibilizada em produção. ### Testando funcionalidades Para testar seu código em condições específicas, utilizamos o método assert, fornecido pelo framework ou outra estrutura de declaração, normalmente chamadas de asserts ou assert statements. Essa estrutura permite que especifiquemos uma mensagem de erro e comparar o resultado real do teste com o resultado esperado. Temos vários tipos de asserts que podem ser implementados: ![](https://i.imgur.com/z9EHe5K.png) * **fail**([message]): pode ser usado para verificar se uma determinada parte do código não é atingida ou para ter um teste com falha antes que o código de teste seja implementado. O parâmetro da mensagem é opcional. * **assertTrue**([message,] boolean condition): verifica se a condição booleana é verdadeira. * **assertFalse**([message,] boolean condition): verifica se a condição booleana é falsa. * **assertEquals**([message,] expected, actual): testa se dois valores (esperado e atual) são os mesmos. No caso de arrays, a verificação é em relação à referência e não ao conteúdo. * **assertEquals**([message,] expected, actual, tolerance): testa se dois valores float ou double correspondem. A tolerância é o número de casas decimais que devem ser consideradas na comparação. * **assertNull**([message,] object): verifica se o objeto é nulo. * **assertNotNull**([message,] object): verifica se o objeto não é nulo. * **assertSame**([message,] expected, actual): verifica se ambas as variáveis se referem ao mesmo objeto. * **assertNotSame**([message,] expected, actual): verifica se ambas as variáveis se referem a objetos diferentes. ### Anotações |Anotação| Descrição| |----|-----| |@Test|Indica que um método é um método de teste. Diferentemente da @Testanotação do JUnit 4 , essa anotação não declara nenhum atributo, pois as extensões de teste no JUnit Jupiter operam com base em suas próprias anotações dedicadas. Tais métodos são herdados, a menos que sejam substituídos.| |@ParameterizedTest|Indica que um método é um teste parametrizado. Tais métodos são herdados, a menos que sejam substituídos.| |@RepeatedTest|Indica que um método é um modelo de teste para um teste repetido. Tais métodos são herdados, a menos que sejam substituídos.| |@TestFactory|Indica que um método é uma fábrica de testes para testes dinâmicos. Tais métodos são herdados, a menos que sejam substituídos.| |@TestTemplate| Indica que um método é um modelo para casos de teste projetados para serem chamados várias vezes, dependendo do número de contextos de chamada retornados pelos provedores registrados. Tais métodos são herdados, a menos que sejam substituídos.| |@TestMethodOrder|Usado para configurar a ordem de execução do método de teste para a classe de teste anotada; semelhante ao JUnit 4 @FixMethodOrder. Tais anotações são herdadas.| |@TestInstance|Usado para configurar o ciclo de vida da instância de teste para a classe de teste anotada. Tais anotações são herdadas.| |@DisplayName|Declara um nome de exibição personalizado para a classe ou método de teste. Tais anotações não são herdadas.| |@DisplayNameGeneration|Declara um gerador de nome para exibição personalizado para a classe de teste. Tais anotações são herdadas.| |@BeforeEach|Denota que o método anotado deve ser executado antes de cada @Test , @RepeatedTest, @ParameterizedTest, ou @TestFactorymétodo na classe atual; análogo ao JUnit 4 @Before. Tais métodos são herdados, a menos que sejam substituídos.| |@AfterEach| Denota que o método anotado deve ser executado após cada @Test , @RepeatedTest, @ParameterizedTest, ou @TestFactorymétodo na classe atual; análogo ao JUnit 4 @After. Tais métodos são herdados, a menos que sejam substituídos.| |@BeforeAll|Denota que o método anotado deve ser executado antes de tudo @Test , @RepeatedTest, @ParameterizedTest, e @TestFactorymétodos na classe atual; análogo ao JUnit 4 @BeforeClass. Esses métodos são herdados (a menos que estejam ocultos ou substituídos ) e devem ser static(a menos que o ciclo de vida da instância de teste "por classe" seja usado).| |@AfterAll|Denota que o método anotado deve ser executado depois de tudo @Test , @RepeatedTest, @ParameterizedTest, e @TestFactorymétodos na classe atual; análogo ao JUnit 4 @AfterClass. Esses métodos são herdados (a menos que estejam ocultos ou substituídos ) e devem ser static(a menos que o ciclo de vida da instância de teste "por classe" seja usado).| |@Nested|Indica que a classe anotada é uma classe de teste aninhada não estática . @BeforeAlle @AfterAllmétodos não podem ser usados diretamente em uma @Nestedclasse de teste, a menos que o ciclo de vida da instância de teste "por classe" seja usado. Tais anotações não são herdadas .| |@Tag|Usado para declarar tags para testes de filtragem , no nível da classe ou do método; análogo aos grupos de teste em TestNG ou Categorias na JUnit 4. Essas anotações são herdadas no nível da classe, mas não no nível do método.| |@Disabled|Usado para desativar uma classe ou método de teste; análogo ao JUnit 4 @Ignore. Tais anotações não são herdadas.| |@Timeout|Usado para falhar em um teste, fábrica de teste, modelo de teste ou método de ciclo de vida se sua execução exceder uma determinada duração. Tais anotações são herdadas| |@ExtendWith|Usado para registrar extensões declarativamente . Tais anotações são herdadas.| |@RegisterExtension|Usado para registrar extensões programaticamente por meio de campos. Tais campos são herdados, a menos que estejam sombreados.| |@TempDir|Usado para fornecer um diretório temporário via injeção de campo ou injeção de parâmetro em um método de ciclo de vida ou método de teste; localizado na org.junit.jupiter.api.ioembalagem.| ### Suites Case A principal função de um test suíte é rodar vários test cases ao “mesmo tempo”, na verdade trata-se de uma classe que contém métodos que disparam a execução de vários test cases. O Eclipse também disponibiliza de maneira simples um assistente para a criação de classes de testes suítes. ## Cucumber ![](https://i.imgur.com/3z1mLdN.png) O **Cucumber** é uma ferramenta que suporta Behavior Driven Development (BDD), que consiste em descrever o comportamento de um usuário. Dessa forma, as necessidades reais do usuário são descritas. **Cucumber** é usado para descrever o valor do negócio em uma linguagem natural, por isso permite que equipes de desenvolvimento de software descrevam como o software deve se comportar em texto simples, escrevendo especificações através de exemplos. Uma boa vantagem de escrever especificações com **Cucumber** é que qualquer um na equipe consegue ler e entender as especificações em texto simples - de pessoas de negócios a desenvolvedores de software. Além disso, ele ajuda a obter feedback dos stakeholders de negócios sobre se a equipe vai construir a coisa certa antes mesmo de começar. Ele também ajuda a equipe a fazer um esforço intencional para desenvolver uma linguagem ubíqua compartilhada para falar sobre o sistema. ### Vantagens: Outra vantagem é que a especificação é uma documentação viva, porque apesar de ser escrita em texto simples, origina testes automatizados executáveis, como você verá mais adiante no artigo. A estrutura que o **Cucumber** usa para as especificações é o formato `Given/When/Then` em conformidade com gramática da linguagem Gherkin. A parte `Given` (Dado) descreve uma pré-condição existente do estado de software antes de começar o comportamento que você está especificando. A seção `When` (Quando) é o próprio comportamento. O `Then` (Então) descreve o resultado esperado do comportamento. Por exemplo: Dado que me inscrevi para Loja de Livros Online, quando eu acesso a loja com minhas credenciais, então vejo uma mensagem "Bem-vinda à Loja de Livros Online!". Continue lendo para encontrar mais exemplos. ### Definir o valor do negócio Seguem alguns princípios de BDD utilizados em **Cucumber** para de escrever testes automatizados com alto valor de negócio. É útil escrevê-los em texto puro antes de implementá-los e garantir que as partes interessadas no negócio dêem feedback sobre se os testes descrevem o comportamento correto do software. Se as partes interessadas no negócio derem o feedback após o comportamento do software já ter sido implementado, provavelmente leva muito mais tempo para corrigir o código do que seria necessário para corrigir um texto simples que descreve o teste. Então testes automatizados escritos antes de construir o software trazem valor através da economia de bastante tempo do time de desenvolvimento de software. ![](https://i.imgur.com/0fp3Su6.png) Escrever narrativas também traz valor para o teste porque descreve em uma frase qual o motivo de implementar a funcionalidade em primeiro lugar, e ajuda a entender o sobre o que são os cenários da funcionalidade. Por exemplo: Para que eu possa identificar dinossauros, como um colecionador de ossos, eu quero acessar informações sobre os dinossauros. Outra qualidade importante em testes automatizados valiosos é que o texto simples usa um vocabulário específico do domínio do negócio para que eles sejam compreendidos por qualquer pessoa da equipe: usuários, stakeholders de negócios e o time de desenvolvimento de software. Isso traz valor para a comunicação da equipe, porque faz com que ela desenvolva uma linguagem ubíqua compartilhada para falar sobre o software e focar no negócio em vez de descrever testes usando termos técnicos que são apenas mais uma variante de uma linguagem de programação. Para ter testes automatizados com alto valor de negócio, **Cucumber** consiste em uma face de negócio e uma face de tecnologia. ![](https://i.imgur.com/K282gJ8.png) É importante escrever funcionalidades declarativas, de modo que os cenários sejam descritos como um usuário poderia descrevê-los, o que os torna altamente manuteníveis quando comparados com cenários que descrevem apenas clicar em links e preencher os campos de formulário. Por exemplo: ![](https://i.imgur.com/648607r.png) Outra dica para reduzir o custo de manutenção em cenários de **Cucumber**, é evitar passos que contêm duas ações, porque um deles pode ser reutilizável em diferentes cenários: ![](https://i.imgur.com/mRQ2Szw.png) ## Selenium WebDriver ![](https://i.imgur.com/03xWC3R.png) É uma ferramenta que simula ações do usuário em navegadores web. Mostramos como usar o **Cucumber**, juntamente com **Selenium WebDriver** para implementar testes automatizados com alto valor de negócio e de baixa manutenção. **Selenium WebDriver** simula as ações do usuário definidas pelas descrições do **Cucumber** em um browser. Ele é usado para testar automaticamente aplicações web, uma vez que conduz um browser utilizando recursos nativos de cada browser. **Selenium** ainda é movido por código, de modo que os testes automatizados são escritos em uma linguagem de programação que define as ações do usuário e controla **Selenium WebDriver**. Há muitas linguagens de programação diferentes que podem ser usadas com **Selenium WebDriver**, tais como Java, Ruby, Python e JavaScript. No entanto, existe uma linguagem ainda mais simples para descrever cenários de teste: a linguagem natural. É possível escrever testes automatizados com **Cucumber** em diferentes linguagens naturais, tais como Português e Inglês, entre mais de 40 outras línguas. Por outro lado, **Cucumber** não interage diretamente com a aplicação de software. É por isso que é normalmente utilizado em conjunto com ferramentas como o **Selenium WebDriver**. Desta forma, os testes automatizados servem como documentação, porque podem ser escritos em uma linguagem específica de um domínio e legível do ponto de vista de negócios. Eles também podem ser executáveis, porque possuem a camada do **Selenium WebDriver** rodando por trás da camada do **Cucumber**; e pode ser de fácil manutenção porque a camada do **Cucumber** não precisa saber como as ações do usuário são simuladas, já que este é o trabalho do **Selenium WebDriver**. Portanto, se a aplicação web muda a forma como o usuário interage com ela, tudo o que precisamos fazer é alterar a camada do **Selenium WebDriver** e manter a camada do **Cucumber** como estava. Para escrevermos os scripts dos testes, precisaremos entender um pouco sobre as chamadas e as classes **WebDriver** e **WebElement**, que utilizaremos nos testes. ### Vantagens * Tarefas repetidas são muito sujeitas a erro. É comum o testador ignorar ou esquecer parte do que precisa ser testado; isso não ocorre quando automatizamos, pois, os passos descritos são seguidos à risca pelo computador. Ele é obediente e nunca cansa! * A capacidade de teste do ser humano é limitada. Se hoje um testador testa 5 funcionalidades por hora, é muito provável que amanhã ele continue testando a mesma quantidade nesse intervalo de tempo. Talvez ele progrida um pouco, mas nada tão absurdo. Já a bateria de testes realizada por um computador (ou vários, pois, podemos montar um grid e paralelizar a execução) tem uma curva de crescimento muito mais acentuada. Ele é capaz de executar muito mais tarefas em menos tempo. * A regressão diminui bastante com o uso de ferramentas automatizadas. A regressão ocorre quando novas funcionalidades de um sistema fazem com que funcionalidades pré-existentes deixem de funcionar. Nos testes manuais, principalmente em grandes sistemas, a regressão ocorre com alguma frequência, pois, os testadores nem sempre conseguem testar todos os cenários possíveis. Já com os testes automatizados isso diminui consideravelmente já que ele executa SEMPRE todos os testes: tanto os das novas funcionalidades quanto os antigos. Daí, ele é capaz de pegar erros em testes antigos que podem ter sido gerados pela inclusão de novas funcionalidades. ### Chamadas * **@Before**: é executado antes de qualquer Caso de Teste, por exemplo, abrir uma página em um browser. * **@Test**: é utilizado para identificar que é Caso de Teste. * **@After**: todas as ações que estão contidas nele são executadas após cada Caso de Teste rodar; por exemplo: fechar browser. ### Como o Selenium Funciona? Os testes de aplicações web, em sua maioria, envolvem o uso de um navegador web. O **Selenium** permite simular o comportamento do usuário utilizando um navegador web. Quando utilizamos o **Selenium** para fazer testes automatizados, basicamente temos duas ferramentas para utilizar: **Selenium IDE**: é uma ferramenta que permite a rápida prototipagem de scripts de testes. É um plugin do Firefox que possibilita gravar o comportamento do usuário: página que ele acessou, textos escritos em formulários, cliques em links e botões etc. Depois de gravadas, estas ações podem ser exportadas para um script de teste em diversas linguagens de programação: Java, Python, Perl, JavaScript etc. **Selenium WebDriver**: é uma ferramenta que oferece uma API que permite a escrita de forma mais produtiva e organizada de scripts de testes. Essa é a escolha natural quando desejamos escrever testes automatizados para aplicações web utilizando o Selenium. Os exemplos desse post utilizam o WebDriver. O **Selenium WebDriver** faz chamadas diretamente ao navegador utilizando o suporte à automação nativo de cada navegador. Assim os testes escritos com o WebDriver são bastante realistas, pois, em vez de usar um engine JavaScript próprio (como era feito no Selenium 1), ele chama diretamente o navegador. ### WebDriver O **WebDriver** é a classe base do Selenium. A partir dela, podemos realizar diversas funcionalidades de navegação; por exemplo: abrir um browser, fechar um browser, fechar uma aba de um browser, entre outras. Para o nosso exemplo de script de testes, utilizaremos abrir e fechar um browser. Seguem exemplos de funções de navegação que serão utilizadas: * Abrir o browser: get(“url”); * Atualizar página: navigate().refresh(); * Fechar página: quit(); ### WebElement **WebElement** é uma classe do Selenium representando um elemento HTML. As principais operações de interação em uma página são realizadas através desta interface. Por exemplo: interações com caixas de texto, botões, links, entre outras. Dentro dessa classe, utilizarmos o método findElements no nosso primeiro test case. Este método permite localizar os elementos dentro de uma página. Porém, para localizar o elemento, precisaremos também da classe `By`, que determina o meio (ID, name, class, xpath) pelo qual o iremos encontrar. Seguem exemplos de como codificar para encontrar os elementos: * Encontrar elementos através do ID: ```java= WebElement elemento = driver.findElement(By.id(“ID do elemento”)); ``` * Encontrar elementos através no nome: ```java= WebElement elemento = driver.findElement(By.name(“nome elemento”)); ``` * Encontrar elementos através do nome da classe: ```java= WebElement element = driver.findElement(By.className(“nome classe”)); ``` Dentro desta mesma classe, utilizaremos validações de elementos, através de asserts. Exemplos de como codificar para validação dos elementos: * Validar se o elemento está exibido na página: ```java= assertTrue(topicosrecentes.isDisplayed()); ``` * Validar se o nome do elemento contém o texto: ```java= assertTrue(menusobre.getText().contains(“SOBRE”)); ``` * Validar se o nome do elemento é igual o texto: ```java= assertTrue(tagwebdriver.getText().equals(“Webdriver”)); ``` Lembrando que existem vários outros tipos de validações em Java. ## Jmeter ![](https://i.imgur.com/cYG4RLg.png) :point_right: Site: https://jmeter.apache.org/ :point_right: Download: http://mirror.nbtelecom.com.br/apache//jmeter/binaries/ ### O que é? O aplicativo Apache JMeter ™ é um software de código aberto, um aplicativo Java 100% puro, projetado para carregar o comportamento funcional do teste e medir o desempenho. Foi originalmente projetado para testar aplicativos da Web, mas foi expandido para outras funções de teste. ### O que posso fazer com isso? O Apache JMeter pode ser usado para testar o desempenho em recursos estáticos e dinâmicos, aplicativos dinâmicos da Web. Ele pode ser usado para simular uma carga pesada em um servidor, grupo de servidores, rede ou objeto para testar sua força ou analisar o desempenho geral em diferentes tipos de carga. Os recursos do Apache JMeter incluem: * Capacidade de carregar e testar o desempenho de muitos tipos diferentes de aplicativos / servidores / protocolos: * Web - HTTP, HTTPS (Java, NodeJS, PHP, ASP.NET,…) * Serviços da Web SOAP / REST * FTP * Banco de dados via JDBC * LDAP * Middleware orientado a mensagens (MOM) via JMS * Correio - SMTP (S), POP3 (S) e IMAP (S) * Comandos nativos ou scripts de shell * TCP * Objetos Java * IDE de teste completo que permite a gravação rápida do plano de teste (de navegadores ou aplicativos nativos), criação e depuração. * Modo CLI (modo de linha de comando (anteriormente chamado de Não GUI) / modo sem cabeça) para carregar o teste de qualquer sistema operacional compatível com Java (Linux, Windows, Mac OSX,…) * Um relatório HTML dinâmico completo e pronto para apresentar * Fácil correlação através da capacidade de extrair dados dos formatos de resposta mais populares, HTML , JSON , XML ou qualquer formato de texto * Portabilidade completa e 100% de pureza Java . * A estrutura completa de multiencadeamento permite amostragem simultânea por muitos encadeamentos e amostragem simultânea de diferentes funções por grupos de encadeamentos separados. * Armazenamento em cache e análise / reprodução offline dos resultados dos testes. * Núcleo altamente extensível: * Samplers conectáveis ​​permitem recursos de teste ilimitados. * Samplers com scripts (linguagens compatíveis com JSR223 como Groovy e BeanShell) * Várias estatísticas de carga podem ser escolhidas com temporizadores conectáveis . * Os plug-ins de análise e visualização de dados permitem grande extensibilidade e personalização. * As funções podem ser usadas para fornecer entrada dinâmica a um teste ou fornecer manipulação de dados. * Integração Contínua fácil através de 3 rd partido bibliotecas de código aberto para Maven, Gradle e Jenkins. ### JMeter não é um navegador O JMeter não é um navegador, ele funciona no nível do protocolo. No que diz respeito aos serviços web e serviços remotos, o JMeter parece um navegador (ou melhor, vários navegadores); no entanto, o JMeter não executa todas as ações suportadas pelos navegadores. Em particular, o JMeter não executa o Javascript encontrado nas páginas HTML. Também não processa as páginas HTML como um navegador (é possível visualizar a resposta como HTML etc.), mas os tempos não estão incluídos em nenhuma amostra e apenas uma amostra em um segmento é exibida por vez. ###### tags: `teste` `apostila`