JavaRush /Blogue Java /Random-PT /JUnit para JavaRush ou um pouco sobre testes em casa.
Sdu
Nível 17

JUnit para JavaRush ou um pouco sobre testes em casa.

Publicado no grupo Random-PT
Cansado de digitar dados de teste no console dezenas de vezes para verificar sua tarefa? Bem-vindo ao gato, direi o que você pode fazer com ele. O objetivo final deste material será automatizar o lançamento da tarefa que está sendo resolvida com diversos parâmetros e verificar os resultados sem fazer alterações em seu código fonte. Como você provavelmente já entendeu pelo título, nosso principal assistente neste assunto bastante simples será o JUnit . Se você ainda não ouviu falar sobre testes unitários e testes unitários , sugiro que faça uma pequena pausa e se familiarize com esses conceitos, felizmente há bastante informação na Internet. Não, você não quer? Bem, tudo bem, acho que isso não será um grande problema para entender o que está acontecendo. Afinal, você sabe o que são teste e testes em geral? Você faz isso toda vez que inicia sua tarefa, insere os dados iniciais e compara o resultado resultante com o que esperava ver.
Olá, mundo JUnit!
O que é JUnit? No site oficial do projeto podemos ler a seguinte descrição:
JUnit é uma estrutura simples para escrever testes repetíveis. É uma instância da arquitetura xUnit para estruturas de teste unitário.
Para nós, isso significa a capacidade de escrever classes especialmente projetadas cujos métodos irão interagir com nosso programa, comparar o resultado resultante com o de referência e nos informar se eles não corresponderem. Para entender o princípio, considere um exemplo simples. Suponha que temos uma classe auxiliar, cujo método pega duas variáveis ​​do tipo int e retorna sua soma: JUnit para JavaRush ou um pouco sobre testes em casa.  - 1 Esta é a funcionalidade que tentaremos testar. Felizmente, nosso IDEA favorito já tem tudo que você precisa para criar testes rapidamente, tudo o que precisamos é colocar o cursor na linha de declaração da classe, pressionar “Alt + Enter” e selecionar “Criar Teste” no menu de contexto: Depois de JUnit para JavaRush ou um pouco sobre testes em casa.  - 2 especificar onde você deve criar um teste, o IDEA sugere escolher uma biblioteca de testes (neste material eu uso JUnit4; para que as classes da biblioteca sejam conectadas ao projeto é necessário clicar no botão “Consertar”), métodos a serem testados e adicionais opções. JUnit para JavaRush ou um pouco sobre testes em casa.  - 3 O IDE criará um modelo de classe de teste: ClassName = TestClassName + "Test" MethodName = "test" + TestMethodName JUnit para JavaRush ou um pouco sobre testes em casa.  - 4 Precisamos apenas preencher o corpo do método. As chamadas “Asserções” , métodos fornecidos pelo JUnit , vão ajudar nisso . De forma simplificada, o trabalho deles fica assim: o resultado esperado e o resultado da chamada do método em teste são passados ​​​​para o método .assert*, por conveniência, você pode adicionar uma mensagem explicativa como primeiro parâmetro. Se os parâmetros não corresponderem durante o teste, você será informado sobre isso. Você pode iniciar uma classe de teste para execução como uma classe normal, prefiro usar a combinação de teclas Ctrl+Shift+F10 JUnit para JavaRush ou um pouco sobre testes em casa.  - 5
Vamos especificar a tarefa
Em teoria tudo é simples e bonito, mas no contexto do exemplo proposto não é realmente necessário; podemos confiar no computador para somar dois números. Estamos mais interessados ​​em como as coisas vão acontecer com problemas reais resolvidos por alunos JavaRush; por exemplo, sugiro fazer o querido nível05.lesson12.bonus03.
/* Problema em algoritmos Escreva um programa que: 1. insira o número N > 0 no console 2. depois insira N números no console 3. exiba o máximo dos N números inseridos. */
Precisamos escrever três testes, para números positivos, negativos e um conjunto misto.
Quanto mais dentro da floresta...
É aqui que algumas surpresas nos aguardam: public class UtilApp { public static void main(String[] args) throws Exception { BufferedReader reader = new BufferedReader(new InputStreamReader(System.in)); //напишите здесь ваш code int n; int maximum; /* Конечно же я не буду размещать решение задачи ;) Код приведенный тут переработан для наглядности, и не в коем случае не означает что он должен присутствовать в "правильном решении" */ System.out.println(maximum); } }
  • A lógica do programa é colocada no método main()
  • Os dados de origem não são passados ​​para o método, mas são inseridos no teclado.
  • O método main() não retorna o resultado, mas o envia para o console.
Se o primeiro ponto não for particularmente problemático (podemos chamar o método main() como de costume), então os próximos dois nos forçam a aprofundar o assunto e forçar nossos cérebros. Encontrei várias soluções para o problema:
  1. Movendo a lógica para encontrar o máximo para um método separado.
    • Prós: Abordagem correta em termos de refatoração
    • Contras: O programa fica cheio de código, estruturas desnecessárias, pelo menos um array ou ArrayList é adicionado (dependendo do gosto e da cor...). Apenas o mecanismo para encontrar o máximo é testado; a entrada e saída de dados não são verificadas.
  2. Escrevendo wrappers para System.in/System.out.
    • Prós: Não usamos bibliotecas de terceiros.
    • Contras: O caminho não é para iniciantes. A complexidade relativa da implementação do teste; a quantidade de código no teste pode ser maior do que na tarefa que está sendo testada.
  3. Usando bibliotecas adicionais para testes.
    • Prós: Código limpo em testes, relativa facilidade de escrever um teste. O código fonte da classe em teste não é alterado.
    • Contras: Necessidade de conectar bibliotecas de terceiros ao projeto.
Para ser sincero, gostei mais da terceira opção, então vamos tentar implementá-la.
Regras do sistema
Uma breve pesquisa me levou à página http://stefanbirkner.github.io/system-rules/ e imediatamente ficou claro que era disso que eu precisava.
Uma coleção de regras JUnit para testar código que usa java.lang.System.
Então, vamos baixar a biblioteca . Baixe a biblioteca Commons IO necessária para que as regras do sistema funcionem . Conectamos ambas as bibliotecas ao nosso projeto (Arquivo -> Estrutura do Projeto -> Bibliotecas -> + -> Java) e começamos a esculpir: Após o lançamento, nossa tarefa solicita que você insira números N+1 no console, onde o primeiro número indica quantos números o seguirão. Nas Regras do Sistema, para esses fins é utilizada a classe TextFromStandardInputStream, inicialmente precisamos adicionar um campo deste tipo à nossa classe de teste e marcá-lo com a anotação @Rule: @Rule public final TextFromStandardInputStream systemInMock = emptyStandardInputStream(); Em seguida, diretamente no método de teste indicamos os dados necessários: systemInMock.provideText("4\n2\n6\n1\n3\n"); Como você pode ver, os números são transmitidos em formato de texto e separados por uma string de hífen "\n". Com base nisso, verifica-se que N será igual a 4, e procuraremos o máximo dos números {2, 6, 1, 3}. A seguir, precisamos criar uma instância da classe em teste e chamar o método main(). Nosso programa lê os dados do systemInMock, processa e imprime o resultado, e tudo o que precisamos fazer é lê-los e compará-los com o padrão. Para fazer isso, as regras do sistema nos fornecem a classe StandardOutputStreamLog. Adicionamos um campo do tipo especificado: @Rule public final StandardOutputStreamLog log = new StandardOutputStreamLog(); Você pode ler os dados impressos usando o método .getLog(), embora seja necessário levar em consideração a presença de caracteres de nova linha, as opções finais podem ser assim: assertEquals("{2, 6, 1, 3}, max = 6", "6", log.getLog().trim()); // or assertEquals("{2, 6, 1, 3}, max = 6", "6\r\n", log.getLog()); Entre testes, para evite camadas de dados, você precisa limpar o log log.clear(); O texto completo da minha classe de teste: import org.junit.Rule; import org.junit.Test; import org.junit.contrib.java.lang.system.StandardOutputStreamLog; import org.junit.contrib.java.lang.system.TextFromStandardInputStream; import static org.junit.Assert.*; import static org.junit.contrib.java.lang.system.TextFromStandardInputStream.emptyStandardInputStream; public class UtilAppTest { @Rule public final TextFromStandardInputStream systemInMock = emptyStandardInputStream(); @Rule public final StandardOutputStreamLog log = new StandardOutputStreamLog(); @Test public void testAddition() throws Exception { systemInMock.provideText("4\n2\n6\n1\n3\n"); UtilApp utilApp = new UtilApp(); utilApp.main(new String[]{}); assertEquals("{2, 6, 1, 3}, max = 6", "6", log.getLog().trim()); systemInMock.provideText("5\n-100\n-6\n-15\n-183\n-1\n"); log.clear(); utilApp.main(new String[]{}); assertEquals("{-100, -6, -15, -183, -1}, max = -1", "-1", log.getLog().trim()); systemInMock.provideText("3\n2\n0\n-1\n"); log.clear(); utilApp.main(new String[]{}); assertEquals("{2, 0, -1}, max = 2", "2", log.getLog().trim()); } } Lançamos e aproveitamos. -=!!! IMPORTANTE!!!=- Este material é fornecido APENAS para fins informativos; não garanto sucesso no teste da tarefa no servidor se houver uma classe estranha no pacote com a tarefa. Antes de enviar uma tarefa para verificação ao servidor, remova tudo o que for estranho: arquivos desnecessários, classes desnecessárias, código comentado. A conclusão bem-sucedida dos testes criados não garante a conclusão bem-sucedida dos testes no servidor. Eu deliberadamente não mastiguei o material teórico: a teoria dos testes unitários, anotações JUnit, assert, etc., todo o material está nos links fornecidos no texto. Talvez você tenha suas próprias maneiras de testar tarefas. Ficarei feliz em discuti-las com você nos comentários.
Comentários
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION