То, что я не применяю юнит-тесты, не значит, что я не тестирую ПО вообще.
Внёс правку, потыкал -- вроде работает. Обычно при тестировании используешь какие-то типовые значения, которые удобно вводить. Типовые -- это круглые. Но реальность не круглая.
Сохраняю в файл два графика, измеренные одновременно за 2 секунды. Всё замечательно работает. Когда начинаются эксплуатационные замеры, оказывается, что выходной файл периодически не открывается. Сначала я думал, что не открываются слишком длинные файлы, но это оказалось не так.
Для хранения у нас используется собственный формат данных, исторический. Функцию сохранения я взял готовую, написанную предками, и модифицировал под свои нужды. Утилита по считыванию доступна в исходных кодах, что позволило мне запустить отладку и посмотреть, где происходит сбой. Причина оказалась простой -- для второго графика сбивается смещение внутри файла, поэтому он начинает считываться с места, где мусор. Но почему это происходит?
ОКАЗАЛОСЬ
Что когда время некруглое, то в графиках может оказаться разное число точек, которое отличается на единицу. При этом вычисление числа точек для поля "число точек" происходит один раз и по одной формуле, а фактическая запись точек делается в другом месте -- и формула там уже другая. Когда время круглое и количество точек одинаковое -- формулы дают одинаковый результат. А когда время некруглое -- числа разные.
***
Я сам мало знаю о модульном тестировании, но может быть, кто-нибудь из читателей знает? Как вы боретесь с подобными ситуациями? Практикуется ли в модульном тестировании рандомизация входных параметров от запуска к запуску чтобы ловить такие ошибки?
Внёс правку, потыкал -- вроде работает. Обычно при тестировании используешь какие-то типовые значения, которые удобно вводить. Типовые -- это круглые. Но реальность не круглая.
Сохраняю в файл два графика, измеренные одновременно за 2 секунды. Всё замечательно работает. Когда начинаются эксплуатационные замеры, оказывается, что выходной файл периодически не открывается. Сначала я думал, что не открываются слишком длинные файлы, но это оказалось не так.
Для хранения у нас используется собственный формат данных, исторический. Функцию сохранения я взял готовую, написанную предками, и модифицировал под свои нужды. Утилита по считыванию доступна в исходных кодах, что позволило мне запустить отладку и посмотреть, где происходит сбой. Причина оказалась простой -- для второго графика сбивается смещение внутри файла, поэтому он начинает считываться с места, где мусор. Но почему это происходит?
ОКАЗАЛОСЬ
Что когда время некруглое, то в графиках может оказаться разное число точек, которое отличается на единицу. При этом вычисление числа точек для поля "число точек" происходит один раз и по одной формуле, а фактическая запись точек делается в другом месте -- и формула там уже другая. Когда время круглое и количество точек одинаковое -- формулы дают одинаковый результат. А когда время некруглое -- числа разные.
***
Я сам мало знаю о модульном тестировании, но может быть, кто-нибудь из читателей знает? Как вы боретесь с подобными ситуациями? Практикуется ли в модульном тестировании рандомизация входных параметров от запуска к запуску чтобы ловить такие ошибки?
19.03.2021 в 17:42
-- Minoru
19.03.2021 в 17:50
19.03.2021 в 18:06
именно что есть поле "число точек" в заголовке, а когда дело доходит до записи самих точек, там число точек вычисляется заново, а не берётся уже готовое значение, вычисленное ранее. Это легаси-код, который стабильно работал для одного графика и для нескольких с равным числом точек. А после моих модификаций число точек стало разным -- и формулы при записи заголовка и самих точек стали давать разные результаты.
Xersareeth, какой фреймворк?
19.03.2021 в 18:15
19.03.2021 в 19:00
Раз это легаси, то имело бы смысл сначала покрыть код тестами, а уже потом что-то менять. Полезно чем-нибудь измерять покрытие и стремиться довести его до 100% — в погоне за последними процентами обычно приходится читать код и плотно думать, и ты мог бы либо просто угадать, что баг существует, либо заметить, что количество точек рассчитывается в двух разных местах (и по-разному).
Ты мог бы нечаянно написать тесты только для случая, когда в файлах равное количество точек, и таким образом прозевать баг (покрытие 100%, а баг есть!). От такого тебя бы спасло ревью кода: второй разработчик мог бы усомниться, почему ты тестируешь только этот случай, и вы бы вскрыли существование бага.
В конце концов, да, ты мог бы написать рандомизированные тесты. Посмотри на rapidcheck и генераторы в Catch2. Для Си я подобных библиотек не знаю. Но там придётся писать генераторы реалистичных данных, для сложных форматов это будет тяжёлой задачей. Кроме того, чем крупнее генератор, тем больше возможностей закодировать в него какие-нибудь предпосылки, например, что в файлах всегда одинаковое количество точек
Пользуюсь на практике всеми тремя методами, но баги все равно лезут
-- Minoru
19.03.2021 в 19:29
Minoru, спасибо за комментарий. За уточнениями я тебе в жаббер написал.
19.03.2021 в 20:34
20.03.2021 в 11:30
Мне было лень заморачиваться с библиотеками и я в своём js коде, где подобное требовалось (пара функций - генератор и парсер токенов), набил пачку массивов возможных входов для каждого аргумента, потом сделал на коленке генератор декартова произведения, запускал функцию на каждой строчке и после проверял инварианты выхлопа.
Ну типа так:
В принципе вместо массивов и декартова произведения можно наколхозить генератор рандомных значений с заданными разумными границами для каждого аргумента.