Подтвердить что ты не робот

Как unit test сложные методы

У меня есть метод, который, учитывая угол для Севера и угол для подшипника, возвращает значение точки компаса из 8 возможных значений (север, северо-восток, восток и т.д.). Я хочу создать unit test, который обеспечивает достойный охват этого метода, предоставляя различные значения для North and Bearing, чтобы обеспечить достаточный охват, чтобы дать мне уверенность в том, что мой метод работает.

Моя первоначальная попытка вызвала все возможные значения целого числа для Севера от -360 до 360 и проверила каждое значение Bearing с -360 до 360. Однако мой тестовый код оказался другой реализацией кода, который я тестировал. Это заставило меня задаться вопросом, что лучший тест для этого, так что мой тестовый код не просто будет содержать те же ошибки, что и мой производственный код.

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

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

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

ПРИМЕЧАНИЕ. Я использую Visual Studio и С#, но я считаю, что этот вопрос является агностическим.

4b9b3361

Ответ 1

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

Ваш XML файл должен содержать только подмножество данных, которые вы описали. Ваши тесты должны гарантировать, что вы можете обрабатывать крайние диапазоны вашего входного домена (-360, 360), несколько точек данных только внутри концов диапазона и несколько точек данных посередине. В ваших тестах также следует проверить, что ваш код изящно выходит из строя при заданных значениях вне диапазона ввода (например, -361 и +361).

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

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

Ответ 2

Вы могли бы перекомпоновать метод на части, которые проще unit test, и написать модульные тесты для деталей. Затем модульные тесты для всего метода должны быть сосредоточены только на проблемах интеграции.

Ответ 3

Я предпочитаю делать следующее.

  • Создайте электронную таблицу с правильными ответами. Однако сложный он должен быть неактуальным. Вам просто нужны столбцы с регистром и некоторые столбцы с ожидаемыми результатами.

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

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

    def testCase215n( self ):
        self.fixture.setCourse( 215 )
        self.fixture.setBearing( 45 )
        self.fixture.calculate()
        self.assertEquals( "N", self.fixture.compass() )
    

[Этот Python, эта же идея будет использоваться для С#.]

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

Я использую небольшую программу Python с xlrd и генератором шаблонов Mako для этого. Вы можете сделать что-то подобное с продуктами С#.

Ответ 4

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

Другие примеры включают в себя запись сортировки пузырьков для проверки сортировки кучи против или использование известной функции рабочего сортирования для поиска медианов и сравнения ее с результатами реализации алгоритма поиска по О (N).

Ответ 5

Я считаю, что ваше решение в порядке, несмотря на использование XML файла (я бы использовал обычный текстовый файл). Но более используемая тактика состоит в том, чтобы просто проверить предельные ситуации, например, использовать в вашем случае входное значение -360, 360, -361, 361 и 0.

Ответ 6

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

Ответ 7

Не уверен, насколько сложным является ваш код, если он принимает целое число и делит его на 8 или 16 направлений на компасе, это, вероятно, несколько строк кода да?

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

В этом конкретном случае я буду кормить его каждый номер в порядке от -360 до +360 и печатать номер и результат (в текстовый файл в формате, который может быть скомпилирован в другую программу в виде файла заголовка). Визуально проверьте, что направление изменяется на желаемом входе. Это должно быть легко визуально проверять и проверять. Теперь у вас есть таблица входов и допустимых выходов. Затем выполните произвольную выборку программы из допустимых входных данных, которые передают ее в тестируемый код, и убедитесь, что правильный ответ вышел. Сделайте несколько сотен таких случайных тестов. В какой-то момент вам нужно проверить, что числа, которые меньше чем -360 или больше +360, обрабатываются в соответствии с вашими требованиями, я предполагаю, что это отсечение или модуляция.

Ответ 8

Итак, я взял класс тестирования программного обеспечения текст ссылки, и в основном вы хотите определить класс входов.. все реальные числа? все целые числа, только положительные, только отрицательные и т.д. Затем группируют выходные действия. 360 уникально отличается от 359 или они в значительной степени в конечном итоге делают то же самое с приложением. Как только происходит комбинация входов и выходов.

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

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

Ответ 9

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

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

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

Ответ 10

Psuedocode:

array colors = { red, orange, yellow, green, blue, brown, black, white }
for north = -360 to 361
    for bearing = -361 to 361
        theColor = colors[dirFunction(north, bearing)] // dirFunction is the one being tested
        setColor (theColor)
        drawLine (centerX, centerY,
                  centerX + (cos(north + bearing) * radius),
                  centerY + (sin(north + bearing) * radius))
        Verify Resulting Circle against rotated reference diagram.

Когда North = 0, вы получите 8-цветную круговую диаграмму. Поскольку север меняется + или -, круговая диаграмма будет выглядеть одинаково, но вращается вокруг этого уровня. Проверка теста - это простой вопрос: (а) изображение является правильно повернутой круговой диаграммой и (б) в оранжевой области нет зеленых пятен и т.д.

Этот метод, кстати, является разновидностью самого большого в мире инструмента для отладки: попросите компьютер обратить ваше внимание на то, что = IT = думает, что это делает. (Слишком часто разработчики тратят часы, преследуя то, что, по их мнению, делает компьютер, только чтобы обнаружить, что он делает что-то совершенно другое.)