@joha0738

Как должен правильно должен выглядеть тест для простого Java приложения?

Доброго времени суток, я новичок в программировании на JAVA и ни разу не сталкивался с тестированием.
Хочу попросить вас помочь с написание тестов для простых методов веб приложения(JAVA,SPRING,H2).У меня просто приложение с 2 сущностями(Планеты(Name), Правители(Name,Age)) и список функционала для которого нужно написать тесты:
- Добавить нового Повелителя
- Добавить новую Планету
- Назначить Повелителя управлять Планетой
- Уничтожить Планету
- Найти всех Повелителей бездельников, которые прохлаждаются и не управляют никакими Планетами
- Отобразить ТОП 10 самых молодых Повелителе.

@Controller
public class MainController {

    @Autowired
    private LordsRepository lordsRepository;

    @Autowired
    private PlanetsRepository planetsRepository;
 
@PostMapping("/createLord")
    public String postCreateLord(@RequestParam(value = "name") String name,@RequestParam(value = "age") int age){
        Lords lord = new Lords();
        lord.setName(name);
        lord.setAge(age);
        lordsRepository.save(lord);
        return "redirect:/";
    }

 @PostMapping("/createPlanet")
    public String postCreatePlanet(@RequestParam(value = "name") String name){
        Planets planet = new Planets();
        planet.setName(name);
        if(planetsRepository.findByName(name) == null)
        planetsRepository.save(planet);
        return "redirect:/planets";
    }

@GetMapping("/destroy/{id}")
    public String destroyPlanet(@PathVariable(value = "id") Planets planet){
        planetsRepository.delete(planet);
        return "redirect:/planets";
    }

@GetMapping("/newPlanetLord/{planet.id}/{lord.id}")
    public String newPlanetLord(@PathVariable(value = "planet.id") Planets planet,@PathVariable(value = "lord.id") Lords lord){
        planet.setLord(lord);
        planetsRepository.save(planet);
        return "redirect:/planets";
    }

@GetMapping("/young")
    public String youngLord(Model model){
        List<Lords> lords = lordsRepository.findAll();
        lords.sort(Comparator.comparingInt(x->x.getAge()));
        model.addAttribute("lords",lords.stream().limit(10).toList());
        return "young";
    }

    @GetMapping("/withoutPl")
    public String withoutLord(Model model){
        List<Lords> lords = lordsRepository.findAll();
        List<Lords> lords1 = new ArrayList<>();
        lords.stream().filter(x->x.getPlanets().size()==0).forEach(x->lords1.add(x));
        model.addAttribute("lords",lords1);
        return "withoutPlanet";
    }


Пытался найти хоть какие то гайды для написания тестов,но все гайды сводились к тому что автор постил уже написанный код без толкового объяснения "что есть что и зачем".

Вот какой код теста я написал,после запуска мне не выдает ошибок, но мне кажется что я написал какую то чушь.....

@SpringBootTest
public class PlanerAppApplicationTests {

    @Mock
    private MainController mainController;

    @Autowired
    private LordsRepository lordsRepository;

    @Autowired
    private PlanetsRepository planetsRepository;

    @Test
    public void createLord(){
        mainController.postCreateLord("John",23);
        mainController.postCreateLord("John2",20);
    }

    @Test
    public void createPlanet(){
        mainController.postCreatePlanet("saturn");
        mainController.postCreatePlanet("saturn2");
    }

    @Test
    public void destroyPlanet(){
        Planets planet = planetsRepository.getById(3l);
        mainController.destroyPlanet(planet);
    }

    @Test
    public void setLordOnPlanet() {
        Lords lord = lordsRepository.getById(1l);
        Planets planet = planetsRepository.getById(1l);
        mainController.newPlanetLord(planet,lord);
    }

    @Test
    public void tenYoungLord(){
        List<Lords> lords = lordsRepository.findAll();
        lords.sort(Comparator.comparingInt(x->x.getAge()));
    }


    @Test
    public void lordWOPlanet(){
        List<Lords> lords = lordsRepository.findAll();
        List<Lords> lords1 = new ArrayList<>();
        lords.stream().filter(x->x.getPlanets().size()==0).forEach(x->lords1.add(x));
    }
}
  • Вопрос задан
  • 134 просмотра
Решения вопроса 1
@rPman
Когда ты разрабатываешь какое то приложение, не важно на сколько сложное, ты же не пишешь его с нуля и до конца полностью (точнее такое бывает но редко, для не сильно больших задач и у этого метода есть недостатки - больше подвержен ошибкам), наоборот, код идеологически разбивается на части или этапы разработки, каждый из которых пишется по очереди, до принципиальной возможности запуска, часто кстати в уже написанные части подставляются заглушки (и/или подсовывается база данных в определенном состоянии) и добавляются отладочные сообщения, чтобы приложение запустилось в нужном состоянии чтобы в принципе была возможность протестировать только что написанную часть.

Под протестировать я подразумеваю любой способ проверить, что получится, как программа отреагирует (например что напишет в логах), и сравнить это с ожидаемым поведением.

Что значит ожидаемое поведение? когда ты делишь задачу на подзадачи, у тебя появляются промежуточные данные и состояния, ну как в анекдоте про чайник и программиста, чтобы заварить чай нужно:
* налить воду в чайник
* поставить на базу/печку и включить
* дождаться готовности/выключить
* налить чай
на каждом этапе нужно проверять состояние, например первый пункт - есть ли вода в чайнике, горячая ли она или холодная, полный ли чайник, есть ли у тебя чайник в руках, и т.п.

Тесты создают на основе данных, являющихся нормальными, ненормальными и граничными для тех алгоритмов, что используются в коде. К примеру нет нужды проверять температуру воды в чайнике отдельно на фиксированные значения 10, 20, 30,.. градусов, если в алгоритме заложены естественные их границы - холодная и горячая, вот вокруг этих констант и приходится гулять.

Вот именно эти проверки и есть тесты, которые необходимо автоматизировать.

Степень полноты тестирования вопрос философский, в конечном счете тесты нужны не только для автоматического тестирования и составления отчетности на изменения кода, но и собственно для разработки, разрабатывая тесты ты делаешь код полнее и точнее (например проверяя температуру воды на первом шаге ты добавишь в код условие - если вода горячая, то пропустить ее нагрев), почитай про test-driven development, TDD

p.s. а еще тесты - это способ исследовать неизвестную библиотеку, дело в том что open source реалии таковы, что документации нет от слова совсем, в лучшем случае перед тобой список методов с типами аргументов и пара примеров, все остальное нужно догадываться по логике наименований, здравому смыслу и ковырянии в исходниках. Тесты тут могут быть исключительно как способ изучения этой библиотеки, но не обязательно такие тесты реализовывать в коде, это все же процесс в ручную происходит, но все же, создавать тесты на ответы от чужой библиотеки полезно для длительной поддержки проекта для того, чтобы у тебя были алерты на необычное поведение ее после обновления)

создание правильных и полных тестов очень сильно повышают стоимость разработки и поддержки проекта, причем чуть ли не на порядок, но дает некоторую защиту от смерти проекта в будущем из-за накапливающихся ошибок, о которых ничего не ясно без тестов.

и еще, создать тесты с нуля на готовый проект почти невозможно.
Ответ написан
Комментировать
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы