Тестування java коду за допомогою junit

English version of this article you can find here.

Тестування далеко не завжди буває веселим і цікавим. Цей процес зазвичай досить тривалий і часом сповнений монотонної роботи. Здається, ще зовсім недавно програмісти користувалися стандартним висновком або ж дебаггера для тестування java класів.

У цій статті я опишу бібліотеку JUnit 4, яка багато в чому спрощує та автоматизує процес написання тестів.

Для демонстрації основних можливостей JUnit Framework, напишемо примітивний клас на мові Java і будемо над ним знущатися. Цей клас буде мати два методу - знаходження факторіала невід'ємного числа і суми двох чисел. Крім того, в екземплярі класу буде знаходиться лічильник викликів методів.

Тепер напишемо Unit тести. Для цього створимо клас з деякою кількістю тестових методів. Природно, клас може містити і звичайні допоміжні методи. Щоб runner тестів міг визначити, хто є хто, тестові методи необхідно позначати аннтоаціей @Test.

У анотації можуть бути проставлені такі параметри:

  • expected - вказуємо яке виключення буде згенеровано методом (див. приклад нижче);
  • timeout - через якийсь час в мілісекундах припинити виконання тесту і зарахувати його як неуспішна.

Якщо ви хочете вказати, що певний тест необхдімо пропустити, то позначте його анотацією @Ignore. Хоча можна просто видалити анотацію @Test.

Буває таке, що для виконання кожного тестового сценарію вам необхідний деякий контекст, наприклад, заздалегідь створені екземпляри класів. А після виконання потрібно звільнити зарезервовані ресурси. В цьому випадку вам знадобляться аннтоаціі @Before і @After. Метод, позначений @Before буде виконуватися перед кожним тестовим випадком, а метод, позначений @After - після кожного тестового випадку.

Якщо ж ініціалізацію і звільнення ресурсів потрібно зробити всього один раз - відповідно до і після всіх тестів - то використовуйте пару анотацій @BeforeClass і @AfterClass.

А ось і сам тестовий клас з декількома тестовими сценаріями:

Метод calls тестує правильність лічильника викликів. Метод factorial перевіряє правильність обчислення факторіала для деяких стандартних значень. Метод factorialNegative перевіряє, що для негативних значень факотріала буде кинутий IllegalArgumentException. Метод todo буде проігнорований. Спробуйте прибрати анотацію @Ignore, коли будете експериментувати з кодом.

Метод assertTrue перевіряє, чи є результат виразу вірним. Деякі інші методи, які можуть стати в нагоді:

  • assertEquals - очікуваний результат і отриманий результат збігаються;
  • assertNull - результатом вираження є null;
  • assertNotNull - результат вираження відмінний від null;
  • assertSame - очікуваний і отриманий об'єкти це один і той же об'єкт.
  • fail - метод генерує виняток AssertionError - додаємо туди, куди не повинен стати надбанням хід виконання програми.

У нашому сучасному світі IDE вміють знаходити і просто запускати тести в проекті. Але що робити, якщо ви хочете запустити їх вручну за допомогою програмного коду. Для цього можна скористатися Runner'ом. Бувають текстовий - junit.textui.TestRunner, графічні версії - junit.swingui.TestRunner, junit.awtui.TestRunner.

Але трохи більш сучасний метод - це використання класу JUnitCore. Додайте наступний метод main в клас MathFuncTest:

І результат виконання:

У більш ранніх версіях JUnit для написання тестового класу потрібно було створити спадкоємця junit.framework.TestCase. Потім необхідно було визначити конструктор, що приймає як параметр String - назва методу - і передати його батьківського класу. Кожен тестовий метод зобов'язаний був починатися з префікса test. Для ініціалізації і звільнення ресурсів використовувалися методи setUp і tearDown. Коротше жах. Ну а зараз все просто, так.

Роз'ясніть, будь ласка, ситуацію. У чому сенс JUnit? Наприклад, рядки

чи не є вони надуманими, в плані перевірки? Адже при налагодженні методу ми все одно перевіряємо правильність його роботи. Так в чому тоді сенс цих рядків? Створюється враження штучності ситуації.

Дійсно хочу зрозуміти. Заздалегідь дякую,

Всі тести в результаті є надуманими, бездумні тести нікому не потрібні і що вони будуть тестувати - велике питання ...

Налагодження: буває різна, все залежить від програми - є випадки коли без ручної налагодження не обійтися ніяк (для цього збирають команди тестувальників), а є випадки, коли прості речі можна перевірити ще на етапі складання програми - для цього і створюються JUnit-тести. Адже погодьтеся, набагато приємніше коли роботу людини виконує залізяка, та ще й швидко, і до того ж на етапі компіляції.

В даному прикладі використаний лише один клас, а в реальності їх може бути набагато більше (і залежностей між ними теж), а значить і ймовірність виникнення помилки зростає ...

Дуже рідко трапляється що клас пишеться один раз і назавжди, SDK і той оновлюється періодично. Ось звідси і з'являється необхідність в автоматичних тестах.

Схожі статті