Руководство по JUnit. API

Базовый функционал фреймворка JUnit содержится в классах пакета junit.framework, который содержит все базовые классы, наиболее важные из которых:

  • Assert
    Набор методов-утверждений
  • TestCase
    Определяет каркас для выполнения тестов (fixtures)
  • TestResult
    Хранит результаты выполнения тестовых случаев
  • TestSuite
    Набор тестов

Рассмотрим по очереди эти классы и их базовые методы:


Класс Assert

Данный класс содержит набор методов-утверждений, которые крайне помогают разработчикам при написании тестов. Записываются только те утверждения, которые оказываются ложными (false). Ниже приведён список наиболее важных методов данного класса:

Метод и описание
1 void assertEquals(boolean expected, boolean actual)

Проверяет, равенство значений двух примитивных типов данных.

2 void assertFalse(boolean condition)

Проверяет, является ли утверждение ложным.

3 void assertNotNull(Object object)

Проверяет, что объект на является null

4 void assertNull(Object object)

Проверяет, что данный объект не является типом null

5 void assertTrue(boolean condition)

Проверяет, что указанное выражение является истинным (true)

6 void fail()

Проваливает тест без вывода сообщений.

Рассмотрим пример использования данного класса:

Откроем наш проект JUnitTutorial и создадим простой класс Calculator, который только считает сумму двух чисел:


package net.proselyte.tutorials;

/**
 * Simple class that represents very primitive calculator
 *
 * @author Eugene Suleimanov
 * @version 1.0
 */
public class Calculator {

    private int firstNumber;

    private int secondNumber;

    public Calculator() {
    }

    public Calculator(int firstNumber, int secondNumber) {
        this.firstNumber = firstNumber;
        this.secondNumber = secondNumber;
    }

    public int getFirstNumber() {
        return firstNumber;
    }

    public void setFirstNumber(int firstNumber) {
        this.firstNumber = firstNumber;
    }

    public int getSecondNumber() {
        return secondNumber;
    }

    public void setSecondNumber(int secondNumber) {
        this.secondNumber = secondNumber;
    }

    public int calculateSum() {
        return (firstNumber + secondNumber);
    }
}

Напишем простой тест CalculatorTests:


package net.proselyte.tutorials;

import org.junit.Test;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;

/**
 * Test class for {@link Calculator}
 *
 * @author Eugene Suleimanov
 * @version 1.0
 */
public class CalculatorTests {
    private Calculator calculator = new Calculator(10, 20);

    @Test
    public void shouldCreateCalculatorInstance() {
        assertNotNull(calculator);
    }

    @Test
    public void shouldReturnCorrectSum() {
        assertEquals(30, calculator.calculateSum());
    }
}

В методе shouldCreateCalculatorInstance() мы проверяем, что экземпляр Calculator действительно создан и не является типом null.
В методе shouldReturnCorrectSum() мы проверяем, что метод calculateSum класса Calculator возвращает корректное значение (10 + 20 = 30).

В результате работы класса CalculatorTests мы получим следующий результат:

calculatortestsclassresult


Класс TestCase

Класс org.junit.TestCase определяет ряд каркас (fixture) для выполнения нескольких тестов. Наиболее использованые методы данного класса приведены ниже:

Методы и описание
1 int countTestCases()

Возвращает количество выполнняемых тестовых случаев (test cases).

2 TestResult createResult()

Создаёт экземпялр класса TestResult по умолчанию.

3 String getName()

Вовращает имя тестового случая

4 TestResult run()

Выполняет тест, собирая результаты с помощью стандартного объекта TestResult.

5 void run(TestResult result)

Выполняет тестовый случай и собирает результаты в экземпляре TestResult

6 void setName(String name)

Задаёт имя тестовому случаю

7 void setUp()

Устанавливает каркас (fixture), например, открывает сетевое соединение

8 void tearDown()

Уничтожает каркас (fixture), например, закрывает сетевое соединение

Рассмотрим небольшой пример:

Мы будем использовать уже созданный класс Calculator:


package net.proselyte.tutorials;

/**
 * Simple class that represents very primitive calculator
 *
 * @author Eugene Suleimanov
 * @version 1.0
 */
public class Calculator {

    private int firstNumber;

    private int secondNumber;

    public Calculator() {
    }

    public Calculator(int firstNumber, int secondNumber) {
        this.firstNumber = firstNumber;
        this.secondNumber = secondNumber;
    }

    public int getFirstNumber() {
        return firstNumber;
    }

    public void setFirstNumber(int firstNumber) {
        this.firstNumber = firstNumber;
    }

    public int getSecondNumber() {
        return secondNumber;
    }

    public void setSecondNumber(int secondNumber) {
        this.secondNumber = secondNumber;
    }

