Поиск…


Вступление

Модульные испытания являются неотъемлемой частью разработки, основанной на тестах, и важной особенностью для создания любого надежного приложения. В Java модульное тестирование почти исключительно выполняется с использованием внешних библиотек и фреймворков, большинство из которых имеют свой собственный тег документации. Этот заглушка служит средством для ознакомления читателя с доступными инструментами и их соответствующей документацией.

замечания

Структуры тестовых модулей

Для модульного тестирования в Java существует множество возможностей. Самым популярным вариантом является JUnit. Он документируется следующим образом:

JUnit

JUnit4 - Предлагаемый тег для функций JUnit4; еще не реализованы .

Существуют другие платформы тестирования модулей и доступны документация:

TestNG

Инструменты для тестирования единиц

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

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

JBehave - BDD Framework. Позволяет связать тесты с пользовательским поведением (разрешая проверку требований / сценариев). Отсутствие ярлыков документов на момент написания; вот внешняя ссылка .

Что такое Unit Testing?

Это немного грунт. В основном это связано с тем, что документация вынуждена иметь пример, даже если он предназначен как статья-заглушка. Если вы уже знаете основы модульного тестирования, не стесняйтесь переходить к замечаниям, где упоминаются конкретные рамки.

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

Рассмотрим следующий (тривиальный) псевдо-пример:

public class Example {
  public static void main (String args[]) {
    new Example();
  }

  // Application-level test.
  public Example() {
    Consumer c = new Consumer();
    System.out.println("VALUE = " + c.getVal());
  }

  // Your Module.
  class Consumer {
    private Capitalizer c;
  
    public Consumer() {
      c = new Capitalizer();
    }

    public String getVal() {
      return c.getVal();
    }
  }

  // Another team's module.
  class Capitalizer {
    private DataReader dr;
  
    public Capitalizer() {
      dr = new DataReader();
    }

    public String getVal() {
      return dr.readVal().toUpperCase();
    }
  }

  // Another team's module.
  class DataReader {
    public String readVal() {
      // Refers to a file somewhere in your application deployment, or
      // perhaps retrieved over a deployment-specific network.
      File f; 
      String s = "data";
      // ... Read data from f into s ...
      return s;
    }
  }
}

Итак, этот пример тривиален; DataReader получает данные из файла, передает его в « Capitalizer , который преобразует все символы в верхний регистр, который затем передается Consumer . Но DataReader сильно связан с нашей прикладной средой, поэтому мы откладываем тестирование этой цепочки, пока не готовы к развертыванию тестовой версии.

Теперь предположим, что где-то по пути в релизе по неизвестным причинам метод getVal() в Capitalizer изменился с возврата строки toUpperCase() строку toLowerCase() :

  // Another team's module.
  class Capitalizer {
    ...

    public String getVal() {
      return dr.readVal().toLowerCase();
    }
  }

Ясно, что это нарушает ожидаемое поведение. Но из-за трудных процессов, связанных с выполнением DataReader , мы не заметим этого до нашего следующего тестового развертывания. Таким образом, дни / недели / месяцы проходят с этой ошибкой, сидящей в нашей системе, а затем менеджер продукта видит это и мгновенно обращается к вам, руководителю группы, связанному с Consumer . «Почему это происходит? Что вы, ребята, изменили?» Очевидно, ты не знаешь. Вы понятия не имеете, что происходит. Вы не изменили код, который должен касаться этого; почему это внезапно нарушено?

В конце концов, после обсуждения между командами и совместной работой проблема прослеживается, и проблема решена. Но он задает вопрос; как это могло быть предотвращено?

Есть две очевидные вещи:

Тесты должны быть автоматизированы

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

Вы должны оценить, что в этом примере я изложил одну очень тривиальную ошибку, которая была введена и незаметна. В промышленном применении с постоянно обновляющимися десятками модулей они могут ползти повсюду. Вы исправляете что-то с помощью одного модуля, только чтобы понять, что само поведение, которое вы «зафиксировали», каким-то образом опиралось на другое (внутреннее или внешнее).

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

Тесты должны быть мелкозернистыми

Вторая проблема, отмеченная в нашем примере выше, - это время, затраченное на прослеживание ошибки. Менеджер продукта пинговал вас, когда тестеры заметили это, вы исследовали и обнаружили, что « Capitalizer возвращал, казалось бы, плохие данные, вы пинали команду « Capitalizer » вашими результатами, они исследовали и т. Д. И т. Д. И т. Д.

То же самое, что я сделал выше о количестве и сложности этого тривиального примера, здесь. Очевидно, что любой разумно хорошо разбирающийся в Java может быстро найти введенную проблему. Но часто и гораздо труднее отслеживать и передавать проблемы. Возможно, команда Capitalizer предоставила вам JAR без источника. Возможно, они расположены на другой стороне мира, а часы общения очень ограничены (возможно, по электронной почте, которые отправляются один раз в день). Это может привести к ошибкам, требующим недель или больше для отслеживания (и, опять же, для данной версии может быть несколько).

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

Введите модульное тестирование

Представьте себе, если бы у нас был тест, в частности, чтобы метод getVal() Capitalizer возвращал getVal() строку для данной входной строки. Кроме того, представьте, что тест был выполнен до того, как мы даже совершили какой-либо код. Ошибка, введенная в систему (то есть toUpperCase() заменяется на toLowerCase() ), не вызовет проблем, потому что ошибка никогда не будет введена в систему. Мы поймаем его в тесте, разработчик (надеюсь) осознает свою ошибку, и будет найдено альтернативное решение о том, как внедрить их предполагаемый эффект.

Здесь приводятся некоторые упущения в отношении того, как выполнять эти тесты, но они описаны в документации по структуре (см. Примечания). Надеюсь, это служит примером того, почему модульное тестирование важно.



Modified text is an extract of the original Stack Overflow Documentation
Лицензировано согласно CC BY-SA 3.0
Не связан с Stack Overflow