JavaRush /Blogue Java /Random-PT /JUnit parte I

JUnit parte I

Publicado no grupo Random-PT

JUnit :: ou como amar o validador JavaRush

JUnit parte I - 1Resumidamente sobre por que precisamos dessa fera? JUnit é uma estrutura para testar automaticamente seu código bom ou não tão bom . Você pode dizer: - por que preciso desse swing, posso testar meu bom código Java de maneira fácil e simples. Você pode escrever muitas letras introdutórias, mas eu não sou muito poeta, vamos ao que interessa...

Crie um objeto

E assim, para testar algo, primeiro precisamos de um objeto de teste. Temos uma tarefa pela frente.
  1. Precisamos de um objeto que armazene informações sobre o usuário.
    1. Id – deve ser contado na ordem em que o novo usuário foi adicionado.
    2. Nome de usuário.
    3. Idade dele.
    4. Gênero Masculino Feminino)
  2. É necessário fornecer armazenamento de uma lista de usuários.

  3. A classe deve ser capaz.

    1. Gere uma lista de todos os usuários.
    2. Gere uma lista de usuários por gênero (MASCULINO/FÊMEA).
    3. Retorne o número de usuários na lista geral e calcule o número com base no sexo do usuário.
    4. Calcule o valor total por idade do usuário e leve em consideração também o sexo.
    5. Calcule a idade média, tanto geral quanto por sexo.
E então, vamos começar a criar um objeto... Vamos criar uma classe Java Userque conterá campos:
private int id;
private String name;
private int age;
private Sex sex;
Isso é suficiente para armazenar os dados do usuário, vamos ver o que mais é necessário para a tarefa. Precisamos armazenar de alguma forma todos os usuários, vamos fazer um campo estático em nossa classe allUsers, acho que está tudo bem se for assimMap<Integer, User>
private static Map<Integer, User> allUsers;
Também precisamos de alguma forma atribuir um número de sequência aos usuários, vamos criar um campo de contador estático, que, ao criar um novo usuário, atribuirá um número de sequência Id ao usuário.
private static int countId = 0;
Então, parece que resolvemos os campos, vamos escrever um construtor para nosso objeto e getters para os campos id, name, age, sex. Não há nada complicado com heterae, vamos pedir ajuda à IDEA , ela nunca recusará e tornaremos o construtor um pouco complicado. O designer será capaz. Inicialize os campos, verifique se existe tal objeto em allUsers, se não existir, aumente nosso contador countId++e adicione-o à lista de todos os usuários. E também inicialize o campo allUsers caso ainda não tenha sido inicializado. Para maior comodidade na busca por objetos idênticos, redefiniremos os métodos equals()e hashCode(), novamente pediremos ajuda à nossa querida IDEA e compararemos por campos name,,, age. sexAlém disso, vamos criar um método privado hasUser()que verificará se tal objeto está na lista.
@Override
public boolean equals(Object o) {
    if (this == o) return true;
    if (o == null || getClass() != o.getClass()) return false;
    User user = (User) o;
    return age == user.age &&
            Objects.equals(name, user.name) &&
            sex == user.sex;
}

