首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >我可以在DUnit中编写参数化测试吗?

我可以在DUnit中编写参数化测试吗?
EN

Stack Overflow用户
提问于 2012-01-25 08:55:18
回答 4查看 2.9K关注 0票数 24

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

有没有一种方法可以在DUnit中编写(类似于)参数化测试?例如,为适当的测试过程指定输入和预期输出,然后运行测试套件并获得关于测试多次运行中哪一次失败的反馈?

(编辑:一个例子)

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

代码语言:javascript
复制
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;

我可能会有更多这样的测试,它们都是完全相同的,但是有不同的输入和期望。我不想把它们合并成一个测试,因为我希望它们能够独立通过或失败。

EN

回答 4

Stack Overflow用户

发布于 2012-01-25 16:56:49

您可以使用DSharp来改进DUnit测试。特别是新的单位DSharp.Testing.DUnit.pas (在德尔菲2010及以上)。

只需在TestFramework之后将其添加到您的使用中,就可以将属性添加到测试用例中。它看起来可能是这样的:

代码语言:javascript
复制
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.

运行它时,您的测试如下所示:

因为Delphi中的属性只接受常量,所以属性只将参数作为字符串,其中值由分号分隔。但是,没有什么可以阻止您创建自己的属性类,这些类接受正确类型的多个参数来防止“魔术”字符串。无论如何,您只限于可以是const的类型。

还可以在方法的每个参数上指定值属性,并使用任何可能的组合调用它(如NUnit中的那样)。

就其他答案而言,我想在编写单元测试时尽可能少地编写代码。另外,当我查看接口部分而不深入实现部分(我不会说:“让我们做BDD")时,我还想看看测试是做什么的。这就是为什么我更喜欢声明式的方式。

票数 22
EN

Stack Overflow用户

发布于 2012-01-25 13:33:29

我想你是在找这样的东西:

代码语言:javascript
复制
unit TestCases;

interface

uses
  SysUtils, TestFramework, TestExtensions;

implementation

type
  TArithmeticTest = class(TTestCase)
  private
    FOp1, FOp2, FSum: Integer;
    constructor Create(const MethodName: string; Op1, Op2, Sum: Integer);
  public
    class function CreateTest(Op1, Op2, Sum: Integer): ITestSuite;
  published
    procedure TestAddition;
    procedure TestSubtraction;
  end;

{ TArithmeticTest }

class function TArithmeticTest.CreateTest(Op1, Op2, Sum: Integer): ITestSuite;
var
  i: Integer;
  Test: TArithmeticTest;
  MethodEnumerator: TMethodEnumerator;
  MethodName: string;
begin
  Result := TTestSuite.Create(Format('%d + %d = %d', [Op1, Op2, Sum]));
  MethodEnumerator := TMethodEnumerator.Create(Self);
  Try
    for i := 0 to MethodEnumerator.MethodCount-1 do begin
      MethodName := MethodEnumerator.NameOfMethod[i];
      Test := TArithmeticTest.Create(MethodName, Op1, Op2, Sum);
      Result.addTest(Test as ITest);
    end;
  Finally
    MethodEnumerator.Free;
  End;
end;

constructor TArithmeticTest.Create(const MethodName: string; Op1, Op2, Sum: Integer);
begin
  inherited Create(MethodName);
  FOp1 := Op1;
  FOp2 := Op2;
  FSum := Sum;
end;

procedure TArithmeticTest.TestAddition;
begin
  CheckEquals(FOp1+FOp2, FSum);
  CheckEquals(FOp2+FOp1, FSum);
end;

procedure TArithmeticTest.TestSubtraction;
begin
  CheckEquals(FSum-FOp1, FOp2);
  CheckEquals(FSum-FOp2, FOp1);
end;

function UnitTests: ITestSuite;
begin
  Result := TTestSuite.Create('Addition/subtraction tests');
  Result.AddTest(TArithmeticTest.CreateTest(1, 2, 3));
  Result.AddTest(TArithmeticTest.CreateTest(6, 9, 15));
  Result.AddTest(TArithmeticTest.CreateTest(-3, 12, 9));
  Result.AddTest(TArithmeticTest.CreateTest(4, -9, -5));
end;

initialization
  RegisterTest('My Test cases', UnitTests);

end.

它在GUI测试运行程序中如下所示:

我很想知道我是否以一种不太理想的方式来做这件事。DUnit是如此的通用和灵活,以至于每当我使用它时,我总是觉得我错过了一种更好、更简单的解决问题的方法。

票数 13
EN

Stack Overflow用户

发布于 2012-01-25 12:06:24

如果DUnit允许编写这样的代码,那么AddTestForDoStuff的每个调用都会创建一个类似于示例中的测试用例,这是否就足够了?

代码语言:javascript
复制
Suite.AddTestForDoStuff.With(2).Expect(4);
Suite.AddTestForDoStuff.With(3).Expect(9);

我会在今天晚些时候发布一个例子.

对于.Net,已经有类似的东西:流利的断言

http://www.codeproject.com/Articles/784791/Introduction-to-Unit-Testing-with-MS-tests-NUnit-a

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/8999945

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档