Junit для javarush або трохи про тестування в домашніх умовах

JUnit для JavaRush або трохи про тестування в домашніх умовах.

Набридло десятки разів забивати в консоль тестові дані щоб перевірити свою задачу? Ласкаво просимо під кат, я розповім що можна з цим зробити.

Кінцевою метою даного матеріалу буде автоматизація запуску розв'язуваної задачі з різними параметрами і перевіркою результатів без внесення змін до її вихідний код. Як Ви вже напевно зрозуміли з заголовка, головним нашим помічником в цьому досить простій справі буде JUnit.

Якщо Ви ще не чули про модульному тестуванні та юніт-тестах. пропоную Вам трохи відволіктися і самостійно познайомитися з цими поняттями, благо в інтернеті інформації достатньо. Ні, не хочете? Ну й добре, думаю великою проблемою для розуміння того, що відбувається це не стане. Адже Ви ж знаєте що таке тест і тестування взагалі? Ви ж займаєтеся цим кожен раз, коли запускаєте свою задачу, вводите початкові дані і порівнюєте отриманий результат з тим, що очікували побачити.

Hello, world JUnit!


Що ж таке JUnit? На оф.сайті проекту ми можемо прочитати ось такий опис:
JUnit is a simple framework to write repeatable tests. It is an instance of the xUnit architecture for unit testing frameworks.
Для нас це означає можливість писати спеціальним чином оформлені класи, методи яких будуть взаємодіяти з нашою програмою, звіряти одержуваний результат з еталонним і інформувати нас якщо вони не співпали.

Для розуміння принципу розглянемо простенький приклад.
Припустимо у нас є допоміжний клас, один з методів якого приймає дві змінні типу int і повертає їх суму:

Junit для javarush або трохи про тестування в домашніх умовах

Після того, як Ви уточніть де варто створити тест, IDEA запропонувати вибрати бібліотеку тестування (в даному матеріалі я використовую JUnit4, для того, щоб класи бібліотеки були підключені до проекту необхідно натиснути кнопку «Fix»), тестовані методи і додаткові опції.

Junit для javarush або трохи про тестування в домашніх умовах

IDE створить шаблон тестового класу:
ІмяКласса = імяТестіруемогоКласса + «Test»
імяМетода = «test» + ІмяТестіруемогоМетода

Junit для javarush або трохи про тестування в домашніх умовах

Нам залишається тільки наповнити тіло методу. У цьому на допоможуть так звані «Assertions \ Твердження». методи надаються JUnit. Спрощено їх робота виглядає наступним чином: в метод .assert * передається очікуваний результат і результат виклику тестованого методу, для зручності першим параметром можна додати пояснює повідомлення. Якщо під час виконання тесту параметри не співпадуть, Ви будете проінформовані про це. Запускати тестовий клас на виконання можна як і звичайний клас, я вважаю за краще використовувати комбінацію клавіш Ctrl + Shift + F10

Junit для javarush або трохи про тестування в домашніх умовах

конкретизуємо завдання


В теорії все просто і красиво, але в розрізі запропонованого прикладу не особливо то й потрібно, скласти два числа ми можемо довірити комп'ютеру. Нас більше цікавить як йтимуть справи з реальними завданнями, які розв'язуються студентами JavaRush, для прикладу я пропоную взяти улюблену level05.lesson12.bonus03.
/ * Завдання по алгоритмам
Написати програму, яка:
1. вводить з консолі число N> 0
2. потім вводить N чисел з консолі
3. виводить на екран максимальну з введених N чисел.
* /
Нам необхідно написати три тести, для позитивних, негативних чисел і змішаного набору.

Чим далі в ліс.


Ось тут нас і чекають деякі сюрпризи:

  • Логіка програми розміщується в методу main ()
  • Вихідні дані не передаються в метод, а вводяться з клавіатури.
  • Метод main () не повертає результат, а виводить його в консоль.

Якщо перший пункт не особливо і проблематичний (ми можемо викликати метод main () як зазвичай), то два наступні змушують заглиблюватися в тему і напружувати звивини. Я знайшов кілька варіантів вирішення проблеми:
  1. Винесення логіки знаходження максимуму в окремий метод.
    • Плюси: Правильний підхід з точки зору рефакторінга
    • Мінуси: Програма обростає кодом, зайвими структурами, як мінімум додається масив або ArrayList (на смак і колір.). Тестується тільки механізм знаходження максимуму, введення даних, як і висновок, що не перевіряються.
  2. Написання обгорток-wrapper'ов для System.in/System.out.
    • Плюси: Чи не використовуємо сторонні бібліотеки.
    • Мінуси: Шлях не для новачків. Відносна складність реалізації тесту, обсяг коду в тесті може бути більше ніж в тестованої задачі.
  3. Використання для тестів додаткових бібліотек.
    • Плюси: Чистота коду в тестах, відносна простота написання тесту. Не змінюється вихідний код тестованого класу.
    • Мінуси: Необхідність підключити до проекту сторонні бібліотеки.

Зізнатися чесно, третій варіант мені сподобався найбільше, ось його і спробуємо реалізувати.
System Rules

Після запуску наше завдання просить ввести з консолі N + 1 чисел, де перше число повідомляє про те, скільки чисел піде за ним. В System Rules для цих цілей служить клас TextFromStandardInputStream, спочатку нам необхідно додати в наш тестовий клас поле цього типу і позначити його анотацією @Rule:

Потім, безпосередньо в тестовому методі вказуємо необхідні дані:


Як бачите, числа передаються в текстовому вигляді і поділяються знаком розриву рядків "\ n". Виходячи з цього, виходить що N у нас буде дорівнює 4, а шукати максимум ми будемо з чисел.

Далі нам необхідно створити екземпляр тестового класу і викликати метод main (). Наша програма вважає дані з systemInMock, обробить їх і роздрукує результат, а нам залишається тільки вважати його і порівняти з еталоном. Для цього, system rules надає нам клас StandardOutputStreamLog.
Додаємо поле зазначеного типу:

Вважати роздруковані дані можна за допомогою методу .getLog (), при цьому потрібно враховувати наявність символів переведення рядка, остаточні варіанти можуть бути такі:

Між тестами, щоб уникнути нашарування даних необхідно очищати log


Повний текст мого тестового класу:

Запускаємо і насолоджуємося.

Даний матеріал наданий ТІЛЬКИ в ознайомлювальних цілях, я не гарантую успішного проходження тестування завдання на сервері в разі наявності стороннього класу в пакеті із завданням. Перш ніж відправляти завдання на перевірку на сервер видаляйте все стороннє: зайві файли, зайві класи, закоментірований код.

Вдале проходження придуманих Вами тестів не гарантує успішного проходження тестів на сервері.

Схожі статті