@Override
public int hashCode() {

    return Objects.hash(name, age, sex);
}
No final, acabei com um designer assim.
public User(String name, int age, Sex sex) {
    if (allUsers == null){
        allUsers = new HashMap<>();
    }

    this.name = name;
    this.age = age;
    this.sex = sex;

    if (!hasUser()){
        countId++;
        this.id = countId;
        allUsers.put(id, this);
    }
}
e um método auxiliar privado
private boolean hasUser(){
    for (User user : allUsers.values()){
        if (user.equals(this) && user.hashCode() == this.hashCode()){
            return true;
        }
    }
    return false;
}
e também redefinirtoString()
@Override
public String toString() {
    return "User{" +
            "id=" + id +
            ", name='" + name + '\'' +
            ", age=" + age +
            ", sex=" + sex +
            '}';
}
Agora é hora de implementar a lógica dos métodos necessários. Como a lógica funcionará principalmente com campos estáticos, também tornaremos os métodos estáticos; eles não são necessários para objetos.
  1. Gere uma lista de todos os usuários.
  2. Gere uma lista de usuários por gênero (MASCULINO/FÊMEA).
  3. Os pontos a e b podem ser bem tratados por um método getAllUsers()que retornará uma lista de todos Usere um método sobrecarregado getAllUsers(Sex sex)que retornará uma lista, dependendo do parâmetro passado Sex.

    public static List<User> getAllUsers(){
        return new ArrayList<>(allUsers.values());
    }
    
    public static List<User> getAllUsers(Sex sex){
        List<User> listAllUsers = new ArrayList<>();
        for (User user : allUsers.values()){
            if (user.sex == sex){
                listAllUsers.add(user);
            }
        }
        return listAllUsers;
    }

  4. Retorne o número de usuários na lista geral e calcule o número com base no sexo do usuário.

    public static int getHowManyUsers(){
        return allUsers.size();
    }
    
    public static int getHowManyUsers(Sex sex){
        return getAllUsers(sex).size();
    }

  5. Calcule o valor total por idade do usuário e leve em consideração também o sexo. Vamos criar métodos para esta tarefa.

    public static int getAllAgeUsers(){
        int countAge = 0;
        for (User user : allUsers.values()){
            countAge += user.age;
        }
        return countAge;
    }
    
    public static int getAllAgeUsers(Sex sex){
        int countAge = 0;
        for (User user : getAllUsers(sex)){
            countAge += user.age;
        }
        return countAge;
    }

  6. Calcule a idade média, tanto geral quanto por sexo.

    public static int getAverageAgeOfAllUsers(){
        return getAllAgeUsers() / getHowManyUsers();
    }
    
    public static int getAverageAgeOfAllUsers(Sex sex){
        return getAllAgeUsers(sex) / getHowManyUsers(sex);
    }

    Ótimo, descrevemos o objeto necessário e seu comportamento. Agora podemos passar para JUnit , mas primeiro vou mostrar como será um teste simples se fizermos isso em main .

    public static void main(String[] args) {
        new User("Eugene", 35, Sex.MALE);
        new User("Marina", 34, Sex.FEMALE);
        new User("Alina", 7, Sex.FEMALE);
    
    
        System.out.println("All users:");
        User.getAllUsers().forEach(System.out::println);
        System.out.println("All users: MALE");
        User.getAllUsers(Sex.MALE).forEach(System.out::println);
        System.out.println("All users: FEMALE");
        User.getAllUsers(Sex.FEMALE).forEach(System.out::println);
        System.out.println("================================================");
        System.out.println(" all users: " + User.getHowManyUsers());
        System.out.println(" all MALE users: " + User.getHowManyUsers(Sex.MALE));
        System.out.println("all FEMALE users: " + User.getHowManyUsers(Sex.FEMALE));
        System.out.println("================================================");
        System.out.println(" total age of all users: " + User.getAllAgeUsers());
        System.out.println(" total age of all MALE users: " + User.getAllAgeUsers(Sex.MALE));
        System.out.println("total age of all FEMALE users: " + User.getAllAgeUsers(Sex.FEMALE));
        System.out.println("================================================");
        System.out.println(" average age of all users: " + User.getAverageAgeOfAllUsers());
        System.out.println(" average age of all MALE users: " + User.getAverageAgeOfAllUsers(Sex.MALE));
        System.out.println("average age of all FEMALE users: " + User.getAverageAgeOfAllUsers(Sex.FEMALE));
        System.out.println("================================================");
    }

    A saída para o console será mais ou menos assim e então compararemos se obtivemos operação normal. Podemos, é claro, ir mais fundo, escrever uma lógica de comparação e ver o que diz o nosso cálculo, mesmo que não tenhamos certeza de que fomos capazes de fornecer tudo.

    //output
    Все пользователи:
    User{id=1, name='Eugene', age=35, sex=MALE}
    User{id=2, name='Marina', age=34, sex=FEMALE}
    User{id=3, name='Alina', age=7, sex=FEMALE}
    Все пользователи: MALE
    User{id=1, name='Eugene', age=35, sex=MALE}
    Все пользователи: FEMALE
    User{id=2, name='Marina', age=34, sex=FEMALE}
    User{id=3, name='Alina', age=7, sex=FEMALE}
    ================================================
           всех пользователей: 3
      всех пользователей MALE: 1
    всех пользователей FEMALE: 2
    ================================================
           общий возраст всех пользователей: 76
      общий возраст всех пользователей MALE: 35
    общий возраст всех пользователей FEMALE: 41
    ================================================
           средний возраст всех пользователей: 25
      средний возраст всех пользователей MALE: 35
    средний возраст всех пользователей FEMALE: 20
    ================================================
    
    Process finished with exit code 0

    Não estamos satisfeitos com este resultado, abaixo dos testes principais , precisamos do JUnit .

