読者です 読者をやめる 読者になる 読者になる

DelphiXE3でTRttiContextを使ってテストフレームワークを作ってみる

Delphi

前に使ってたバージョンがDelphi2009なのでTRttiContextを使うのはこれが初めて。
TRttiContextを使ってメソッド名の取得や取得したメソッドの実行ができるので、xUnit(DUnitとか)なテストフレームワークを作ってみました。
"Test"という名前で始まるメソッドを探して実行する部分のコードはこんな感じ。細かい部分は省略してます。

procedure TTestCase.Run(TestResultList: TObjectList<TTestResult>);
var
  RttiContext: TRttiContext;
  RttiType: TRttiType;
  Method: TRttiMethod;
begin
  RttiContext := TRttiContext.Create;
  try
    RttiType := RttiContext.GetType(ClassType);
    for Method in RttiType.GetMethods do
    begin
      if LeftStr(Method.Name, 4) = 'Test' then
      begin
        try
          try
            SetUp;
            Method.Invoke(Self, []); // テストメソッドを呼び出し
          except
            on E: EAssertionError do
              // テスト結果を記録(省略)
            on E: ESkipTest do
              // テスト結果を記録(省略)
            on E: Exception do
              // テスト結果を記録(省略)
          end;
        finally
          TearDown;
        end;
      end;
    end;
  finally
    RttiContext.Free;
  end;
end;

DUnitがあるので別にこれを使う必要はないですが、練習で作ってみました。
TStopWatchも使っているのですが、便利ですね。
まだアサーションのメソッドは少ししか作ってないです。

ソースコード

ソースコードgithubとbitbucketに置きました。

dprojファイルがないのは、IDEを使ってないだけです。Makefileを書いて、makeコマンドでビルドしています。

実行結果

Exampleの下のソースコードをmakeコマンドでビルドして実行するとこんな感じ。
Pythonのunittestモジュールの出力を参考に作ってみました。

C:\Users\tokibito\_bitbucket\delphi-unittest\Example>TestProject.exe
..FS..
======================================================================
FAIL: TestAddFail (TMyUnit1Test)
----------------------------------------------------------------------
EAssertionError: 30 != 40

----------------------------------------------------------------------
Ran 6 tests in 0.501s

FAILED (failures=1, skipped=1)

ビルドしたTestProjectはMacOSXでも動作しました。