Политика тестирования
Компания QApp уделяет особое внимание тестированию и безопасности создаваемых решений
Практическое тестирование реализации
Анализ кода

Проверка форматирования
Каждый push сопровождается автоматической проверкой форматирования, что позволяет поддерживать единый стиль кода.
Инструменты: clang-format, autopep8.

Статический анализ
Автоматический поиск потенциальных ошибок в коде без его выполнения. Позволяет на раннем этапе повышать качество кода.
Инструменты: clang-tidy.

Code-review
В процессе приемки задачи участвуют как минимум два участника команды.

Инспекции кода специалистами по безопасности
Периодический просмотр кода специалистами по безопасности(ASE). На основе найденных уязвимостей проводятся семинары и заводятся задачи для разработчиков. Найденные уязвимости оцениваются по шкале: Critical, High, Low, None. Уязвимости уровней Critical и High закрываются в первом приоритете.

Функциональное тестирование

Модульные тесты
Тестируются как внешние интерфейсы, так и внутренние реализации. Итоговое покрытие кода превышает 90%.
Инструменты: Googletest, gcovr.

Модульные тесты с использованием санитайзеров
В процессе тестирования используется набор санитайзеров для компиляторов GCC и CLang. Код инструментируется дополнительными инструкциями на этапе компиляции, затем выполняется в специально подготовленном окружении. Краткий список того, что ищут санитайзеры:
  • Ошибки при работе с памятью.
  • Утечки памяти.
  • Гонки данных (data races).
  • Ошибки переполнения.
  • Ошибки инициализации.
  • Ошибки по работе с типами.
  • Недопустимые арифметические операции.
  • и т.д.
Инструменты:
Интеграционные тесты
Разностороннее тестирование внешней функциональности (API). Основные направления:
  • Граничные значения.
  • Некорректные входные данные.
  • Изменение промежуточных данных.
  • Подключение разных источников энтропии.
Документация к интеграционным тестам пишется прямо в комментариях к коду. Сценарии и параметры описываются с помощью doxygen-тегов. В результате на выходе получается готовая тестовая документация в формате BDD.
Инструменты: Googletest, Doxygen

End-To-End тесты
Для поставки клиентам собирается пакет, содержащий необходимое ПО и документацию. Каждый пакет проходит автоматическое тестирование в чистой среде. Проверяются:
  1. Название пакета
  2. Состав пакета
  3. Установка содержимого пакета
  4. Работа примеров использования
  5. Документация
Инструменты: pytest.

Тесты интеграции с другими продуктами
Применяется политика привязки к конкретным версиям зависимых продуктов. Это может быть название тега или, в крайнем случае, ветки. Используются готовые артефакты на CI. Таким образом, тест работает с уже собранными артефактами. В результате получаем постоянно готовую к работе интеграцию.
Инструменты: pytest

Системное тестирование

Тестирование производительности
Тестирование производительности алгоритмов решает следующие задачи:
  1. Отслеживание динамики изменения производительности между версиями.
  2. Сравнение с альтернативными реализациями.
  3. Получение статистики времени, затрачиваемого на обработку разных входных данных. Это помогает проверять реализации на устойчивость к timing-атакам.
Инструменты: Google.Benchmark, SUPERCOP.

Fuzzy-тестирование
Помогает исследовать устойчивость ПО к случайным, в т.ч. некорректным, входным данным. Результатом является:
  1. Набор файлов, охватывающий все найденные пути в коде. Полученный набор может в дальнейшем использоваться для тестирования на timing-атаки.
  2. Набор файлов, которые вызвали падение или зависание ПО.
Инструменты: AFL (American Fuzzy Lop).

Тестирование на устойчивость к timing-атакам
Один из ключевых видов тестирования для криптографического ПО. Два направления развития:
  1. Разработка собственного фреймворка, оценивающего статистику времени выполнения на основе выходных данных фаззера.
  2. Интеграция dudect - специализированного инструмента для оценки статистики времени выполнения кода.
Инструменты: собственный фреймворк, dudect.

Аудиты безопасности
Поиск уязвимостей с использованием специализированных инструментов для статического и динамического анализа.
Инструменты:
  1. Для динамического анализа: GDB/GDBSERVER, GEF
  2. Для статического анализа: IDA, Ghydra, Unicorn
  3. Для декомпиляции и динамической инструментации Android-приложений: JEB, JADX, Frida

CI

Центральным звеном всего процесса разработки является CI. Там выполняются все автоматизированные тесты, а также сборка и тестирование пакетов.
Инструменты: GitLab.

Уровни сборки
Разработано несколько уровней сборки, где регулируется:
  1. Набор тестируемых конфигураций.
  2. Выполнение самых затратных Job. Например, это касается тестов производительности и тестов на timing-атаки.

Самый быстрый и поверхностный уровень - для сборки и тестирования feature-веток:
Pipeline для feature-веток
Самый медленный и полный - для обновлений master-ветки и ночных сборок:
Часть pipeline-а для обновлений master-ветки и ночных сборок
Также добавлен набор manual-job, где можно вручную указать, какие Job необходимо выполнить:
Часть pipeline-а для запуска Job вручную
Ночные сборки
Выполняются ежесуточные ночные сборки master- а. Применяется максимальный набор конфигураций.

Workflow разработки

Команда использует простой, но эффективный Workflow:
Workflow разработки

Теоретическая валидация
  • Доказательство секретности.
  • Бенчмаркинг квантово-безопасных алгоритмов.