Como conectar JUnit a um projeto

Surge a questão de como conectá-lo ao projeto. Para quem sabe, não vou optar pelo Maven , pois esta é uma história completamente diferente. ;) Abra a estrutura do projeto Ctrl + Alt + Shift + S -> Bibliotecas -> clique em + (Nova Biblioteca de Projetos) -> selecione no Maven, JUnit parte I - 2então vemos essa janela, digite “junit:junit:4.12” na barra de pesquisa , espere até encontrar -> OK! -> OK! JUnit parte I - 3Você deve obter este resultado. JUnit parte I - 4Clique em OK, parabéns, JUnit foi adicionado ao projeto. Vamos continuar. Agora precisamos criar testes para nossa classe Java, coloque o cursor no nome da classe User -> pressione Alt + Enter -> selecione criar teste. Deveremos ver uma janela na qual precisamos selecionar a biblioteca JUnit4 -> selecionar os métodos que vamos testar -> OK JUnit parte I - 5A ideia em si criará uma classe UserTest, esta é a classe na qual cobriremos nosso código com testes. Vamos começar:

Nosso primeiro @Test

Vamos criar nosso primeiro método @TestgetAllUsers() - este é um método que deve retornar todos os usuários. O teste será mais ou menos assim:
@Test
public void getAllUsers() {
    // create test data
    User user = new User("Eugene", 35, Sex.MALE);
    User user1 = new User("Marina", 34, Sex.FEMALE);
    User user2 = new User("Alina", 7, Sex.FEMALE);

    //create an expected list and fill it with the data of our method
    List<User> expected = User.getAllUsers();

    //create actual list put data in it for comparison
    //what we expect the method to return
    List<User> actual = new ArrayList<>();
    actual.add(user);
    actual.add(user1);
    actual.add(user2);

    //run the test if the list expected and actual are not equal
    //the test will fail, read the test results in the console
    Assert.assertEquals(expected, actual);
}
Aqui criamos vários usuários de teste -> criamos uma lista expected na qual colocaremos os usuários cujo método retornará para nós getAllUsers()-> criamos uma lista actual na qual colocaremos os usuários cujos assumimos que o getAllUsers()método Assert.assertEquals(actual, esperado) será utilizado e passaremos para ele as listas, inspecionadas e atuais. Este método testará os objetos nas listas fornecidas e retornará o resultado do teste. O método irá comparar todos os campos dos objetos, passando inclusive pelos campos dos pais se houver herança. Vamos fazer o primeiro teste... JUnit parte I - 6O teste foi concluído com sucesso. Agora vamos tentar fazer o teste falhar, para isso precisamos alterar uma das listas de teste, faremos isso comentando a adição de um usuário na lista actual.
@Test
public void getAllUsers() {
    // create test data
    User user = new User("Eugene", 35, Sex.MALE);
    User user1 = new User("Marina", 34, Sex.FEMALE);
    User user2 = new User("Alina", 7, Sex.FEMALE);

    //create an expected list and fill it with the data of our method
    List<User> expected = User.getAllUsers();

    //create actual list put data in it for comparison
    //what we expect the method to return
    List<User> actual = new ArrayList<>();
    actual.add(user);
    actual.add(user1);
    //actual.add(user2);

    //run the test if the list expected and actual are not equal
    //the test will fail, read the test results in the console
    Assert.assertEquals(expected, actual);
}
executamos o teste e vemos o seguinte: JUnit parte I - 7Agora podemos analisar um pouco o motivo da falha do teste. Aqui vemos que há mais usuários na lista inspecionada do que na lista atual. Esta é a razão do fracasso. Podemos verificar isso em main? JUnit: main = 1: 0. Vamos ver como ficará o teste se ele contiver objetos completamente diferentes, vamos fazer assim:
@Test
public void getAllUsers() {
    // create test data
    User user = new User("Eugene", 35, Sex.MALE);
    User user1 = new User("Marina", 34, Sex.FEMALE);
    User user2 = new User("Alina", 7, Sex.FEMALE);

    //create an expected list and fill it with the data of our method
    List<User> expected = User.getAllUsers();

    //create actual list put data in it for comparison
    //what we expect the method to return
    List<User> actual = new ArrayList<>();
    actual.add(new User("User1", 1, Sex.MALE));
    actual.add(new User("User2", 2, Sex.FEMALE));
    actual.add(new User("User3", 3, Sex.MALE));

    //run the test if the list expected and actual are not equal
    //the test will fail, read the test results in the console
    Assert.assertEquals(expected, actual);
}
Isto é o que estará no console: JUnit parte I - 8aqui você pode ver imediatamente que existem usuários diferentes nas listas comparadas, também podemos clicar em <Clique para ver a diferença> obteremos uma janela onde podemos ver em detalhes quais dados temos um Problema com. IDEA irá destacar todos os campos onde existem diferenças. JUnit parte I - 9mainisso pode acontecer? - Não. JUnit : main = 2 : 0 Bem, vamos em frente, ainda temos um monte de métodos que precisam ser cobertos com testes), mas espere, não será ruim verificar se o método retornará getAllUsers()para nós, porque isso é o que fazemos com nullas tarefas JavaRush capturadas pelo validador). Vamos fazer isso, é uma questão de três copeques...
@Test
public void getAllUsers_NO_NULL() {
    //add check for null
    List<User> expected = User.getAllUsers();
    Assert.assertNotNull(expected);
}
Sim, sim, é aproximadamente assim que o validador captura nosso código de merdanull ;) Agora vamos executar este teste e ver o que ele nos mostra. E vai mostrar um erro, como???? Como poderia ser cometido um erro de teste aqui))) JUnit parte I - 10E aqui podemos colher os primeiros frutos de cobrir nosso código com testes. Como você lembra, allUsers inicializamos o campo no construtor, o que significa que ao chamar o método getAllUsers(), nos referiremos a um objeto que ainda não foi inicializado. Vamos editá-lo, remover a inicialização do construtor e fazer isso na declaração do campo.
private static Map<Integer, User> allUsers = new HashMap<>();

    public User(String name, int age, Sex sex) {
        this.name = name;
        this.age = age;
        this.sex = sex;

        if (!hasUser()) {
            countId++;
            this.id = countId;
            allUsers.put(id, this);
        }
    }
