Общие модульные тесты в Java (1): JUnit
Общие модульные тесты в Java (1): JUnit

Почему мы не можем хорошо писать модульные тесты

Существует множество ситуаций, когда юнит-тесты не могут быть написаны хорошо. Зачастую на нас оказывают давление требования, и мы непроизвольно начинаем «писать случайные вещи». Иногда мы даже не знаем, как долго может работать этот проект. Как только проект выпущен, он может снова и снова входить в цикл разработки другого проекта, и времени на написание модульных тестов нет.

У разработчиков есть 10 000 причин не писать модульные тесты:

  • Недостаточно времени: Обычно цикл итерации в проекте короткий.,Короткое время, тяжелые задачи,Вчера вечером лидеру пришла в голову замечательная идея.,Мне бы хотелось выйти в Интернет сегодня утром,Разработчики борются,Нет времени писать Модульное тестирование😤.
  • Неопределенный спрос: Для проектов с особенно большими изменениями спроса напишите сегодня из Модульное Кстати, завтра его не будет, даже только что закончил писать Модульное Кстати, требования изменились. Некоторые из них одновременно разрабатывают и корректируют требования. Таким образом, невозможно написать Модульное заранее. недавно или наверстали упущенное потом. Если все привыкли каждый день менять свои требования, кто напишет Модульное тестированиеах 😈。
  • Разработка слишком сильно полагается на команду тестирования: думать, что тестирование — это ответственность команды тестирования. Если не написать две ошибки, что будет с их производительностью 😂.
  • верно Модульное обучениеиз Низкая осведомленность: Дело не в том, что его нельзя использовать, просто через это надо пройти самому. 😠。
  • верно Модульное обучение Нет четких требований. компания QA команда, даже развитие Leader верно ВМодульное в обучении нет четкого требования к из, поэтому не пишите Модульное информация. (Никто не пишет, я не могу их заманить в ловушку) 😔)
  • недостаток Модульное Обучение Необходимые навыки и инструменты: Большинство из них также продолжают существовать до main и System.out метод проведения тестирования, который неэффективен и оставляет множество бесполезных методов. 🐌。

Конечно дело не только в модульном тестировании, ведь разработка даже комментариев не пишет 😂🤣😂.

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

1. Качество кода

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

2. Раннее обнаружение дефектов программного обеспечения

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

3. Легко рефакторить

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

Поскольку разработчики добавляют в программное обеспечение все больше и больше функций,Иногда необходимо изменить старый код дизайни. Однако,Менять уже протестированный код рискованно и дорого. Если у нас есть соответствующее из Модульное Сегодня мы сможем с уверенностью провести рефакторинг.

4. Упростите процесс отладки

Модульные тесты помогают упростить процесс отладки. Если тест не пройден, то нужно отлаживать только последние изменения в коде.

5. Предоставить документацию

Модульное Обновление предоставляет систему документации. Разработчики, которые хотят знать, какие функции предлагает модуль и как он работает, могут проверить Модульное. Хотите получить базовое представление об интерфейсе устройства (API) из.

6. Дизайн

Написание тестов сначала заставляет вас тщательно подумать о своем проекте и о том, чего он должен достичь, прежде чем писать код. Это не только поможет вам сосредоточиться, но и позволит создавать более качественные проекты. Тестирование фрагмента кода заставляет вас определить, за что этот код отвечает. Если вы можете сделать это легко, это означает, что обязанности кода четко определены и поэтому он очень связан.

Конечно, если вам интересно, вы можете взглянуть на «Test Driven Development TDD».

7. Сократите затраты

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

Как писать модульные тесты

Выше упомянуто так много многословных вопросов, так как же нам их написать? Сначала мы должны прояснить, что мы пишем Модульное тестирование Цельных принципов:

Цель

  • существуют фаза разработки сокращена заранее Bug
  • Улучшить освещение Модульного тестирования
  • существовать Время рефакторинга,Возможно проверочное тестирование

в принципе

  • Независимый (может работать независимо, не влияет на бизнес и не зависит от результатов сторонних сервисов)
  • Повторяемость (проверено несколько раз, результат один и тот же)
  • Автоматизация (никогда нельзя один раз запустить и один раз изменить код)
  • Есть четкие ожидания (вы знаете результат по переданным параметрам, не всегда можете Модульное случайное число теста дня)

