Я обнаружил, что во многих моих научных вычислительных программах есть требования к тестированию, которые не охватываются стандартными тестовыми средами:
Тестирование времени вычислений
- Чтобы убедиться, что алгоритмы не становятся медленнее. Я мог бы сделать что-то вроде,
assureSmallerEqual(RuntimeWrapper(algorithm),53)
но я бы хотел, чтобы порог в 53 секунды непрерывно уменьшался, когда я работаю над алгоритмом, то есть что-то вродеassureSmallerEqual(RuntimeWrapper(algorithm),'previousbest+noisetolerance')
- Чтобы убедиться, что алгоритмы не становятся медленнее. Я мог бы сделать что-то вроде,
Тестирование производительности
- Чтобы убедиться, что алгоритм, который ранее нашел хорошее приближение к аналитическому решению, все же находит решение, которое по крайней мере так же хорошо или лучше. Опять же, это может быть эмулировано стандартным интеграционным тестом, но я бы хотел, чтобы допуск постоянно уменьшался, поскольку алгоритм становится все лучше и лучше. Подумайте о замене
assureAlmostEqual(foo(),1,places=3)
наassureAlmostEqual(foo(),1,places='previousbest')
- Чтобы убедиться, что алгоритм, который ранее нашел хорошее приближение к аналитическому решению, все же находит решение, которое по крайней мере так же хорошо или лучше. Опять же, это может быть эмулировано стандартным интеграционным тестом, но я бы хотел, чтобы допуск постоянно уменьшался, поскольку алгоритм становится все лучше и лучше. Подумайте о замене
Тестирование физических требований
- Чтобы убедиться, что алгоритмам внезапно не понадобится больше памяти / места на жестком диске. Очень похоже на 1.
Тестирование абстрактных требований
- Чтобы убедиться, что для алгоритма, работавшего с квадратичными приближениями, внезапно не требуются кубические приближения, или для алгоритма, который справился с шагом 0,1, внезапно не нужны 0,01 для устойчивости. Опять же, они могут быть эмулированы стандартными интеграционными тестами, но цель состоит в том, чтобы запомнить, какой наименьший параметр требования был для достижения определенной цели, поэтому для этого потребовалось бы много ручного обновления. Например, если
foo(10)
ранее не было никаких исключений, я бы хотел, чтобы фреймворк по-foo(10)
прежнему работал, а также пытался, еслиfoo(9)
сейчас работает (в этом случае все будущие тесты будут обеспечиватьfoo(9)
работу).
- Чтобы убедиться, что для алгоритма, работавшего с квадратичными приближениями, внезапно не требуются кубические приближения, или для алгоритма, который справился с шагом 0,1, внезапно не нужны 0,01 для устойчивости. Опять же, они могут быть эмулированы стандартными интеграционными тестами, но цель состоит в том, чтобы запомнить, какой наименьший параметр требования был для достижения определенной цели, поэтому для этого потребовалось бы много ручного обновления. Например, если
Можно утверждать, что то, о чем я прошу, не описывает тесты в смысле модульного / интеграционного тестирования, поскольку, например, увеличение времени выполнения может быть приемлемым в обмен на другие улучшения.
На практике, однако, я знаю, что я бы сэкономил много времени на отладку, если бы у меня была вышеописанная функциональность тестирования, потому что в 95% случаев требования и производительность менялись из-за ошибок, которые я представил. Действительно, я точно знаю, что многих ошибок, которые я обнаружил (после того, как потратил много времени на проверку своего собственного кода) с внешними цифровыми библиотеками программного обеспечения, можно было бы тривиально избежать, если бы вышеприведенные тесты применялись строго.
PS
Вопрос с таким же названием /programming/34982863/framework-for-regression-testing-of-numeric-code не является дубликатом, поскольку он описывает функциональность, которую легче реализовать с помощью стандартных структур регрессионного тестирования.
Вопрос Стратегии для модульного тестирования и управляемой тестированием разработки требует стратегий, а не структуры, которая помогает их реализовать (и стратегии, которые он запрашивает / которые приведены в ответах, отличаются от того, что я описываю здесь, на мой взгляд).
Ответы:
1. Мне кажется, что этот тип теста плохо определен, потому что его условия тестирования привязаны к конкретной машине, на которой вы проводили тестирование в разработке. Одним из пунктов тестирования является то, что выполнение ваших тестов на моем ноутбуке говорит мне, что-то не так с кодом или средой, которую я настроил. 53 секунды зависят от вашей машины разработки, и время работы также увеличится, если машина тестирования будет загружена другими рабочими нагрузками или пользователями. Я не ожидал бы, что тестирующие фреймворки решат эту проблему: «функция запускается на входе менее чем за 53 секунды» - просто не очень хорошая спецификация корректности.
2. Я думаю, что это неоднозначно и нежелательно с точки зрения тестирования программного обеспечения по тем же причинам, 1 , вы теряете оправдание для тестирования программного обеспечения.
3. Это довольно часто, позвольте мне описать одно решение. Это не совсем работа инфраструктуры тестирования, но вы можете использовать отдельный инструмент, как описано в вопросе Unix SE Ограничение использования памяти для одного процесса Linux . Первым стандартным инструментом, который нужно попробовать, является
ulimit
команда inbash
, которая позволяет запустить процесс и убедиться, что он завершается сбоем, если он пытается, например, выделить слишком много памяти. Поэтому, если вы запуститеruntests
сценарий с ограничением памяти, он потерпит крах, и среда тестирования сможет справиться с этим как с обычной ошибкой тестирования.4. Большинство фреймворков тестирования не думают единицы тестирует этот путь на всех . Испытательный набор запускается (например, перед фиксацией кода в master или перед развертыванием), и результатом является да или нет, указывающее, функционирует ли он. Фреймворки тестирования не считают частью своей работы, например, отслеживание прогресса функций, а тестирование обычно не такое. Что бы вы сделали здесь, вы бы написали два теста
expect_succeeds(foo(10)); expect_fails(foo(9))
. Каждый раз оба теста запускаются, и успехи и ожидаемые неудачи проходят. Когда вы реализуете,foo(9)
и это успешно, тест ожидаемого сбоя теперь терпит неудачу, так что вы переписали быexpect_succeeds(foo(9))
и это абсолютно стандартная особенность всех фреймворков. Но вы должны четко указать, какое поведение вы ожидаете, потому что в противном случае это просто противоречит основным идеям тестирования программного обеспечения.performs_better(foo_A(), foo_B())
источник