Vamos fazer o teste, agora está tudo bem. JUnit parte I - 11Não acho que será fácil capturar NPEs em main, acho que você concordará que a contagem é JUnit: main = 3: 0 Então cobrirei todos os métodos com testes e deixarei você ver como ficará ... Agora nossa classe de teste está assim:
package user;

import org.junit.Assert;
import org.junit.Test;

import java.util.ArrayList;
import java.util.List;

import static org.junit.Assert.*;

public class UserTest {

    @Test
    public void getAllUsers() {
        // create test data
        User user = new User("Eugene", 35, Sex.MALE);
        User user1 = new User("Marina", 34, Sex.FEMALE);
        User user2 = new User("Alina", 7, Sex.FEMALE);

        //create an expected list and fill it with the data of our method
        List<User> expected = User.getAllUsers();

        //create actual list put data in it for comparison
        //what we expect the method to return
        List<User> actual = new ArrayList<>();
        actual.add(user);
        actual.add(user1);
        actual.add(user2);

        //run the test if the list expected and actual are not equal
        //the test will fail, read the test results in the console
        Assert.assertEquals(expected, actual);
    }

    @Test
    public void getAllUsers_NO_NULL() {
        //add check for null
        List<User> expected = User.getAllUsers();
        Assert.assertNotNull(expected);
    }

    @Test
    public void getAllUsers_MALE() {
        User user = new User("Eugene", 35, Sex.MALE);
        User user1 = new User("Marina", 34, Sex.FEMALE);
        User user2 = new User("Alina", 7, Sex.FEMALE);

        List<User> expected = User.getAllUsers(Sex.MALE);

        List<User> actual = new ArrayList<>();
        actual.add(user);

        Assert.assertEquals(expected, actual);
    }