Несколько советов (начнем писать отдельные тесты 😈)

Уведомление: следующий кодиспользовать Java 8 и Maven отсутствие ошибок в других средах не гарантируется.

бросить писать main и sysout Бар 😏

Например, мы написали класс инструмента (конкретная реализация удалена для удобства отображения). Это некоторые из наиболее часто используемых.

Язык кода:javascript
копировать
package com.example.ut.util;

import java.util.Objects;

public final class StringUtil {

  private StringUtil() {}

  public static String firstNonBlank(String... params) {}

  public static String firstNonNull(String... params) {}

  public static boolean isNullOrEmpty(String string) {}

  public static boolean isBlank(String string) {}

  public static boolean hasText(String string) {}

  public static boolean hasLength(String string) {}

  public static String commonPrefix(CharSequence a, CharSequence b) {}

  public static String commonSuffix(CharSequence a, CharSequence b) {}

  public static String lenientFormat(String template, Object... args) {}
}

Например, мы можем увидеть множество способов проверить, можно ли использовать каждый метод напрямую через основной метод в StringUtil, например этот:

Язык кода:javascript
копировать
public final class StringUtil {

  public static void main(String[] args) {
    System.out.println(firstNonBlank(null, "", "b", "", "d"));
  }

  ...
}

Есть ли смысл в таком тесте? Возможно, его действительно можно было бы использовать, когда я в то время писал код.,Но как проверить правильность? Если вы проводите рефакторинг из,Как узнать, что исходное поведение противоречиво?

использовать JUnit5 для простого теста

What is JUnit 5?

Unlike previous versions of JUnit, JUnit 5 is composed of several different modules from three different sub-projects.

JUnit 5 = JUnit Platform + JUnit Jupiter + JUnit Vintage

The JUnit Platform serves as a foundation for launching testing frameworks on the JVM. It also defines the TestEngine API for developing a testing framework that runs on the platform. Furthermore, the platform provides a Console Launcher to launch the platform from the command line and a JUnit 4 based Runner for running any TestEngine on the platform in a JUnit 4 based environment. First-class support for the JUnit Platform also exists in popular IDEs (see IntelliJ IDEA, Eclipse, NetBeans, and Visual Studio Code) and build tools (see Gradle, Maven, and Ant).

JUnit Jupiter is the combination of the new programming model and extension model for writing tests and extensions in JUnit 5. The Jupiter sub-project provides a TestEngine for running Jupiter based tests on the platform.

JUnit Vintage provides a TestEngine for running JUnit 3 and JUnit 4 based tests on the platform.

JUnit один в Java Относительно простая среда модульного тестирования, в основном предназначенная для модульного тестирования, теперь появилась. JUnit 5, Здесь тоже в основном используют JUnit 5, вместо JUnit 4。

Шаг 1. Введение зависимостей

Версия здесь произвольная, лишь бы она работала

Язык кода:javascript
копировать
<dependency>
  <groupId>org.junit.jupiter</groupId>
  <artifactId>junit-jupiter-engine</artifactId>
  <version>5.6.3</version>
  <scope>test</scope>
</dependency>
Шаг 2. Создайте тестовый код

существовать IDEA , если вы хотите написать Модульное для определенного класса или метода Обновление очень простое, непосредственно существование указывает из класса или метода. ctrl + enter, Появится быстрый запрос на создание кода, выберите Test Вот и все, выберите здесь firstNonNull,hasText,commonPrefix Давайте проверим это.

Фотографии модульных тестов

Автоматически сгенерированный код выглядит следующим образом (вы можете написать его самостоятельно, если вы с ним знакомы, но IDEA можно сгенерировать, не буду писать от руки), отмечено @Test из метода можно протестировать отдельно, если вы существуете IDEA На боковой панели вы можете увидеть небольшой зеленый кружок со стрелкой. Вы можете нажать на соответствующее исполнение. run или debug

Язык кода:javascript
копировать
import org.junit.jupiter.api.Test;

class StringUtilTest {

  @Test
  void firstNonBlank() {}

  @Test
  void hasText() {}

  @Test
  void commonPrefix() {}
}
Шаг 3:использовать JUnit 5 напиши немного кода
Язык кода:javascript
копировать
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;

class StringUtilTest {

