Должны ли ожидаемые результаты модульного теста быть жестко закодированы или они могут зависеть от инициализированных переменных? Увеличивают ли жестко закодированные или рассчитанные результаты риск внесения ошибок в модульный тест? Есть ли другие факторы, которые я не учел?
Например, какой из этих двух форматов является более надежным?
[TestMethod]
public void GetPath_Hardcoded()
{
MyClass target = new MyClass("fields", "that later", "determine", "a folder");
string expected = "C:\\Output Folder\\fields\\that later\\determine\\a folder";
string actual = target.GetPath();
Assert.AreEqual(expected, actual,
"GetPath should return a full directory path based on its fields.");
}
[TestMethod]
public void GetPath_Softcoded()
{
MyClass target = new MyClass("fields", "that later", "determine", "a folder");
string expected = "C:\\Output Folder\\" + string.Join("\\", target.Field1, target.Field2, target.Field3, target.Field4);
string actual = target.GetPath();
Assert.AreEqual(expected, actual,
"GetPath should return a full directory path based on its fields.");
}
РЕДАКТИРОВАТЬ 1: В ответ на ответ ДХМ, является ли вариант 3 предпочтительным решением?
[TestMethod]
public void GetPath_Option3()
{
string field1 = "fields";
string field2 = "that later";
string field3 = "determine";
string field4 = "a folder";
MyClass target = new MyClass(field1, field2, field3, field4);
string expected = "C:\\Output Folder\\" + string.Join("\\", field1, field2, field3, field4);
string actual = target.GetPath();
Assert.AreEqual(expected, actual,
"GetPath should return a full directory path based on its fields.");
}
c#
unit-testing
Hand-E-Food
источник
источник
Ответы:
Я думаю, что рассчитанные ожидаемые значения результатов в более надежных и гибких тестовых случаях. Кроме того, используя хорошие имена переменных в выражении, которое вычисляет ожидаемый результат, становится намного более ясным, откуда ожидался ожидаемый результат.
Сказав это, в вашем конкретном примере я бы НЕ доверял методу "мягкого кода", потому что он использует вашу SUT (тестируемую систему) в качестве входных данных для ваших расчетов. Если в MyClass есть ошибка, из-за которой поля не сохраняются должным образом, ваш тест на самом деле пройдет, потому что при расчете ожидаемого значения будет использоваться неправильная строка, как target.GetPath ().
Мое предложение будет рассчитывать ожидаемое значение там, где это имеет смысл, но убедитесь, что вычисление не зависит от кода из самого SUT.
В ответ на обновление ОП на мой ответ:
Да, исходя из моих знаний, но немного ограниченного опыта в выполнении TDD, я бы выбрал вариант № 3.
источник
Что делать, если код был следующим:
Ваш второй пример не поймает ошибку, но первый пример будет.
В общем, я бы рекомендовал не программировать, потому что это может скрывать ошибки. Например:
Можете ли вы определить проблему? Вы не сделаете ту же ошибку в жестко закодированной версии. Труднее получить правильные расчеты, чем жестко закодированные значения. Вот почему я предпочитаю работать с жестко закодированными значениями, чем с мягко закодированными.
Но есть и исключения. Что если ваш код должен работать в Windows и Linux? Мало того, что путь должен быть другим, он должен использовать разные разделители пути! Вычисление пути с использованием функций, которые абстрагируют разницу, может иметь смысл в этом контексте.
источник
На мой взгляд, оба ваших предложения не идеальны. Идеальный способ сделать это это:
Другими словами, тест должен работать исключительно на основе входных и выходных данных объекта, а не на основе внутреннего состояния объекта. Объект должен рассматриваться как черный ящик. (Я игнорирую другие проблемы, такие как неуместность использования string.Join вместо Path.Combine, потому что это всего лишь пример.)
источник
target.Dispose(); Assert.IsTrue(target.IsDisposed);
(очень простой пример.)В обсуждении есть два аспекта:
1. Использование самой цели в тестовом примере
. Первый вопрос: следует ли / можно ли использовать сам класс, чтобы полагаться и получать часть работы, выполненной в тестовой заглушке? - Ответ НЕТ, поскольку, как правило, вы никогда не должны делать предположения о коде, который вы тестируете. Если это не сделано должным образом, со временем ошибки становятся невосприимчивыми к некоторым юнит-тестам
2. Жесткое кодирование -
это жесткий код ? Снова ответ - нет . потому что, как и любое программное обеспечение, жесткое кодирование информации становится сложным, когда вещи развиваются. Например, если вы хотите, чтобы вышеуказанный путь был изменен снова, вам нужно либо написать дополнительный модуль, либо продолжить модификацию. Лучшим способом является сохранение входных данных и даты оценки на основе отдельной конфигурации, которую можно легко адаптировать.
например, вот как я бы исправил тестовую заглушку.
источник
Есть много возможных концепций, сделал несколько примеров, чтобы увидеть разницу
Подводя итог: в целом ваш первый просто жестко запрограммированный тест имеет для меня наибольшее значение, поскольку он прост, понятен и т. Д. Если вы слишком много раз начинаете жесткое кодирование пути, просто добавьте его в метод настройки.
Для дальнейшего структурированного тестирования в будущем я хотел бы проверить источники данных, чтобы вы могли просто добавить больше строк данных, если вам нужно больше ситуаций тестирования.
источник
Современные тестовые среды позволяют вам предоставлять параметры для вашего метода. Я бы использовал эти:
На мой взгляд, есть несколько преимуществ:
источник