#java #c# #unit-testing #testing #code-coverage
#java #c# #модульное тестирование #тестирование #покрытие кода
Вопрос:
У меня есть куча кода проверки, который следует этому шаблону:
bool IsBroken()
{
var isBroken = Check(..., "error-1")
| Check(..., "error-2")
...
| Check(..., "error-n");
if (...)
{
isBroken |= Check(..., "error-1")
| Check(..., "error-2")
...
| Check(..., "error-n");
}
else
{
isBroken |= Check(..., "error-1")
| Check(..., "error-2")
...
| Check(..., "error-n");
}
// ...
// Could have more if-else or even nested if-else
return isBroken;
}
bool Check(bool condition, string message)
{
if (condition)
{
errors.Add(message);
}
return condition;
}
Цель состоит в том, чтобы выполнить все проверки независимо от результата. Однако проблема с этим кодом заключается в том, что он не подходит для покрытия ветвей.
Простым решением было бы, очевидно, Check(bool, string)
заменить тело функции, но это создает еще одну меньшую проблему, которая заключается в беспорядке кода. Я пытаюсь найти решение, которое может дать мне лучшее из обоих миров. Есть идеи ?!
Комментарии:
1. learn.microsoft.com/en-us/dotnet/csharp/pattern-matching
2.
isBroken
на самом деле не требуется:return !errors.isEmpty()
3. Кроме того, можно использовать что-то вроде a
List<Validator>
и перебирать список, где каждый элемент списка инкапсулирует anif
.
Ответ №1:
Если существует так много повторяющихся проверок (if-проверок), и они довольно короткие, вы можете создать словарь проверок, которые необходимо выполнить. Передайте этот словарь методу, выполните итерацию по элементам в словаре и добавьте сообщение об ошибке, если возникает ошибка проверки.
Пример кода:
class A
{
Dictionary<Func<A, bool>, string> dictOfChecks = new Dictionary<Func<A, bool>, string>()
{
//Example of checks , Error Message
{ (arg) => arg.ToString().Length < 3, "Length is smaller than 3" },
{ (arg) => arg.ToString().Length < 2, "Length is smaller than 2" },
};
public bool IsBroken()
{
//there you can enter multiple call of GetErrors to check whether there are some
var errors = GetErrors(dictOfChecks);
return errors.Length == 0;
}
public string[] GetErrors(Dictionary<Func<A, bool>, string> dict)
{
var errors = new List<string>();
foreach (KeyValuePair<Func<A, bool>, string> kvp in dict)
{
if (kvp.Key.Invoke(this))
errors.Add(kvp.Value);
}
return errors.ToArray();
}
}
Ответ №2:
Придумал подходящее решение:
_ = condition amp;amp; Append("error");
bool Append(string error)
{
errors.Add(error);
return true;
}
хотя это также можно записать как if (condition) Append("error")
. В нашем случае операторы блока должны быть записаны как:
if (condition)
{
...
}