KL Tool を使用してエクステンションの開発・デバッグ

../_images/FE_logo_345_60.png
Fabric Engine version 2.4.0
Copyright (c) 2010-2017 Fabric Software Inc. All rights reserved.

KL Tool

Fabric Engineにはコマンドラインで実行可能な kl (Windowsでは kl.exe) が bin/ フォルダ以下に付属します。これを KL tool を称します。

KL tool によりコマンドラインからKLプログラムを実行し、結果をリポートさせることができます。Fabric Software 社内では KL tool を内部のユニットテストスイート全体に使用しています。さらに KL tool は独自の KLエクステンション開発においてもとても役立ちます。

Fabric Engine の環境をセットアップ ―Fabric Engine 配布物ののルートに存在する environment.sh の読み込み(source) あるいはwindowsでは prompt.bat のダブルクリック― すると、KL tool が PATH に通り、コマンドラインから単に kl とするだけで実行可能になります。 kl --help と実行することで利用可能なオプションを表示し、正常に動作しているかの確認ができます。

KL Tool を使用しKLソースファイルのコンパイルと評価

KL tool にソースファイルの名前を指定し実行し、コンパイルし実行しまます。与えられたソースファイルは通常、entry オペレータ(以下に詳述)と、幾つかの出力を生成するコードからなる小規模なテキストファイルです。例えば、KLソースコードを含む MyTest.kl を KL tool から実行するには以下のコマンドです:

kl MyTest.kl

entry() オペレータ

KL tool は entry と呼ばれる引数0個をとるオペレータをコード中から探します。このオペレータはソースコードコンパイル後に呼びだされます。

operator entry() {
  report("Hello World");
}

/*
** Output:

Hello World

*/

エクステンションのテスト

独自エクステンションの種々のテストの読み込みと実行のために、シンプルなソースコードを記述することがよくあります。単に require MyExtension; とファイル先頭にインクルードし、インクルードされたエクステンション全体の機能性を生じます。 require 文によりさらに、エクステンションに文法エラーが無いかも検証します。エクステンションやそれに必要なKLソースコードのコンパイルが成功すると、entryオペレータが呼び出されます。

エクステンションをテストするため、KLソースファイルでは通常、エクステンション内に定義されたオブジェクトと構造体を構築(construct)し、それらを呼び出し結果をリポートし、機能のテストを行います。

注釈

データ構造を丸々リポートさせることは避けたほうが良いでしょう。コードの振る舞いを破壊せず変更が利くようにするためです。かわりに、カスタム型に対するメソッドの呼び出しを検討し、結果をチェックしましょう。internal メソッドのテストは避けます。ユーザから隠蔽されていることが期待されているためです。独自のエクステンションでは、他のエクステンションや、Splice/Canvasオペレータから使用されることを想定しメソッドを定義しましょう。これらのメソッドによって独自エクステンションへのインタフェースを定義し、徹底的にテストするべきです。アクセス修飾子 ― public, private により、独自オブジェクトや構造体への外部APIの制御することはとても良いプラクティスです。 構造体、オブジェクト、インタフェースでのアクセス制御 を参照してください。
/*
** Example: A Simple Test in KL
*/

require Math;

operator entry() {
  Mat33 mat33 = Quat(Euler(0.0, HALF_PI, 0.0, RotationOrder('zyx'))).toMat33();
  report(mat33);
}

/*
** Output:

{row0:{x:+0.596046e-7,y:+0.0,z:+0.999999},row1:{x:+0.0,y:+1.0,z:+0.0},row2:{x:-0.999999,y:+0.0,z:+0.596046e-7}}

*/

テキストファイルへの出力

KL tool の出力は > shell オペレータを使用しテキストファイルに送ります:

kl MyTest.kl > MyTest.out

テストが大量の出力を生成する場合や、テキストエディタを利用し検索を行う場合などとても有用です。もちろんユニットテストの正しい出力結果ファイルを生成する場合にもつかえます。

KL Tool のユニットテストセットアップへの利用

ユニットテストシステムは KL Tool を利用し簡単にセットアップ可能です。典型的にユニットテストは参照する出力と、正答となる出力結果を比較し、コードの動作が変わっていないかを判断します。

Linux や OS X, Windows の mingw シェルなどを利用中であれば、 cmpdiff ユーティリティを利用し、テストを実行する簡単なスクリプトが作成できます。このように記述します:

#!/bin/bash

USAGE="Usage: $0 file1.kl file2.kl ... fileN.kl"

if [ "$#" == "0" ]; then
  echo "$USAGE"
  exit 1
fi

while (( "$#" )); do

  KL=$1
  OUT=${KL%.kl}.out
  RES=${KL%.kl}.res

  kl "$KL" >"$RES"
  if ! cmp "$OUT" "$RES"; then
    echo "FAIL $KL"
    echo "diff:"
    diff -u "$OUT" "$RES"
    # rm "$RES"
    exit 1
  else
    echo "PASS $KL"
    rm "$RES"
  fi

  shift

done

このスクリプトは、 test.kl ソースファイルを受け取り、入力ファイルに対応した正しい出力結果が記載された test.out が存在することを期待しています。このスクリプトを verify.sh などと保存したとすると、実行するには:

./verify.sh test.kl

test.kl の出力結果が test.out の内容と一致するかどうかを確認します。

テストのためより複雑なスクリプトを書くことも可能です。次の例では Python から KL Tool を実行し、出力をレファレンスファイルと比較します。レファレンスファイルが存在しない場合、あるいは --update True オプションが与えられた場合はレファレンスを生成します。

# Import system modules
import sys, string, os
import argparse
import subprocess

# Parse the commandline args.
parser = argparse.ArgumentParser()
parser.add_argument('klFile', help = "The kl File to use in the test")
parser.add_argument('--update', required=False, help = "Force the update of the reference file")
args = parser.parse_args()

klFile = args.klFile
cmdstring = "kl.exe " + klFile

# Call the KL tool piping output to the output buffer.
proc = subprocess.Popen(cmdstring,stdout=subprocess.PIPE)
output = ""
while True:
  line = proc.stdout.readline()
  if line != '':
    output += line.rstrip()
  else:
    break
referencefile = os.path.splitext(klFile)[0]+'.txt'
if not os.path.exists(referencefile) or args.update == 'True':
    with open(referencefile, 'w') as f:
      f.write(output)
    print "Reference Created"
else:
  referenceTxt = str(open( referencefile ).read())
  if referenceTxt == output:
    print "Test:" + klFile + " Passed"
  else:
    print "Test:" + klFile + " Failed"

上記の python コードを例えば pythonTester.py ファイルとして保存します。KLソースファイルをテストするためユニットテストを実行します。

python pythonTester.py test.kl

テスト結果をアップデートするには、テスターに –update 引数を与え実行します。

​ python pythonTester.py test.kl –update

独自のエクステンションにユニットテストフレームワークを設定し、それらテストを定期的に実行すると、APIに対する破壊的変更を捕捉する助けとなるでしょう。