    @Test
    public void getAllUsers_MALE_NO_NULL() {
        //add check for null
        List<User> expected = User.getAllUsers(Sex.MALE);
        Assert.assertNotNull(expected);
    }

    @Test
    public void getAllUsers_FEMALE() {
        User user = new User("Eugene", 35, Sex.MALE);
        User user1 = new User("Marina", 34, Sex.FEMALE);
        User user2 = new User("Alina", 7, Sex.FEMALE);

        List<User> expected = User.getAllUsers(Sex.FEMALE);

        List<User> actual = new ArrayList<>();
        actual.add(user1);
        actual.add(user2);

        Assert.assertEquals(expected, actual);
    }

    @Test
    public void getAllUsers_FEMALE_NO_NULL() {
        //add check for null
        List<User> expected = User.getAllUsers(Sex.FEMALE);
        Assert.assertNotNull(expected);
    }

    @Test
    public void getHowManyUsers() {
        User user = new User("Eugene", 35, Sex.MALE);
        User user1 = new User("Marina", 34, Sex.FEMALE);
        User user2 = new User("Alina", 7, Sex.FEMALE);

        int expected = User.getHowManyUsers();

        int actual = 3;

        Assert.assertEquals(expected, actual);
    }

    @Test
    public void getHowManyUsers_MALE() {
        User user = new User("Eugene", 35, Sex.MALE);
        User user1 = new User("Marina", 34, Sex.FEMALE);
        User user2 = new User("Alina", 7, Sex.FEMALE);

        int expected = User.getHowManyUsers(Sex.MALE);

        int actual = 1;

        Assert.assertEquals(expected, actual);
    }

    @Test
    public void getHowManyUsers_FEMALE() {
        User user = new User("Eugene", 35, Sex.MALE);
        User user1 = new User("Marina", 34, Sex.FEMALE);
        User user2 = new User("Alina", 7, Sex.FEMALE);

        int expected = User.getHowManyUsers(Sex.FEMALE);

        int actual = 2;

        Assert.assertEquals(expected, actual);
    }

    @Test
    public void getAllAgeUsers() {
        User user = new User("Eugene", 35, Sex.MALE);
        User user1 = new User("Marina", 34, Sex.FEMALE);
        User user2 = new User("Alina", 7, Sex.FEMALE);

        int expected = User.getAllAgeUsers();

        int actual = 35 + 34 + 7;

        Assert.assertEquals(expected, actual);
    }

    @Test
    public void getAllAgeUsers_MALE() {
        User user = new User("Eugene", 35, Sex.MALE);
        User user1 = new User("Marina", 34, Sex.FEMALE);
        User user2 = new User("Alina", 7, Sex.FEMALE);

        int expected = User.getAllAgeUsers(Sex.MALE);

        int actual = 35;

        Assert.assertEquals(expected, actual);
    }

    @Test
    public void getAllAgeUsers_FEMALE() {
        User user = new User("Eugene", 35, Sex.MALE);
        User user1 = new User("Marina", 34, Sex.FEMALE);
        User user2 = new User("Alina", 7, Sex.FEMALE);

        int expected = User.getAllAgeUsers(Sex.FEMALE);

        int actual = 34 + 7;

        Assert.assertEquals(expected, actual);
    }
}
Sim, acabou não sendo pequeno, mas o que acontecerá quando se trabalhar com grandes projetos. O que pode ser reduzido aqui? Depois de avaliar tudo, você pode ver que criamos dados de teste em cada teste, e aqui as anotações vêm em nosso auxílio. Vejamos @Before- A anotação @Beforeindica que o método será executado antes de cada método testado @Test. Esta é a aparência de nossa classe de teste com anotação @Before:
package user;

import org.junit.Assert;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;

import java.util.ArrayList;
import java.util.List;

import static org.junit.Assert.*;

public class UserTest {
    private User user;
    private User user1;
    private User user2;

    @Before
    public void setUp() throws Exception {
        user = new User("Eugene", 35, Sex.MALE);
        user1 = new User("Marina", 34, Sex.FEMALE);
        user2 = new User("Alina", 7, Sex.FEMALE);
    }

    @Test
    public void getAllUsers() {
        List<User> expected = User.getAllUsers();

        List<User> actual = new ArrayList<>();
        actual.add(user);
        actual.add(user1);
        actual.add(user2);

        Assert.assertEquals(expected, actual);
    }

