В связи с расширением использования CI/CD и гибких методологий разработки как никогда важно обеспечить, чтобы процесс разработки был настолько полным, насколько это возможно. Большинство типичных конвейеров состоят из этапа компиляции, на котором компилируется код, затем следует этап интеграции, на котором выполняются КАК модульные тесты, так и интеграционные тесты, чтобы гарантировать, что новые изменения не нарушают предыдущие версии кодовой базы. Как правило, конвейер может завершаться созданием отчетов или выпуском артефактов на промежуточные или производственные серверы или контейнеры и т.д. Мы сосредоточимся на интеграционных тестах.
Интеграционные тесты
Интеграционные тесты важны, потому что они тестируются на другом уровне абстракции, чем модульные тесты. В то время как модульные тесты проверяют правильность отдельного фрагмента кода с учетом конкретных данных и ожидаемого результата, интеграционные тесты идут на шаг выше в абстракции и могут типично тестировать потоки кода, которые имеют дело с такими вещами, как подключения к базе данных или взаимосвязанные потоки проверки определенного ожидаемого результата после запуска нескольких приложений Spring CLI, входы которых зависят друг от друга.
Java обладает несколькими интересными функциями, которые позволяют нам проверять такие вещи, как структура базы данных и выполнение определенных потоков в приложении. Все это полезно при написании интеграционных тестов, давайте посмотрим.
Использование ресурсов класса для “хранения” тестовых данных
Ресурс – это данные (изображения, аудио, текст и т. Д.), К которым программа должна получить доступ способом, не зависящим от расположения программного кода.
Это может быть особенно полезно, если классы, интеграцию с которыми вы хотите протестировать, зависят от внешних данных, таких как входные файлы или конкретные аргументы конфигурации, что обычно имеет место для приложений Spring CLI, которые добавляют функциональность к определенной кодовой базе, такой как заполнение баз данных или использование внутренней логики для получения значимых вычислений из входных данных.
Доступ к ресурсам класса может быть осуществлен с помощью методов в классах Класс
и Загрузчик классов
это обеспечивает независимый от местоположения способ поиска ресурсов.
Как правило, идея заключается в том, что, когда требуется доступ к файлу, будь то в целях настройки для выполнения некоторого потока кода или как часть всей идеи интеграционного теста (т.Е. “если этот файл используется для запуска этого конкретного приложения Spring CLI, и его вывод требуется другому, тогда, в счастливом пути, определенный результат должен быть проверен”), мы можем использовать методы из java.lang. Класс
в наших интересах. Ниже приведен код очень полезного getResourceAsStream
:
public InputStream getResourceAsStream(String name) { name = resolveName(name); ClassLoader cl = getClassLoader0(); if (cl==null) { // A system class. return ClassLoader.getSystemResourceAsStream(name); } return cl.getResourceAsStream(name); }
Этот метод можно использовать для извлечения определенного файла, который либо был помещен в папку ресурсы
определенного пакета, либо из загрузчика системных классов, который в основном делегируется встроенному загрузчику классов виртуальной машины.
С помощью этого мы можем загружать файлы для использования в нашем тестовом коде, чтобы запустить определенный поток, например:
InputStream f = getClass().getResourceAsStream("/test.yml"); File config = new File("test.yml"); try { org.apache.commons.io.FileUtils.copyInputStreamToFile(f, config); } catch (IOException e) { e.printStackTrace(); } SomeSpringApp.main(new String[]{config.toPath().toString(), "outputFile.txt"} File output = new File("outputFile.txt"); //for a given input file, we always need to ensure we have an output file assertTrue(output.length()>0);
Таким образом, мы можем использовать файлы для эмуляции того, что было бы реальным вариантом использования нашего приложения, вместо тестирования поведения на уровне модуля. В этом и заключается суть интеграционного теста.
Использование JDBC для доступа к базе данных
Последний полезный совет, который у меня есть, заключается в том, что, если по какой-то причине мы создали базу данных в рамках нашего интеграционного теста, нам может потребоваться доступ к ней впоследствии, а именно, если мы хотим проверить, существует ли определенная таблица или создана успешно. Чтобы сделать это, нам нужно сначала установить соединение, использовать учетные данные БД, чтобы иметь возможность запрашивать его, выполнять наши действия и впоследствии закрывать соединение. JDBC – Подключение к базе данных Java – это API, который предоставляет набор методов для доступа к базе данных из кода Java. Без лишних слов, вот код для подключения к определенной базе данных и проверки наличия таблицы:
final String JDBC_DRIVER = "org.mariadb.jdbc.Driver"; final String DB_URL = "jdbc:mysql://localhost/"; final String USER = " "; final String PASS = " "; Connection conn; Statement stmt; try { Class.forName(JDBC_DRIVER); LOG.info("Connecting to the selected database..."); conn = DriverManager.getConnection(DB_URL, USER, PASS); LOG.info("Connected to database successfully..."); stmt = conn.createStatement(); DatabaseMetaData meta = conn.getMetaData(); ResultSet res = meta.getTables(null, null, " ", new String[] {"TABLE"}); assertNotNull(res); assertTrue(res.next()); String sql = "DROP DATABASE "; stmt.executeUpdate(sql); LOG.info("Database deleted successfully..."); } catch (SQLException e) { e.printStackTrace(); }
По сути, используя JDBC, мы можем установить соединение через драйвер, который будет внутренне сопоставлять спецификацию конкретного поставщика БД с внутренними компонентами, реализованными на стороне Java, и с помощью этого соединения мы можем создавать операторы и и выполнять запросы, вызывая метод executeUpdate
и у нас также есть доступ к Набору результатов
, который позволяет изучать информацию и структуру об определенном запросе к БД. Таким образом, мы можем обогатить наш интеграционный тест интеграцией и проверкой базы данных, что может оказаться очень полезным для проверки правильности кода (или иногда просто целостности: базы данных могут быть полностью пустыми, но простой факт, что тест прошел успешно и определенная таблица существует, может быть очень значимой информацией для определенных потоков кода).
Вывод
Использование ресурсов класса и использование JDBC – это два полезных способа, с которыми я недавно столкнулся при написании полных и значимых интеграционных тестов, которые могут обеспечить хорошую обратную связь для определенных потоков кода и помочь вам и вашей команде разрабатывать, расширять и изменять определенные потоки кода.
Оригинал: “https://dev.to/brunooliveira/java-tips-for-improving-your-integration-tests-2lpp”