  @Test
  void firstNonBlank() {
    // Вызовите метод, чтобы получить первую непустую строку, вот она должна быть a
    String shouldIsA = StringUtil.firstNonBlank("", null, "a", "c");
    // Определение результатов с помощью классов утверждений
    Assertions.assertEquals("a", shouldIsA);

    String shouldIsC = StringUtil.firstNonBlank("c", null, "a", "c");
    Assertions.assertEquals("c", shouldIsC);
  }

  // Можетиспользовать DisplayName доработать прототип Модульное название свадьбы проекта
  @DisplayName("Проверьте, содержит ли строка текст. Пустые строки не считаются содержащими текст")
  @Test
  void hasText() {
    // Это должно быть false, потому что null нет содержания
    Assertions.assertFalse(StringUtil.hasText(null));

    // Это должно быть false, потому что пустая строка нет содержания
    Assertions.assertFalse(StringUtil.hasText(""));

    // Это должно быть false, потому что пустая строка нет содержания
    Assertions.assertFalse(StringUtil.hasText(" "));

    // Это должно быть true, потому что a нет содержания
    Assertions.assertTrue(StringUtil.hasText(" a "));
  }

  @DisplayName("Проверить общедоступный префикс")
  @Test
  void commonPrefix() {
    // Нет общего префикса
    Assertions.assertEquals("", StringUtil.commonPrefix(" a ", "b"));
    Assertions.assertEquals(" ", StringUtil.commonPrefix(" a ", " b"));
    Assertions.assertEquals("abab", StringUtil.commonPrefix("ababa", "ababc"));
    Assertions.assertNotEquals("aba", StringUtil.commonPrefix("ababa", "ababc"));
  }
}

существования можно заказать здесь class Нажмите зеленую кнопку на экране, чтобы запустить все тесты ниже, или выберите для тестирования указанный.

Такое простое из Модульное тестирование Вот и все,Используется внутри:@Test (необходимый) Отметить это как тест, который необходимо пройтиизметод;@DispalyName (Необязательный)для тестированияметодили Красивый классизимяилиописывать;Assertions Определите, верен ли результат, с помощью серии утверждений. Этот шаг можно пройти без написания кода, но в противном случае его необходимо написать. sout Какая разница?

С помощью этих трех комбинаций вы можете выполнить ряд простых и легких шагов. Привет, взгляни ниже Assertions Какие конкретные операции определения поддерживаются? Он обеспечивает 282 методы, большинство из которых перегружены. Здесь не будут показаны все перегруженные методы.

Следующее содержимое получено из методов класса org.junit.jupiter.api.Assertions.

Описание параметра: сообщение — информация, запрашиваемая после сбоя; ожидаемый — ожидаемый результат; фактический — фактический результат;

Реализация кода на самом деле длится до тех пор, пока expected и actual Если не равно, выдать исключение.

сигнатура метода

описывать

использовать

fail(String message, Object expected, Object actual)

Вызывается напрямую для выявления сбоя тестового примера

assertTrue(boolean condition, String message)

Определить, что результат должен быть истинным

assertFalse(boolean condition, String message)

Определить, что результат должен быть ложным

assertNull(Object actual, String message)

Результат не может быть нулевым

assertEquals(Object expected, Object actual, String message)

Фактический результат должен быть равен ожидаемому результату

assertNotEquals(Object expected, Object actual, String message)

Фактический результат не должен быть равен ожидаемому результату

assertArrayEquals(Object[] expected, Object[] actual, SuppliermessageSupplier)

Оба массива должны быть равны

assertIterableEquals(Iterable expected, Iterable actual, String message)

Оба итератора должны быть равны

assertSame(Object expected, Object actual, String message)

Фактический результат должен совпадать с ожидаемым.

Например, тестирование единичного случая

assertNotSame(Object expected, Object actual, String message)

Фактические результаты не должны совпадать с ожидаемыми результатами объект

Например, тестирование нескольких случаев

assertAll(Executable… executables)

Все исполняемые файлы выполняются без исключений.

assertThrows(ClassexpectedType, Executable executable, String message)

Исключение должно быть выброшено

assertDoesNotThrow(Executable executable, String message)

Невозможно выдать исключение

assertTimeout(Duration timeout, Executable executable, String message)

Завершено в течение указанного времени выполнения, Исполняемый файл извонящийсуществовать Выполняется в том же потоке

Оценка продолжительности метода