    @Test
    public void getAllUsers_NO_NULL() {
        List<User> expected = User.getAllUsers();
        Assert.assertNotNull(expected);
    }

    @Test
    public void getAllUsers_MALE() {
        List<User> expected = User.getAllUsers(Sex.MALE);

        List<User> actual = new ArrayList<>();
        actual.add(user);

        Assert.assertEquals(expected, actual);
    }

    @Test
    public void getAllUsers_MALE_NO_NULL() {
        //add check for null
        List<User> expected = User.getAllUsers(Sex.MALE);
        Assert.assertNotNull(expected);
    }

    @Test
    public void getAllUsers_FEMALE() {
        List<User> expected = User.getAllUsers(Sex.FEMALE);

        List<User> actual = new ArrayList<>();
        actual.add(user1);
        actual.add(user2);

        Assert.assertEquals(expected, actual);
    }

    @Test
    public void getAllUsers_FEMALE_NO_NULL() {
        //add check for null
        List<User> expected = User.getAllUsers(Sex.FEMALE);
        Assert.assertNotNull(expected);
    }

    @Test
    public void getHowManyUsers() {
        int expected = User.getHowManyUsers();

        int actual = 3;

        Assert.assertEquals(expected, actual);
    }

    @Test
    public void getHowManyUsers_MALE() {
        int expected = User.getHowManyUsers(Sex.MALE);

        int actual = 1;

        Assert.assertEquals(expected, actual);
    }

    @Test
    public void getHowManyUsers_FEMALE() {
        int expected = User.getHowManyUsers(Sex.FEMALE);

        int actual = 2;

        Assert.assertEquals(expected, actual);
    }

    @Test
    public void getAllAgeUsers() {
        int expected = User.getAllAgeUsers();

        int actual = 35 + 34 + 7;

        Assert.assertEquals(expected, actual);
    }

    @Test
    public void getAllAgeUsers_MALE() {
        int expected = User.getAllAgeUsers(Sex.MALE);

        int actual = 35;

        Assert.assertEquals(expected, actual);
    }

    @Test
    public void getAllAgeUsers_FEMALE() {
        int expected = User.getAllAgeUsers(Sex.FEMALE);

        int actual = 34 + 7;

        Assert.assertEquals(expected, actual);
    }
}
Bem, e você, já é mais divertido e fácil de ler ;) Aqui está uma lista de anotações para JUnit; é definitivamente mais fácil conviver com elas.
@Test – определяет что метод method() является тестовым.
@Before – указывает на то, что метод будет выполнятся перед каждым тестируемым методом @Test.
@After – указывает на то что метод будет выполнятся после каждого тестируемого метода @Test
@BeforeClass – указывает на то, что метод будет выполнятся в начале всех тестов,
а точней в момент запуска тестов(перед всеми тестами @Test).
@AfterClass – указывает на то, что метод будет выполнятся после всех тестов.
@Ignore – говорит, что метод будет проигнорирован в момент проведения тестирования.
(expected = Exception.class) – указывает на то, что в данном тестовом методе
вы преднамеренно ожидаете Exception.
(timeout = 100) – указывает, что тестируемый метод не должен занимать больше чем 100 миллисекунд.
Métodos de classe principais Assertpara verificação:
fail(String) – указывает на то что бы тестовый метод завалился при этом выводя текстовое сообщение.
assertTrue([message], boolean condition) – проверяет, что логическое condition истинно.
assertsEquals([String message], expected, actual) – проверяет, что два значения совпадают.
Примечание: для массивов проверяются ссылки, а не содержание массивов.
assertNull([message], object) – проверяет, что an object является пустым null.
assertNotNull([message], object) – проверяет, что an object не является пустым null.
assertSame([String], expected, actual) – проверяет, что обе переменные относятся к одному an objectу.
assertNotSame([String], expected, actual) – проверяет, что обе переменные относятся к разным an objectм.
É assim que podemos adicionar a dependência do JUnit 4.12 no Maven
<dependency>
  <groupId>junit</groupId>
  <artifactId>junit</artifactId>
  <version>4.12</version>
  <scope>test</scope>
</dependency>
continua aqui -> JUnit parte II
Comentários
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION