Как создать хорошее покрытие кода логики с плавающей запятой?

Я вручную создаю новый код. Я хотел бы убедиться, что я не оставлю камня на камне.

Есть ли что-то конкретное, что я могу сделать, кроме указания контрактов кода, чтобы направлять Pex, чтобы он обеспечивал хорошее покрытие в числовом коде?

Попробуйте выполнить поиск по http://research.microsoft.com/en-us/projects/pex/pexconcepts.pdf для ключевого слова 'float' для некоторой справочной информации.

Арифметические ограничения для чисел с плавающей запятой аппроксимируются преобразованием в рациональные числа, а методы эвристического поиска используются вне Z3 для нахождения приблизительных решений для ограничений с плавающей запятой.

...а также...

Символическое обоснование. Pex использует автоматический решатель ограничений, чтобы определить, какие значения относятся к тесту и тестируемому коду. Однако возможности решателя ограничений всегда были и будут ограниченными. В частности, Z3 не может точно рассуждать об арифметике с плавающей запятой.

В качестве альтернативы, знаете ли вы инструмент для .NET, который лучше подходит для задачи поиска числовых аномалий в .NET? Мне известен http://fscheck.codeplex.com/, но он не выполняет символьные вычисления.


person GregC    schedule 26.05.2012    source источник
comment
Избегайте условных выражений, относящихся к == для floats. Вместо этого используйте < или >. Если вам нужно использовать ==, используйте выражение Math.Abs(value - target) < epsilon для любого допуска эпсилон, который вас интересует. Из-за approximation to rational отношения == слишком часто терпят неудачу, когда вы хотите, чтобы они были успешными. Но Пексу должно быть легче иметь дело с <.   -  person Jesse Chisholm    schedule 17.06.2012
comment
@JesseChisholm Мне известны инструменты статического анализа, которые позволяют находить такие ошибки кодирования. Я не уверен, как это поможет с вопросом.   -  person GregC    schedule 19.06.2012
comment
@GregC, я не уверен, что понимаю, о чем ты спрашиваешь. Вы хотите знать (A) используют ли условные операторы, которые содержат числа с плавающей запятой, допуск epsilon, или (B) ваши алгоритмы численно стабильны, или (C) просто рекомендацию для инструмента покрытия кода? Или что-то другое?   -  person Special Touch    schedule 19.06.2012
comment
(A) — ошибка кодирования, которую можно определить с помощью статического анализа. (B) можно вывести путем анализа сгенерированных тестовых входных данных. (C) Покрытие кода несложно сделать; создание значимых граничных условий для получения интересных результатов трудно сделать, и это то, что я ищу   -  person GregC    schedule 19.06.2012
comment
В NUnit вы можете сделать это: Assert.That(result, Is.EqualTo(expected).Within(.000001)); Не много знаю о Pex, но, похоже, это то, чем вы хотите заниматься.   -  person cbp    schedule 17.07.2012
comment
@cbp Я чувствую, что ваш комментарий не имеет отношения к обсуждению. Пожалуйста, посмотрите, что делает Pex; может быть, у вас будут какие-то идеи. Вы можете попробовать Pex на pexforfun.com, если не хотите возиться с его установкой.   -  person GregC    schedule 17.07.2012
comment
Это наводит меня на мысль, что нам следует избегать использования типов с плавающей запятой, если только в этом нет крайней необходимости.   -  person AndyM    schedule 10.08.2012
comment
0.0f, 0.1f, 0.9f, 1.0f, 1.1f, float.MaxValue - 0.1f, float.MaxValue -0.1f, -0.9f, -1.0f, -1.1f, float.MinValue + 0.1f, float. Минимальное значение   -  person MrFox    schedule 21.08.2012
comment
@MrFox Ваш комментарий демонстрирует пробел в понимании ошибки с плавающей запятой из-за двоичного представления. Представьте себе повторяющийся процесс, который увеличивает ошибку на каждом шагу. Теперь рассмотрим такой итеративный процесс, который занимает несколько недель на современном вычислительном кластере. Ошибка просачивается в результат. Я хотел бы, чтобы инструмент сообщал мне, когда это может произойти.   -  person GregC    schedule 21.08.2012


Ответы (1)


