Единичная тестовая машина

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

Очевидно, что правильная вещь - добавить модульные тесты, но не ясно, как это сделать. Многие компоненты моей программы дают несколько субъективный ответ, и я не могу автоматизировать проверки работоспособности.

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

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

6 ответов

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

Окончательная мысль об этом - книга Майкла Пера, работающая эффективно с устаревшим кодом. Раньше это было полезным резюме на сайте ObjectMentor, но, увы, веб-сайт пошел по пути компании. Однако WELC оставил наследие в обзорах и других статьях. Проверьте их (или просто купите книгу), хотя основными уроками являются те, которые S.Lott и tvanfosson в своих ответах.


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


", тогда я не проверю все, что может пойти не так."

Правильно.

Задача модульных тестов - не проверять все, что может пойти не так.

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

Ничто не может проверить все, что может пойти не так. Вы можете написать доказательство, но вам будет трудно писать тесты на все.

Правильно выберите ваши тестовые примеры.

Кроме того, задание модульных тестов состоит в том, чтобы проверить, что каждая малая часть общего приложения делает правильную вещь - изолированно.

Например, ваш "код, который аппроксимирует кривую с кривой с низким разрешением", вероятно, имеет несколько небольших частей, которые можно тестировать как отдельные единицы. В изоляции. Интегрированное целое также может быть проверено, чтобы быть уверенным, что оно работает.

Например, ваша "вычислительно интенсивная работа над кривой с низким разрешением", вероятно, имеет несколько небольших частей, которые могут быть протестированы как отдельные блоки. В изоляции.

Эта точка модульного тестирования заключается в создании небольших, правильных единиц, которые впоследствии собраны.


В ваших модульных тестах необходимо использовать какой-то фактор пух, либо путем принятия приближений, либо с помощью каких-то вероятностных проверок.

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

TEST_ALMOST_EQ(result, 4.0);

Выше TEST_ALMOST_EQ может убедиться, что result находится между 3.9 и 4.1 (например).

В качестве альтернативы, если ваши алгоритмы машинного обучения являются вероятностными, ваши тесты должны быть приспособлены для него, принимая среднее значение нескольких прогонов и ожидая, что оно будет в пределах некоторого диапазона.

x = 0;
for (100 times) {
 x += result_probabilistic_test();
}
avg = x/100;
TEST_RANGE(avg, 10.0, 15.0);

Конечно, тесты не являются детерминированными, поэтому вам нужно будет их настроить таким образом, чтобы вы могли получить нелипкие тесты с высокой вероятностью. (Например, увеличить количество испытаний или увеличить диапазон ошибок).

Вы также можете использовать mocks для этого (например, генератор случайных чисел для ваших вероятностных алгоритмов), и они обычно помогают для детерминированного тестирования определенных кодов кода, но для этого требуется много усилий. В идеале вы бы использовали комбинацию нечеткого тестирования и mocks.

НТН.


Как правило, для статистических измерений вы строите epsilon для своего ответа. И.Е. средняя квадратная разница ваших точек будет равна < 0,01 или некоторые такие. Другой вариант - запустить несколько раз, и если он "слишком часто выходит из строя" , значит, у вас есть проблема.


  • Получить соответствующий тестовый набор данных (возможно, подмножество того, что обычно используется)
  • Рассчитать некоторую метрику в этом наборе данных (например, точность)
  • Запишите полученное значение (перекрестная проверка)
  • Это должно указывать, как установить порог для

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

licensed under cc by-sa 3.0 with attribution.