Оптимизация процесса тестирования по С с использованием эвристического анализа тестового покрытия кода (1187409), страница 5
Текст из файла (страница 5)
Сопоставление покрытия и измененийОпишем все возможные интеракции между данными о покрытии икодовой базой.321. Удаление теста. Удаляем тест. В этом случае каскадом будутудалены данные о покрытии из таблицы Coverage.2. Добавление теста. Добавляем запись в таблицу Test, а также данныео покрытии в таблицу Coverage после его запуска.3.
Изменение теста. Фактически, равносильно удалению старого тестаи добавлению нового - покрытие могло значительно измениться.Удаляем данные о старом тесте, добавляем данные о новом.4. Изменение кода. Согласно алгоритму, будут запущены тесты,которые покрывали этот код, но только те, что помещаются вуказанное ограничение по времени. Данные о покрытии для этихтестов будут обновлены. Данные о покрытии для тестов, чтозапущены не были, останутся прежними. При удалении строк,данные о них удаляются. Однако требуется произвести сдвиг другихстрок на место удаленных.6.7. Вычисление разницы между областями покрытияКак было указано ранее, в качестве хранилища мы будем использоватьsqlite базу с одной таблицей. Так как алгоритм вычисления уникальногопокрытия является последовательным, то все уникальные строки для тестаk можно получить с помощью выбора всех строк из таблицы Coverage,для которых test_id будет равен k, если не существует строки с тем женомером, для которых test_id принадлежит множеству рассмотренныхранее тестов.6.8.
Интерфейс для работы с тестирующей системойДля запуска тестов на языке C требуется перекомпилировать программу.GNU make является одной из наиболее популярных утилит для[12]автоматизации сборки и тестирования проектов.Внедрение утилитыдолжно ложиться на плечи сотрудника, в должностные обязанности33которого входитразработка и внедрение систем автоматизации инепрерывной интеграции. Альтерация Makefile - действие достаточнопростое, однако из-за отсутствия общего стандарта по поиску и запускутестов, предоставить универсальное решение по интеграции являетсядостаточно сложной задачей.
Для упрощения данного процесса, утилитадолжна быть понятной для разработчика любого уровня и зависеть толькоот своей базы данных. Это означает, что для ее внедрения требуетсяминимальное количество усилий:1. Инициализация2. Изменение Makefile с полного запуска тестов на запуск только техтестов, что перечислены в результате работы утилиты.3. Периодическое обновление полной информации о покрытииБлагодаря простоте схемы базы данных, весь процесс обновления утилитызаключается в замене исполняемого файла. В случае, если формат БДбудет изменен, существуют доступные решения по безболезненноймиграции данных, например, alembic.6.9. Инициализация и поддержание актуальности своих данныхИнициализация производится путем получения транслятором полнойинформации о покрытии, то есть последовательности пар путей к тестам исоответствующих им результатов работы анализатора.После каждого запуска утилиты необходимо обновить информацию опокрытии запущенных тестов.
Так как приоритет при запуске получаюттесты, покрывающие наибольшее количество строк за наименьшее время,то средняя консистентность данных будет меняться достаточно медленно.Как мы указывали ранее, такие “оптимальные” тесты обычно являютсяобщими проверками, быстро проверяющими основной функционал.Вероятность того, что объем затронутого кода для тестов будет уменьшен34- достаточно низка, из чего следует, что большая часть записей о покрытиибудет оставаться актуальной.
Однако для точности и полной проверкиработоспособности продукта требуется периодически запускать все тесты.Одной из функций утилиты может быть предоставление оптимальногопериода полного тестирования, исходя из скорости устаревания базы.6.10. Полная схема утилитыПостараемся достичь максимальной модульности и обособленностисоставных частей утилиты. Это также упростит тестирование ее самой.6.10.1. ТрансляторПринимает в качестве входных параметров результат работы анализаторапокрытия (в конкретном случае - xml выдачу gcov).
Из входных данныхизвлекаются данные о строках, а также путь к тесту. Данные о тестеудаляются, после чего записываются новые.6.10.2. Обработчик измененийНа вход получает выдачу в формате утилиты GNU diff (например,результат работы git diff).[17] Помечает все тесты как обычные. В случаеудаления строк удаляет строки в базе. Сдвигает строки в случае35добавления, но не добавляет новых записей. Описанным ранее способомвыделяетмножествотестовдляпокрытияизменений.Помечаетвыбранные тесты как приоритетные.6.10.3. Алгоритм выбора тестовДанный модуль работает только с базой и заданным ограничением повремени. Результатом является список путей к рекомендуемым дляисполнения тестам.
Алгоритм работает в два этапа - сначала выбираютсяпопадающие в интервал тесты из помеченных, после чего происходитдобор из оставшихся.6.11. Рекомендации по использованию и ограничения1. Независимость тестов с точки зрения логики и порядка запуска.Хотя повторение именно логической части теста не помешает работеутилиты, ее эффективность будет ниже. Зависимость же тестов отпорядказапускаполностьюотметаетвозможностьвыбораконкретных тестов с соблюдением их валидности.2. Отсутствие метапрограммирования, а также зависимости результатаработы утверждения от его позиции в коде.
В этих случаях оценкапоследствий изменений, опирающаяся лишь на данные о покрытии ипозициях строк, перестает работать в принципе.3. Утилиту рекомендуется использовать на уровне конкретныхразработчиков, желающих удостовериться, что их изменения неповлекли за собой обширных проблем.
Это знание являетсясерьезным фактором для процесса ревью, для уверенностиразработчика в своих действиях, а также спасает от бесполезнойтраты машинного времени.4. Периодический запуск всех тестов. Для обеспечения качествапродукта этого не избежать. Предлагается работа в двух циклах36тестирования. Малый цикл - per-commit запуск оптимального наборатестов для снижения шанса попадания ошибок в билд. Большойцикл - per-build запуск всего тестового набора для доказательствавалидности накопленных изменений.5.
Многие VCS позволяют делать такую вещь, как коммит-хук - запускскриптов при коммите. Интегрировав утилиту подобным образом всерверсистемы,пулл-реквестов,можнопозволяяснизитьсократитьколичествовремя,невалидныхпотраченноеразработчиками на поиск потенциальных ошибок.6. Требования по работе с окружением. Для каждого окружениянеобходимо поддерживать собственную базу данных, так как взависимости, например, от флагов компиляции, данные о покрытиибудут разниться.377. Экономическая эффективностьПри рассмотрении ситуации, решением которой является полученнаяоптимизация, будет получена выгода в виде сэкономленных часов работынад проектом.
Обычно, если наличествует длительный этап, не требующийнепосредственного участия человека, менеджмент назначает работникунесколько задач одновременно. Но даже при работе над несколькимиправками кода в параллели, в какой-то момент разработчик будетвсе-равно заблокирован тестами, вследствие чего не сможет продолжатьэффективную работу.Рассмотрим два исходных случая.1. Процесс непрерывной интеграции не налажен. В таком случаетестирование проводится по требованию, обычно перед сборкой.Велики риски нахождения проблем только на конечном этапе цикларазработки.
Утилита позволяет внедрить практику непрерывнойинтеграции, существенно снижая риски, а также потенциальныетраты ресурсов на экстренные исправления.2. Процесс непрерывной интеграции налажен. Разработчик вынужденждать непропорционально огромное время, чтобы продолжитьработу. Оптимизационная утилита позволяет сместить длительныйавтоматический этап на нерабочее время (например, ночь, иливыходные),приэтомсохраняявыгодыотнепрерывноготестирования. В данном случае повышается эффективность работы38программистов, а также снижаются затраты на непосредственнотестирование.8. Прикладные расчеты и результатыПроверим на существующем проблемном проекте исследуемый алгоритмоптимизации.8.1 ПроектВ качестве основы для проведения расчетов эффективности был взятрепозиторий одного из компонент продукта Acronis Cloud Platform.
Вданном репозитории используется язык python, для которого интеграция сутилитой не требует дополнительных решений, что послужило основнойпричиной его выбора. Данный продукт является проприетарным, так что висследовании будут продемонстрированы только статистические данные.Для их получения используются базовые возможности git. В статистикеуказывается лишь фактическое состояние ветки master на данный моментв силу удаления ветвей после успешного слияния, то есть мы располагаемданными только о коммитах, прошедших тестирование и слитых в master.Ниже представлена необходимая информация о проекте, а также графикироста репозитория и распределение коммитов по времени суток.39Статистика репозиторияОбъем кодаОбъем тестовТестовый цикл13740 строк18810 строк~120 минутКоммитыСтатистикаизмененийСтатистикакоммитов2678 (1834)55 строк/коммит~9 в рабочий деньИзменения кодаИзменения тестовВремя разработки64220 строк36987 строк282 рабочих дня408.2 РасчетыРассчитаем, сколько времени было потрачено на тестирование.Проект использует jenkins в качестве системы непрерывной интеграции.[18]Запуск тестов происходит для каждого коммита в pull-request.Согласностатистике ci-системы, в 36% случаев тесты были провалены.