Talvez minha pergunta seja nova, mas eu realmente não consigo entender as circunstâncias em que eu usaria junit?
Se eu escrevo aplicativos simples ou aplicativos maiores, testo-os com as System.out
instruções e isso me parece bastante fácil.
Por que criar classes de teste com JUnit, pastas desnecessárias no projeto, se ainda precisamos chamar os mesmos métodos, verificar o que eles retornam e, em seguida, temos uma sobrecarga de anotar tudo?
Por que não escrever uma classe e testá-la imediatamente com, System.out
mas não criar, classes de teste?
PS. Eu nunca trabalhei em grandes projetos, estou apenas aprendendo.
Então qual é o propósito?
java
unit-testing
junit
tdd
Artem Moskalev
fonte
fonte
Respostas:
Isso não está testando, está "olhando manualmente para a saída" (conhecida como LMAO). Mais formalmente, é conhecido como "procurando manualmente por resultados anormais" (LMFAO). (Ver nota abaixo)
Sempre que alterar o código, você deve executar o aplicativo e o LMFAO para todo o código afetado por essas alterações. Mesmo em pequenos projetos, isso é problemático e propenso a erros.
Agora dimensione até 50k, 250k, 1m LOC ou mais e o LMFAO sempre que você fizer uma alteração no código. Não é apenas desagradável, é impossível: você escalou as combinações de entradas, saídas, sinalizadores, condições e é difícil exercer todas as ramificações possíveis.
Pior ainda, LMFAO pode significar visitar páginas e páginas de aplicativos da web, executar relatórios, examinar milhões de linhas de registros em dezenas de arquivos e máquinas, ler e-mails gerados e entregues, verificar mensagens de texto, verificar o caminho de um robô, encher uma garrafa de refrigerante, agregando dados de uma centena de serviços web, verificando a trilha de auditoria de uma transação financeira ... você entendeu. "Saída" não significa algumas linhas de texto, "saída" significa comportamento agregado do sistema.
Por fim, os testes de unidade e comportamento definem o comportamento do sistema. Os testes podem ser executados por um servidor de integração contínuo e verificados quanto à correção. Claro que sim
System.out
, mas o servidor de IC não saberá se um deles está errado - e, se o fizer, são testes de unidade, e você também pode usar uma estrutura.Por melhor que pensemos que somos, os humanos não são boas estruturas de teste de unidade ou servidores de CI.
Nota: O LMAO está testando, mas em um sentido muito limitado. Não é repetível de forma significativa em todo o projeto ou como parte de um processo. É semelhante ao desenvolvimento incremental em um REPL, mas nunca formalizando esses testes incrementais.
fonte
Escrevemos testes para verificar a correção do comportamento de um programa.
Verificar a correção do comportamento de um programa, inspecionando o conteúdo das instruções de saída usando seus olhos, é um processo manual ou, mais especificamente, visual .
Você poderia argumentar que
Agora, primeiro, é ótimo que você esteja interessado em saber se o código funciona ou não corretamente. Isso é uma coisa boa. Você está à frente da curva! Infelizmente, há problemas com isso como uma abordagem.
O primeiro problema com a inspeção visual é que você sofreu um grave acidente de soldagem e nunca conseguiu verificar novamente a correção do seu código.
O segundo problema é que o par de olhos usado está fortemente acoplado ao cérebro do dono dos olhos. Se o autor do código também possui os olhos usados no processo de inspeção visual, o processo de verificação da correção depende do conhecimento sobre o programa internalizado no cérebro do inspetor visual.
É difícil para um novo par de olhos entrar e verificar a correção do código simplesmente porque eles não são associados ao cérebro do codificador original. O proprietário do segundo par de olhos terá que conversar com o autor original do código para entender completamente o código em questão. A conversa como meio de compartilhar conhecimento é notoriamente não confiável. Um ponto discutível se o codificador original não estiver disponível para os novos olhos de par. Nesse caso, o novo par de olhos precisa ler o código original.
Ler o código de outras pessoas que não é coberto por testes de unidade é mais difícil do que ler o código que possui testes de unidade associados. Na melhor das hipóteses, ler o código de outras pessoas é um trabalho complicado, na pior das hipóteses, é a tarefa mais incômoda da engenharia de software. Há uma razão pela qual os empregadores, ao anunciar vagas, destacam que um projeto é um greenfield (ou novíssimo). Escrever código do zero é mais fácil do que modificar o código existente e, assim, tornar o trabalho anunciado mais atraente para os funcionários em potencial.
Com o teste de unidade, dividimos o código em suas partes componentes. Para cada componente, organizamos nossa tenda, indicando como o programa deve se comportar . Cada teste de unidade conta uma história de como essa parte do programa deve agir em um cenário específico. Cada teste de unidade é como uma cláusula de um contrato que descreve o que deve acontecer do ponto de vista do código do cliente.
Isso significa que um novo par de olhos possui dois fios de documentação ativa e precisa sobre o código em questão.
Primeiro eles têm o próprio código, a implementação, como o código foi feito ; segundo, eles têm todo o conhecimento que o codificador original descreveu em um conjunto de declarações formais que contam a história de como esse código deve se comportar.
Os testes de unidade capturam e descrevem formalmente o conhecimento que o autor original possuía quando implementou a classe. Eles fornecem uma descrição de como essa classe se comporta quando usada por um cliente.
Você está certo ao questionar a utilidade de fazer isso, porque é possível escrever testes de unidade que são inúteis, não cobrem todo o código em questão, ficam obsoletos ou desatualizados e assim por diante. Como garantir que os testes de unidade não apenas imitem, mas melhorem o processo de um autor experiente e consciente que inspeciona visualmente as instruções de saída de seu código em tempo de execução? Escreva o teste de unidade primeiro e depois o código para fazer esse teste passar. Quando terminar, deixe que os computadores executem os testes, eles são rápidos e são ótimos em realizar tarefas repetitivas, ideais para o trabalho.
Garanta a qualidade do teste, revendo-os sempre que tocar no código que eles testam e executar os testes para cada compilação. Se um teste falhar, corrija-o imediatamente.
Automatizamos o processo de execução de testes para que sejam executados toda vez que fazemos a construção do projeto. Também automatizamos a geração de relatórios de cobertura de código que detalham qual porcentagem de código é coberta e exercida pelos testes. Nós nos esforçamos para obter altas porcentagens. Algumas empresas impedirão que as alterações de código sejam registradas no controle do código-fonte se elas não tiverem testes de unidade suficientes escritos para descrever quaisquer alterações no comportamento do código. Normalmente, um segundo par de olhos revisará as alterações de código em conjunto com o autor das alterações. O revisor passará pelas alterações para garantir que as alterações sejam compreensíveis e suficientemente cobertas pelos testes. Portanto, o processo de revisão é manual, mas quando os testes (testes de unidade e integração e possivelmente testes de aceitação do usuário) passam nesse processo de revisão manual, tornam-se parte do processo de criação automática. Eles são executados toda vez que uma alteração é registrada.integração contínua O servidor executa essa tarefa como parte do processo de construção.
Os testes executados automaticamente mantêm a integridade do comportamento do código e ajudam a impedir que futuras alterações na base de código quebrem o código .
Por fim, o fornecimento de testes permite re-fatorar agressivamente o código, pois você pode tornar grandes melhorias de código seguras, sabendo que suas alterações não quebram os testes existentes.
Há uma ressalva para o Test Driven Development e é que você precisa escrever um código para torná-lo testável. Isso envolve codificar para interfaces e usar técnicas como injeção de dependência para instanciar objetos de colaboração. Confira o trabalho de Kent Beck, que descreve muito bem o TDD. Procure codificação para interfaces e estudePadrões de design
fonte
Ao testar usando algo como System.out, você está testando apenas um pequeno subconjunto de possíveis casos de uso. Isso não é muito completo quando você lida com sistemas que podem aceitar uma quantidade quase infinita de entradas diferentes.
Os testes de unidade foram projetados para permitir a execução rápida de testes em seu aplicativo usando um conjunto muito grande e diversificado de entradas de dados diferentes. Além disso, os melhores testes de unidade também são responsáveis por casos de fronteira, como as entradas de dados que ficam bem no limite do que é considerado válido.
Para um ser humano, testar todas essas entradas diferentes pode levar semanas, enquanto que uma máquina pode levar alguns minutos.
Pense assim: você também não está "testando" algo que será estático. Seu aplicativo provavelmente está passando por mudanças constantes. Portanto, esses testes de unidade são projetados para serem executados em diferentes pontos do ciclo de compilação ou implantação. Talvez a maior vantagem seja esta:
Se você quebrar algo em seu código, você saberá sobre isso agora , não depois da implantação, nem quando um testador de controle de qualidade detectar um bug, nem quando seus clientes tiverem cancelado. Você também terá uma chance melhor de corrigir a falha imediatamente , pois fica claro que o que quebrou a parte do código em questão provavelmente aconteceu desde a sua última compilação. Assim, a quantidade de trabalho de investigação necessário para corrigir o problema é bastante reduzida.
fonte
Eu adicionei alguns outros System.out NÃO podem fazer:
Torne cada caso de teste independente (é importante)
O JUnit pode fazer isso: toda vez que uma nova instância de caso de teste será criada e
@Before
chamada.Separe o código de teste da fonte
JUnit pode fazê-lo.
Integração com CI
O JUnit pode fazer isso com Ant e Maven.
Organize e combine casos de teste facilmente
O JUnit pode fazer
@Ignore
e testar o conjunto.Resultado fácil de verificar
JUnit oferece muitos métodos Assert (
assertEquals
,assertSame
...)Mock e stub fazem você se concentrar no módulo de teste.
O JUnit pode fazer: O uso de mock e stub faz com que você configure o equipamento correto e se concentre na lógica do módulo de teste.
fonte
Os testes de unidade garantem que o código funcione conforme o esperado. Eles também são muito úteis para garantir que o código ainda funcione conforme o planejado, caso você precise alterá-lo posteriormente para criar novas funcionalidades para corrigir um bug. Ter uma cobertura de teste alta do seu código permite continuar desenvolvendo recursos sem precisar executar muitos testes manuais.
Sua abordagem manual
System.out
é boa, mas não a melhor. Esse é um teste único que você executa. No mundo real, os requisitos continuam mudando e na maioria das vezes você faz muitas modificações nas funções e classes existentes. Então ... nem toda vez que você testar o trecho de código já escrito.também existem alguns recursos mais avançados no JUnit, como
Declarações de afirmação
O JUnit fornece métodos para testar determinadas condições. Esses métodos geralmente começam com assertivos e permitem especificar a mensagem de erro, o resultado esperado e o real.
Alguns desses métodos são
fail([message])
- Permite que o teste falhe. Pode ser usado para verificar se uma determinada parte do código não é alcançada. Ou ter um teste com falha antes que o código de teste seja implementado.assertTrue(true)
/assertTrue(false)
- Sempre será verdadeiro / falso. Pode ser usado para predefinir um resultado de teste, se o teste ainda não estiver implementado.assertTrue([message,] condition)
- Verifica se o booleanocondition
é verdadeiro.assertEquals([message,] expected, actual)
- Testa se dois valores são iguais (de acordo com oequals
método, se implementado, caso contrário, usando==
comparação de referência). Nota: Para matrizes, é a referência que é verificada, e não o conteúdo, usadoassertArrayEquals([message,] expected, actual)
para isso.assertEquals([message,] expected, actual, delta)
- Testa se dois valores flutuantes ou duplos estão a uma certa distância um do outro, controlados pelodelta
valor.assertNull([message,] object)
- Verifica se o objeto é nuloe assim por diante. Veja o Javadoc completo para todos os exemplos aqui .
Suítes
Com os conjuntos de testes, você pode, de certo modo, combinar várias classes de teste em uma única unidade, para poder executá-las todas de uma vez. Um exemplo simples, combinando as classes de teste
MyClassTest
eMySecondClassTest
em um Suite chamadoAllTests
:fonte
A principal vantagem do JUnit é que ele é automatizado, e você não precisa verificar manualmente com as impressões. Cada teste que você escreve permanece no seu sistema. Isso significa que, se você fizer uma alteração que tenha um efeito colateral inesperado, seu teste será detectado e falhará, em vez de você ter que se lembrar de testar manualmente tudo após cada alteração.
fonte
JUnit é uma estrutura de teste de unidade para a linguagem de programação Java. É importante no desenvolvimento orientado a teste e faz parte de uma família de estruturas de teste de unidade conhecidas coletivamente como xUnit.
O JUnit promove a idéia de "primeiro teste e depois codificação", com ênfase na configuração dos dados de teste para um trecho de código que pode ser testado primeiro e depois implementado. Essa abordagem é como "teste um pouco, codifique um pouco, teste um pouco, codifique um pouco ...", que aumenta a produtividade do programador e a estabilidade do código do programa que reduz o estresse do programador e o tempo gasto na depuração.
Recursos O JUnit é uma estrutura de código aberto usada para escrever e executar testes.
Fornece anotação para identificar os métodos de teste.
Fornece asserções para testar os resultados esperados.
Fornece corredores de teste para executar testes.
Os testes JUnit permitem escrever código mais rapidamente, aumentando a qualidade
JUnit é elegantemente simples. É menos complexo e leva menos tempo.
Os testes JUnit podem ser executados automaticamente e verificam seus próprios resultados e fornecem feedback imediato. Não há necessidade de vasculhar manualmente um relatório dos resultados dos testes.
Os testes JUnit podem ser organizados em conjuntos de testes contendo casos de teste e até outros conjuntos de testes.
O Junit mostra o progresso do teste em uma barra verde se o teste estiver indo bem e fica vermelha quando um teste falha.
fonte
Eu tenho uma perspectiva um pouco diferente de por que o JUnit é necessário.
Na verdade, você pode escrever todos os casos de teste, mas é complicado. Aqui estão os problemas:
Em vez de
System.out
, podemos adicionarif(value1.equals(value2))
e retornar 0 ou -1 ou mensagem de erro. Nesse caso, precisamos de uma classe de teste "principal" que execute todos esses métodos e verifique os resultados e mantenha quais casos de teste falharam e quais foram aprovados.Se você quiser adicionar mais alguns testes, precisará adicioná-los a essa classe de teste "principal" também. Alterações no código existente. Se você deseja detectar automaticamente casos de teste de classes de teste, precisará usar a reflexão.
Todos os seus testes e sua classe principal para executar testes não são detectados pelo eclipse e você precisa escrever configurações personalizadas de depuração / execução para executar esses testes. Você ainda não vê essas saídas coloridas de verde / vermelho.
Aqui está o que o JUnit está fazendo:
Possui
assertXXX()
métodos úteis para imprimir mensagens de erro úteis das condições e comunicar resultados à classe "principal".A classe "main" é chamada runner, que é fornecida pelo JUnit, portanto não precisamos escrever nenhuma. E detecta os métodos de teste automaticamente por reflexão. Se você adicionar novos testes com
@Test
anotação, eles serão detectados automaticamente.O JUnit também possui integração com eclipse e maven / gradle, por isso é fácil executar testes e você não precisará escrever configurações de execução personalizadas.
Eu não sou especialista em JUnit, então é isso que entendi a partir de agora e que acrescentará mais no futuro.
fonte
Você não pode escrever nenhum caso de teste sem usar a estrutura de teste; caso contrário, terá que escrever seu quadro de teste para dar justiça aos seus casos de teste. Aqui estão algumas informações sobre o JUnit Framework, além de que você pode usar a estrutura TestNG.
O que é o Junit?
O Junit é uma estrutura de teste amplamente usada junto com a linguagem de programação Java. Você pode usar essa estrutura de automação para testes de unidade e de interface do usuário. Isso nos ajuda a definir o fluxo de execução do nosso código com diferentes anotações. O Junit baseia-se na idéia de "primeiro teste e depois codificação", o que nos ajuda a aumentar a produtividade dos casos de teste e a estabilidade do código.
Recursos importantes do Junit Testing -
fonte
JUNIT é o método geralmente aceito pelo desenvolvedor java. Onde eles podem fornecer entrada esperada semelhante à função e decidir de acordo que o código escrito está perfeitamente escrito ou se o caso de teste falhar, uma abordagem diferente também pode precisar ser implementada. O JUNIT agilizará o desenvolvimento e garantirá os 0 defeitos na função.
fonte
JUNTA: OBSERVE E AJUSTE
Aqui está a minha perspectiva da JUNIT.
O JUNIT pode ser usado para:
1) Observar o comportamento do sistema quando uma nova unidade é adicionada nesse sistema.
2) Faça ajustes no sistema para receber a "nova" unidade no sistema.
O que? Exatamente.
Quando seu parente visitar o quarto de sua faculdade,
1) Você fingirá ser mais responsável.
2) Você manterá todas as coisas onde elas devem estar, como sapatos na sapateira não na cadeira, roupas no armário e não na cadeira.
3) Você vai se livrar de todo o contrabando.
4) você começará a limpeza em todos os dispositivos que possui.
Sistema: Seu código
UNIDADE: nova funcionalidade.
Como a estrutura JUNIT é usada para a linguagem JAVA, JUNIT = UNIDADE JAVA (pode ser).
Suponha que você já tenha um código à prova de balas, mas veio um novo requisito e você deve adicionar o novo requisito ao seu código. Esse novo requisito pode quebrar seu código para alguma entrada (testcase).
A maneira mais fácil de adaptar essa alteração é usando o teste de unidade (JUNIT).
Para isso, você deve escrever vários casos de teste para seu código ao criar sua base de código. E sempre que surgir um novo requisito, basta executar todos os casos de teste para ver se algum deles falha. Se Não, você é um artista BadA ** e está pronto para implantar o novo código.
Se alguma das caixas de teste falhar, você altera seu código e executa novamente as caixas de teste até obter o status verde.
fonte