Можно ли передать набор в тестовый набор в DUnitX?
Я пытаюсь проверить состояние объекта после запуска теста. Это состояние содержится в наборе. Можно ли передать ожидаемое состояние в тестовый набор с помощью атрибутов DUnitX, чтобы я мог использовать один и тот же тест для всех разных входов?
Я пытался передать набор как константу или как набор, но в моей процедуре тестирования он всегда появляется как пустой набор.
- Возможно ли это вообще с использованием атрибутов?
- Как бы вы проверили, если наборы идентичны?
Пример кода:
type
TResult = (resOK,resWarn,resError);
TResultSet = set of TResult;
const
cErrWarn : TResultSet = [resWarn];
type
[TestFixture]
TMyTest = class(TBaseTest)
[Test]
[TestCase('Demo1','InputA,[resWarn]')] // <-- tried as a set
[TestCase('Demo2','InputB,cErrWarn')] // <-- tried as a constant
procedure Test(Input:string; ExpectedResult: TResultSet);
end;
procedure TMyTest.Test(Input:string; ExpectedResult: TResultSet);
begin
// ExpectedResult is always the empty set []
RunTests(MyObject(Input));
Assert.AreEqual(ExpectedResult, MyObject.ResultSet);
end;
Я также попытался определить ожидаемый результат как массив, но тогда DUnitX даже не вызывает тест. Вероятно, это просто "слишком много"
procedure Test(Input:string; ExpectedResult: array of TResult);
Лучшее, что я мог придумать, это использовать следующий подход. Возьмите пример из трех ожидаемых состояний (введите здесь ваше любимое целое число...) и проверьте их отдельно. Это не то, на что я надеялся, но это помогает.
procedure Test(Input:string; R1,R2,R3: TResult);
Помощь очень ценится.:)
2 ответа
Ты используешь TestCaseAttribute
указать аргументы, которые будут переданы вашему методу тестирования. Однако он просто не поддерживает передачу множеств в качестве аргументов. Вы можете увидеть, что это так, посмотрев на постоянную Conversions
объявлено в DUnitX.Utils
Блок. Он отображает любое преобразование в набор ConvFail
,
Итак, если вы хотите указать эти данные с помощью атрибутов, вам нужно будет расширить среду тестирования. Вы можете получить свой собственный потомок от CustomTestCaseSourceAttribute
и переопределить GetCaseInfoArray
декодировать ваши заданные аргументы. В качестве грубого примера, вы можете использовать это:
type
MyTestCaseAttribute = class(CustomTestCaseSourceAttribute)
private
FCaseInfo: TestCaseInfoArray;
protected
function GetCaseInfoArray: TestCaseInfoArray; override;
public
constructor Create(const ACaseName: string; const AInput: string; const AExpectedResult: TResultSet);
end;
constructor MyTestCaseAttribute.Create(const ACaseName, AInput: string; const AExpectedResult: TResultSet);
begin
inherited Create;
SetLength(FCaseInfo, 1);
FCaseInfo[0].Name := ACaseName;
SetLength(FCaseInfo[0].Values, 2);
FCaseInfo[0].Values[0] := TValue.From<string>(AInput);
FCaseInfo[0].Values[1] := TValue.From<TResultSet>(AExpectedResult);
end;
function MyTestCaseAttribute.GetCaseInfoArray: TestCaseInfoArray;
begin
Result := FCaseInfo;
end;
Затем вы можете добавить следующий атрибут в ваш метод тестирования:
[MyTestCase('Demo2', 'InputB', [resWarn])]
procedure Test(Input: string; ExpectedResult: TResultSet);
Я избегал использовать RTTI здесь для простоты, но использование RTTI даст вам больше гибкости. Вы передадите аргумент в виде строки и расшифруете его, используя RTTI, как это делает код в DUnitX. Это означает, что вам не нужно писать сделанные на заказ атрибуты каждый раз, когда вы хотите использовать заданный аргумент.
Еще лучше было бы реализовать это в DUnitX путем расширения Conversions
карту, чтобы покрыть наборы, и представить это как патч. Я уверен, что другие найдут это полезным.
Добавить эту функцию преобразования в DUnitX.Utils
и положить его в матрицу конверсий для tkUString
в tkSet
(из-за ограничений StringToSet
а также TValue
это работает только для наборов до 32 элементов, для больших наборов до 256 элементов требуется больше кода):
function ConvStr2Set(const ASource: TValue; ATarget: PTypeInfo; out AResult: TValue): Boolean;
begin
TValue.Make(StringToSet(ATarget, ASource.AsString), ATarget, AResult);
Result := True;
end;
Также вам нужно использовать другой символ-разделитель для параметров, иначе он будет разделен неправильно:
[TestCase('Demo1','InputA;[resWarn,resError]', ';')]