我可以在DUnit中写'参数化'测试 [英] Can I write 'parameterized' tests in DUnit

查看:180
本文介绍了我可以在DUnit中写'参数化'测试的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用DUnit来测试一个Delphi库。我有时会遇到这样的情况,我写了几个类似的测试来检查一个函数的多个输入。



有没有办法写一个参数化测试DUnit?例如,将输入和预期输出指定到合适的测试过程,然后运行测试套件并获得测试的多次运行中哪一个的反馈失败?



(编辑:一个例子)



例如,假设我有两个这样的测试:

  procedure TestMyCode_WithInput2_Returns4(); 
var
Sut:TMyClass;
结果:整数;
begin
//安排:
Sut:= TMyClass.Create;

// Act:
结果:= sut.DoStuff(2);

// Assert
CheckEquals(4,Result);
结束

过程TestMyCode_WithInput3_Returns9();
var
Sut:TMyClass;
结果:整数;
begin
//安排:
Sut:= TMyClass.Create;

//动作:
结果:= sut.DoStuff(3);

// Assert
CheckEquals(9,Result);
结束

我可能有更多的这些测试完全相同的东西,但具有不同的输入和期望。我不想将它们合并成一个测试,因为我希望他们能够独立地通过或失败。

解决方案

您可以使用DSharp来改进您的DUnit测试。特别是新的单位)。



参考其他答案,我想写单位测试时尽可能少写代码。此外,我想看看测试在做什么,当我看看接口部分,而不是挖掘实现部分(我不会说:让我们做 BDD )。这就是为什么我更喜欢声明的方式。


I am using DUnit to test a Delphi library. I sometimes run into cases, where i write several very similar tests to check multiple inputs to a function.

Is there a way to write (something resembling) a parameterized test in DUnit? For instance specifying an input and expected output to a suitable test procedure, then running the test suite and getting feedback on which of the multiple runs of the test failed?

(Edit: an example)

For example, suppose I had two tests like this:

procedure TestMyCode_WithInput2_Returns4();
var
  Sut: TMyClass;
  Result: Integer;
begin
  // Arrange:
  Sut := TMyClass.Create;

  // Act:
  Result := sut.DoStuff(2);

  // Assert
  CheckEquals(4, Result);
end;

procedure TestMyCode_WithInput3_Returns9();
var
  Sut: TMyClass;
  Result: Integer;
begin
  // Arrange:
  Sut := TMyClass.Create;

  // Act:
  Result := sut.DoStuff(3);

  // Assert
  CheckEquals(9, Result);
end;

I might have even more of these tests that do exactly the same thing but with different inputs and expectations. I don't want to merge them into one test, because I would like them to be able to pass or fail independently.

解决方案

You can use DSharp to improve your DUnit tests. Especially the new unit DSharp.Testing.DUnit.pas (in Delphi 2010 and higher).

Just add it to your uses after TestFramework and you can add attributes to your test case. Then it could look like this:

unit MyClassTests;

interface

uses
  MyClass,
  TestFramework,
  DSharp.Testing.DUnit;

type
  TMyClassTest = class(TTestCase)
  private
    FSut: TMyClass;
  protected
    procedure SetUp; override;
    procedure TearDown; override;
  published
    [TestCase('2;4')]
    [TestCase('3;9')]
    procedure TestDoStuff(Input, Output: Integer);
  end;

implementation

procedure TMyClassTest.SetUp;
begin
  inherited;
  FSut := TMyClass.Create;
end;

procedure TMyClassTest.TearDown;
begin
  inherited;
  FSut.Free;
end;

procedure TMyClassTest.TestDoStuff(Input, Output: Integer);
begin
  CheckEquals(Output, FSut.DoStuff(Input));
end;

initialization
  RegisterTest(TMyClassTest.Suite);

end.

When you run it your test looks like this:

Since attributes in Delphi just accept constants the attributes just take the arguments as a string where the values are separated by a semicolon. But nothing prevents you from creating your own attribute classes that take multiple arguments of the correct type to prevent "magic" strings. Anyway you are limited to types that can be const.

You can also specify the Values attribute on each argument of the method and it gets called with any possible combination (as in NUnit).

Referring to the other answers personally I want to write as little code as possible when writing unit tests. Also I want to see what the tests do when I look at the interface part without digging through the implementation part (I am not going to say: "let's do BDD"). That is why I prefer the declarative way.

这篇关于我可以在DUnit中写'参数化'测试的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