assertTimeoutPreemptively(Duration timeout, Executable executable, String message)

Завершено в течение указанного времени выполнения, Исполняемый файл существоватьновыйиз Выполнение потока

Оценка продолжительности метода

assertLinesMatch(ListexpectedLines, ListactualLines, String message)

Соответствующие строки соответствуют обычным совпадениям, равным,Проблемы с объяснением,Рекомендуется посмотреть код,или Выбери часть и поговори о ней отдельно

существоватьвышеиз Пример,использовать Понятно assertEqualsassertFalseassertTrueassertNotEquals изиспользовать,Другие также могут попробовать это индивидуально.,использоватьметодтакой же。

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

Общие инструменты

  • JUnit
  • Mockito
  • Assertj
  • Hamrest
  • Moco
  • В сочетании с утом Spring
  • Макет объекта
  • DB

Ссылки

  1. https://junit.org/junit5/docs/current/user-guide/#overview
  2. https://www.cnblogs.com/zhuminghui/p/10788968.html
  3. https://zhuanlan.zhihu.com/p/350639096
boy illustration
Разрешение циклических зависимостей Spring Bean: существует ли неразрешимая циклическая ссылка?
boy illustration
Разница между промежуточным программным обеспечением ASP.NET Core и фильтрами
boy illustration
[Серия Foolish Old Man] Ноябрь 2023 г. Специальная тема Winform Control Элемент управления DataGridView Подробное объяснение
boy illustration
.NET Как загрузить файлы через HttpWebRequest
boy illustration
[Веселый проект Docker] Обновленная версия 2023 года! Создайте эксклюзивный инструмент управления паролями за 10 минут — Vaultwarden
boy illustration
Высокопроизводительная библиотека бревен Golang zap + компонент для резки бревен лесоруба подробное объяснение
boy illustration
Концепция и использование Springboot ConstraintValidator
boy illustration
Новые функции Go 1.23: точная настройка основных библиотек, таких как срезы и синхронизация, значительно улучшающая процесс разработки.
boy illustration
[Весна] Введение и базовое использование AOP в Spring, SpringBoot использует AOP.
boy illustration
Чтобы начать работу с рабочим процессом Flowable, этой статьи достаточно.
boy illustration
Байтовое интервью: как решить проблему с задержкой сообщений MQ?
boy illustration
ASP.NET Core использует функциональные переключатели для управления реализацией доступа по маршрутизации.
boy illustration
[Проблема] Решение Невозможно подключиться к Redis; вложенное исключение — io.lettuce.core.RedisConnectionException.
boy illustration
От теории к практике: проектирование чистой архитектуры в проектах Go
boy illustration
Решение проблемы искажения китайских символов при чтении файлов Net Core.
boy illustration
Реализация легких независимых конвейеров с использованием Brighter
boy illustration
Как удалить и вернуть указанную пару ключ-значение из ассоциативного массива в PHP
boy illustration
Feiniu fnos использует Docker для развертывания учебного пособия по AList
boy illustration
Принципы и практика использования многопоточности в различных версиях .NET.
boy illustration
Как использовать PaddleOCRSharp в рамках .NET
boy illustration
CRUD используется уже два или три года. Как читать исходный код Spring?
boy illustration
Устраните проблему совместимости между версией Spring Boot и Gradle Java: возникла проблема при настройке корневого проекта «demo1» > Не удалось.
boy illustration
Научите вас шаг за шагом, как настроить Nginx.
boy illustration
Это руководство — все, что вам нужно для руководства по автономному развертыванию сервера для проектов Python уровня няни (рекомендуемый сборник).
boy illustration
Не удалось запустить docker.service — Подробное объяснение идеального решения ️
boy illustration
Настройка файлового сервера Samba в системе Linux Centos. Анализ NetBIOS (супер подробно)
boy illustration
Как настроить метод ssh в Git, как получить и отправить код через метод ssh
boy illustration
RasaGpt — платформа чат-ботов на основе Rasa и LLM.
boy illustration
Nomic Embed: воспроизводимая модель внедрения SOTA с открытым исходным кодом.
boy illustration
Улучшение YOLOv8: EMA основана на эффективном многомасштабном внимании, основанном на межпространственном обучении, и эффект лучше, чем у ECA, CBAM и CA. Малые цели имеют очевидные преимущества | ICASSP2023