    public int calculateSum() {
        return (firstNumber + secondNumber);
    }
}

И создадим новый тестовый класс:

CalculatorAdvancedTests


package net.proselyte.tutorials;

import org.junit.Before;
import org.junit.Test;

import static org.junit.Assert.assertEquals;

/**
 * Test class for {@link Calculator}
 *
 * @author Eugene Suleimanov
 * @version 1.0
 */
public class CalculatorAdvancedTests {

    private Calculator calculator = new Calculator();

    private int firstNumber;
    private int secondNumber;

    @Before
    public void setUp() {
        firstNumber = 100;
        secondNumber = 200;
        calculator.setFirstNumber(firstNumber);
        calculator.setSecondNumber(secondNumber);
    }

    @Test
    public void shouldCreateCalculatorWithSetUpValues() {
        assertEquals(firstNumber, 100);
        assertEquals(secondNumber, 200);
    }

    @Test
    public void shouldReturnCorrectSum() {
        assertEquals(300, calculator.calculateSum());
    }
}

В методе setUp() мы указываем операции, которые запускаются перед каждым тестом.
В методе shouldCreateCalculatorWithSetUpValues() мы проверяем, что значения целых чисел в экземпляре calculator установлены в методе setUp (100 и 200).
А метод shouldReturnCorrectSum() проверяет, что метод calculateSum корректно вычисляет сумму элементов.
В результате работы данного класса мы получим следующий результат:

calculatoradvancedtestsresult


Класс TestResult

Класс org.junit.TestResult хранит результаты работы test case. Он отличает failures (сбои) и errors (ошибки).  Сбои ожидаются и проверяются с помощью утверждений. Ошибки же, в свою очередь, не ожидаются (например OutOfMemoryError).

Ниже приведены наиболее важные методы класса TestResult:

Методы и описания
1 void addError(Test test, Throwable t)

Добавляет ошибку в список ошибок

2 void addFailure(Test test, AssertionFailedError t)

Добавялет сбой в список сбоев.

3 void endTest(Test test)

Выводит результаты завершённых тестов.

4 int errorCount()

Возвращает количество обнаруженных ошибок.

5 Enumeration<TestFailure> errors()

Возвращает перечисление для ошибок.

6 int failureCount()

Возвращает количество обнаруженных сбоев.

7 void run(TestCase test)

Запускает TestCase.

8 int runCount()

Возвращает количество запущенных тестов.

9 void startTest(Test test)

Выводит результат теста, который передаётся в параметре.

10 void stop()

Останавливает запущенный тест.


Класс TestSuite

Класс org.junit.TestSuite представляет собой группу тестов, которые могут быть запущены вместе.

Ниже приведены основные методы данного класса:

Методы и описание
1 void addTest(Test test)

Добавляет тест в suite.

2 void addTestSuite(Class<? extends TestCase> testClass)

Добавляет тесты из указанного тестового класса.

3 int countTestCases()

Возвращает количество тестовых случаев, которые будут запущены в данном тесте.

4 String getName()

Возвращает имя suite.

5 void run(TestResult result)

Запускает тесты и записывает их результаты в TestResult.

6 void setName(String name)

Указывает имя suite.

7 Test testAt(int index)

Возвращает тест с указанным индексом

8 int testCount()

Возвращает количество тестов в данном сьюте.

9 static Test warning(String message)

Возвращает тест, который не пройдёт и выводит сообщение

Создадим простой TestSuite, в который добавим имеющиеся тестовые классы:

TestSuiteDemo.java


package net.proselyte.tutorials;

import junit.framework.TestResult;
import junit.framework.TestSuite;
import org.junit.Test;

/**
 * Demonstration of {@link TestSuite}
 *
 * @author Eugene Suleimanov
 * @version 1.0
 */
public class TestSuiteDemo {
    TestSuite testSuite = new TestSuite(CalculatorTests.class, CalculatorAdvancedTests.class);
    TestResult result = new TestResult();

    @Test
    public void testSuiteInAction() {
        testSuite.run(result);
        System.out.println("Amount of test cases: " + testSuite.countTestCases());
        testSuite.setName("SimpleTestSuite");
        System.out.println("Name of Test Suite: " + testSuite.getName());
    }
}

В начале мы создаём экземпляр TestSuite и добавляем в него классы CalculatorTests и CalculatorAdvancedTests.
После этого мы выводим количество TestCases, задаём TestSuite имя и выводим его в консоль.
В результате работы данного класса мы получим следующий результат:

testsuitedemoresult

На этом мы заканчиваем обзор базового API фреймворка JUnit.

В следующей статье мы рассмотрим базовые принципы написания тестов.