«1. Обзор

JGoTesting — это совместимая с JUnit среда тестирования, вдохновленная пакетом тестирования Go.

В этой статье мы рассмотрим ключевые функции среды JGoTesting и реализуем примеры, чтобы продемонстрировать ее возможности.

2. Зависимость Maven

Во-первых, давайте добавим зависимость jgotesting в наш pom.xml:

<dependency>
    <groupId>org.jgotesting</groupId>
    <artifactId>jgotesting</artifactId>
    <version>0.12</version>
</dependency>

Последнюю версию этого артефакта можно найти здесь.

3. Введение

JGoTesting позволяет нам писать тесты, совместимые с JUnit. Для каждого метода утверждения, предоставляемого JGoTesting, в JUnit есть один с такой же сигнатурой, поэтому реализовать эту библиотеку очень просто.

Однако, в отличие от JUnit, когда утверждение терпит неудачу, JGoTesting не останавливает выполнение теста. Вместо этого сбой записывается как событие и представляется нам только после выполнения всех утверждений.

4. JGoTesting в действии

В этом разделе мы увидим примеры того, как настроить JGoTesting и изучить его возможности.

4.1. Начало работы

Чтобы написать наши тесты, давайте сначала импортируем методы утверждения JGoTesting:

import static org.jgotesting.Assert.*; // same methods as JUnit
import static org.jgotesting.Check.*; // aliases starting with "check"
import static org.jgotesting.Testing.*;

Библиотеке требуется обязательный экземпляр JGoTestRule, отмеченный аннотацией @Rule. Это указывает на то, что все тесты в классе будут управляться JGoTesting.

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

public class JGoTestingUnitTest {
 
    @Rule
    public final JGoTestRule test = new JGoTestRule();
    
    //...
}

4.2. Написание тестов

JGoTesting предоставляет два набора методов утверждения для написания наших тестов. Имена методов в первом наборе начинаются с утверждения и совместимы с JUnit, а остальные начинаются с проверки.

Оба набора методов ведут себя одинаково, и библиотека обеспечивает однозначное соответствие между ними.

Вот пример проверки равенства числа другому с использованием обеих версий:

@Test
public void whenComparingIntegers_thenEqual() {
    int anInt = 10;

    assertEquals(anInt, 10);
    checkEquals(anInt, 10);
}

Остальная часть API не требует пояснений, поэтому мы не будем вдаваться в подробности. Во всех следующих примерах мы сосредоточимся только на проверочной версии методов.

4.3. События и сообщения об ошибках

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

Вот пример, показывающий, как это выглядит:

@Test
public void whenComparingStrings_thenMultipleFailingAssertions() {
    String aString = "The test string";
    String anotherString = "The test String";

    checkEquals("Strings are not equal!", aString, equalTo(anotherString));
    checkTrue("String is longer than one character", aString.length() == 1);
    checkTrue("A failing message", aString.length() == 2);
}

После выполнения теста мы получаем следующий вывод:

org.junit.ComparisonFailure: Strings are not equal!
  expected:<[the test s]tring> but was:<[The Test S]tring>
// ...
java.lang.AssertionError: String is longer than one character
// ...
java.lang.AssertionError: Strings are not the same
  expected the same:<the test string> was not:<The Test String>

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

Давайте напишем тестовый метод, который реализует это на практике:

@Test
public void whenComparingNumbers_thenLoggedMessage() {
    log("There was something wrong when comparing numbers");

    int anInt = 10;
    int anotherInt = 10;

    checkEquals(anInt, 10);
    checkTrue("First number should be bigger", 10 > anotherInt);
    checkSame(anInt, anotherInt);
}

После выполнения теста мы получим следующий вывод:

org.jgotesting.events.LogMessage: There was something wrong
  when comparing numbers
// ...
java.lang.AssertionError: First number should be bigger

Обратите внимание, что в дополнение к logf(), который может форматировать сообщения как метод String.format(), мы также можем использовать методы logIf() и logUnless() для регистрации сообщений на основе условного выражения.

4.4. Прерывание тестов

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

Вот пример теста, который завершается преждевременно из-за того, что требуемый файл не существует:

@Test
public void givenFile_whenDoesnotExists_thenTerminated() throws Exception {
    File aFile = new File("a_dummy_file.txt");

    terminateIf(aFile.exists(), is(false));

    // this doesn't get executed
    checkEquals(aFile.getName(), "a_dummy_file.txt");
}

Обратите внимание, что мы также можем использовать методы terminate() и terminateUnless() для прерывания выполнения теста.

4.5. Объединение в цепочку

Класс JGoTestRule также имеет гибкий API, который мы можем использовать для объединения проверок в цепочку.

Давайте рассмотрим пример, который использует наш экземпляр JGoTestRule для объединения нескольких проверок объектов String:

@Test
public void whenComparingStrings_thenMultipleAssertions() {
    String aString = "This is a string";
    String anotherString = "This Is a String";

    test.check(aString, equalToIgnoringCase(anotherString))
      .check(aString.length() == 16)
      .check(aString.startsWith("This"));
}

4.6. Пользовательские проверки

Помимо логических выражений и экземпляров Matcher, методы JGoTestRule могут принимать пользовательский объект Checker для выполнения проверки. Это интерфейс единого абстрактного метода, который можно реализовать с помощью лямбда-выражения.

Вот пример, который проверяет, соответствует ли String определенному регулярному выражению, используя вышеупомянутый интерфейс:

@Test
public void givenChecker_whenComparingStrings_thenEqual() throws Exception {
    Checker<String> aChecker = s -> s.matches("\\d+");

    String aString = "1235";

    test.check(aString, aChecker);
}

5. Заключение

В этом кратком руководстве мы рассмотрели функции, которые JGoTesting предоставляет нам для написания тестов.

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

«Как всегда, полный исходный код этой статьи можно найти на Github.