LogoRRR использует TestFX для выполнения интеграционных тестов пользовательского интерфейса JavaFX. Эти тесты дают уверенность в том, что основные рабочие процессы сохраняются при добавлении новых функций, рефакторинге и обновлении зависимостей, а также позволяют выявлять регрессии, которые невозможно заметить при модульном тестировании.
Почему именно сейчас
После выхода более 20 релизов LogoRRR стал достаточно сложным, и одного ручного тестирования стало недостаточно. Кодовой базе требовалась «сеть безопасности». TestFX позволяет управлять реальным окном приложения — нажимать кнопки, открывать файлы, проверять состояние пользовательского интерфейса — непосредственно из методов тестирования JUnit.
Решение о том, когда инвестировать в сквозные тесты (end-to-end), всегда является компромиссом. На ранних этапах проекта пользовательские интерфейсы меняются слишком быстро, и тесты не успевают за ними. Но как только основные потоки стабилизируются, тесты становятся ускорителем, а не обузой. Этот переломный момент наступил с версией 24.3.0.
Реализация
Лаконичный синтаксис Scala естественным образом подходит для создания небольшого DSL для тестирования. Каждое атомарное действие — открытие файла, нажатие кнопки закрытия, проверка того, что панель вкладок пуста — становится понятным строительным блоком:
@Test def openAndCloseTab(): Unit = {
checkForEmptyTabPane()
openFile(path)
checkForNonEmptyTabPane()
clickOn(lookup(UiNodes.LogFileHeaderTabs).query[StackPane](), MouseButton.SECONDARY)
waitAndClickVisibleItem(CloseTabMenuItem.uiNode(fileId))
checkForEmptyTabPane()
}
Написание фронтенд-тестов заставило улучшить и рабочий код. Был добавлен новый слой Service для абстрагирования ввода-вывода файлов и вызовов внешних процессов — эти изменения улучшили архитектуру независимо от пользы для самих тестов.
Что выявили тесты
- Поведение при завершении работы приложения — ресурсы, которые никогда не очищались должным образом, стали очевидны при тестировании.
- Изоляция тестов — каждый тест должен настраивать и удалять собственное состояние, что выявило несколько тонких предположений об общем состоянии пользовательского интерфейса.
- Базовый уровень производительности — отслеживание времени выполнения тестов предотвращает медленное накопление неповоротливых тестов.
Фото в заголовке: Sora Shimazaki на Pexels.
