Как правильно провести единичный тест методом контроля потока - PullRequest
0 голосов
/ 04 мая 2019

У меня есть метод проверки, который возвращает true, если обратный вызов должен быть пропущен после сохранения в записи, в противном случае он возвращает false.

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

Я использую Rails и Minitest, но считаю, что это общий вопрос о модульном тестировании, который может применяться к другим языкам и / или тестовым фреймам.

Я пытался протестировать метод и в итоге получился беспорядок.

  • вернуть true, если ни одно поле интереса не изменилось, а не массовая ассоциация
  • возвращает true, если массовая ассоциация, но нет ассоциированного пользователя
  • возвращает true, если массовая ассоциация и связанный пользователь, но не активны
  • возвращает false, если массовая ассоциация и связанный активный пользователь
  • вернуть false, если attribute_a изменился и связанный активный пользователь
  • вернуть false, если attribute_b изменился и связанный активный пользователь
  • вернуть false, если attribute_c изменился и связанный активный пользователь

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

def skip_callback
  return true unless (self.attribute_a_changed? || self.attribute_b_changed? || self.attribute_c_changed? || self.bulk_association == true)

  user = self.user
  return true if user.blank?
  return true unless user.active
  false
end

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

Ответы [ 2 ]

0 голосов
/ 08 мая 2019

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

Сначала , вы можете разработать тестовые сценарии с использованием MC / DC(измененное условие / покрытие решения).Идея заключается в следующем: для каждого логического ввода b в ваш код идентифицируйте два тестовых случая, которые имеют следующие свойства: a) Один из тестовых случаев имеет ожидаемый true результат, а другой - ожидаемый false результат.б) Оба теста имеют одинаковые входные данные, за исключением b, который в одном тестовом случае имеет значение true, а в другом - false.Другими словами, между этими двумя контрольными случаями только b изменяет и контролирует выход.

Пример: для того, чтобы вход self.attribute_a_changed? управлял выходом, другие входы должны иметь следующие значения:

  • self.attribute_b_changed? должно быть false
  • self.attribute_c_changed? должно быть false
  • self.bulk_association должно отличаться от true
  • self.user.blank? должно быть false
  • self.user.active должно быть true

Затем один тестовый случай со всеми вышеуказанными входными даннымизначения в сочетании с self.attribute_a_changed?, равным true, приведут к ожидаемому выводу false для skip_callback.Во втором тестовом примере вышеуказанные входные значения будут объединены с self.attribute_a_changed?, равным false, и приведут к ожидаемому выводу true для skip_callback.Выполнение этих двух тестов даст вам уверенность в том, что вы действительно проверили, что self.attribute_a_changed? влияет на выход.

MC / DC описывается на этой странице Википедии , которая также имеетссылка на этот учебник от НАСА .Есть также несколько примеров для SO, например, здесь .

Second , вы можете проверить свои тестовые случаи, запустив их для измененных версий (мутаций) вашего кода,Это называется мутационным тестированием и используется для оценки качества набора тестов.Чтобы увидеть, действительно ли один из ваших тестов обнаружил особую ошибку (например, self.attribute_a_changed? не оказывает желаемого влияния на результаты), просто вставьте эту ошибку и посмотрите, не прошел ли тест.Например, вы можете просто удалить self.attribute_a_changed? из кода и проверить, заметили ли ваши тесты.Или вы можете инвертировать его в self.attribute_a_changed? == false и посмотреть, найдут ли ваши тесты эту ошибку.

0 голосов
/ 07 мая 2019

Одним из вариантов может быть использование библиотеки-макета для обеспечения условий для каждого случая:

https://github.com/freerange/mocha

Ваши тесты будут тогда написаны примерно так:

your_test_object.expects(:attribute_a_changed?).returns(true)

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

...