Вам нужно хорошее покрытие? Просто наличие теста, который запускает каждую ветвь в фрагменте кода, вряд ли на самом деле означает, что он правильный - часто это больше касается крайних случаев, и вы, как разработчик, лучше всего знаете, что это за крайние случаи. Это также звучит так, как будто это работает, просто говоря «вот интересная входная комбинация», тогда как более чем вероятно, что вы хотите указать поведение системы, которое вы хотите увидеть — если вы изначально написали код неправильно, то интересное входные данные могут быть совершенно не связаны с правильным кодом.

Возможно, это не тот ответ, который вы ищете, но я бы сказал, что лучший способ сделать это — вручную! Запишите спецификацию до того, как вы начнете программировать, и превратите ее в множество тестовых случаев, когда вы знаете/так как вы пишете API для своего класса/подсистемы.

Когда вы начнете заполнять API / писать код, вы, вероятно, подберете дополнительные фрагменты, которые вам нужно сделать, + выясните, какие сложные биты - если у вас есть условные выражения и т. д., которые вы чувствуете, что кто-то реорганизует ваш код. могут ошибаться, тогда напишите тестовый пример, который охватывает их. Иногда я намеренно пишу код неправильно в этих точках, запускаю тест, который не работает, а затем исправляю его просто для того, чтобы убедиться, что тест проверяет правильный путь в коде.

Затем попробуйте подумать о любых нечетных значениях, которые вы, возможно, не рассмотрели - отрицательные входные данные, нули и т. д. Часто это будут случаи, которые недействительны, и вы не хотите их учитывать / о которых нужно думать - в этих случаях я обычно пишу некоторые тесты сказать, что они должны генерировать исключения - это в основном останавливает людей, неправильно использующих код в тех случаях, когда вы не подумали о правильном/с неверными данными.

Вы упомянули выше, что работаете с числовым интенсивным кодом - возможно, стоит протестировать уровень выше, чтобы вы могли протестировать поведение в системе, которую вы ищете, а не просто обрабатывать числа - предполагая, что код не является чисто числовым, это будет помочь вам установить некоторые реальные условия выполнения, а также убедиться, что все, что на самом деле делает бит обработки чисел, взаимодействует с остальной частью программы так, как вам нужно - если это что-то алгоритмическое, вам, вероятно, лучше написать приемочный тест язык, чтобы помочь охарактеризовать желаемые результаты в различных ситуациях - это дает четкое представление о том, чего вы пытаетесь достичь, а также позволяет вам пропускать большие объемы (реальных) данных через систему, которая, вероятно, лучше, чем сгенерированная компьютером Вход. Другим преимуществом этого является то, что если вы понимаете, что алгоритм нуждается в радикальной переработке, чтобы соответствовать некоторым новым требованиям, все, что вам нужно сделать, это добавить новый тестовый пример, а затем переписать/рефакторить; если бы ваши тесты просто рассматривали детали алгоритма и предполагали влияние на внешний мир, тогда у вас была бы существенная головная боль, пытаясь выяснить, как алгоритм в настоящее время влияет на поведение, какие части были правильными, а какие нет, а затем пытаясь перенести множество модульных тестов на новый API/алгоритм.

person JonnyRaa    schedule 17.07.2012
comment
Конечно, это именно то, что сделано сейчас. Я хочу сказать, что лучше просею через сгенерированный компьютером набор тестовых данных, чем буду догадываться заранее, какие проблемы могут возникнуть с полевыми данными. Если вы изучали численный анализ, это может иметь для вас смысл. Я особенно заинтересован в поиске разумно сформированных данных, которые вызывают числовые ошибки, такие как переполнение и потеря значимости. Такие задачи часто сложны в вычислительном отношении, и их лучше всего поручить машине. - person GregC; 17.07.2012
comment
Вот пример исследования, которое можно упростить с помощью автоматического поиска неисправностей: mathworks. com/matlabcentral/newsreader/view_thread/278975 - person GregC; 17.07.2012
comment
Я не мог понять, в чем заключалось решение проблемы этих парней - можно ли было найти его с помощью сгенерированных тестовых данных? Должно быть очень большое пространство для поиска чисел с плавающей запятой - кажется, в этом pdf-файле говорится, что pex не может точно рассуждать о них. Интересная проблема, извините, я не мог больше помочь! - person JonnyRaa; 25.07.2012
comment
Я отметил ваш ответ как решение проблемы, хотя на самом деле это не так. Думаю, мне нужно погрузиться в глубокое обучение... - person GregC; 10.05.2016