はじめに
Smalltalkでの開発を管理する上で、Smalltalkの外の世界から管理することが重要になってきました。自分は運良く HoneyGinger や Jun4Pharo の開発で Inria の Jenkins サーバを利用する機会に恵まれました。そこで得られたノウハウをここで共有したいと思います。自前で Jenkins サーバ立てて運用する人達の参考になれば嬉しいです。
Pharo で単体テスト
Jenkins での CI を効果的にするためには、単体テストは欠かせません。本節では Pharo 上での単体テストの記述や実行を簡単に紹介します。
TestCase
TestCase クラスのサブクラスを定義し、必要に応じて setUp メソッドや tearDown メソッドを定義して、メソッド毎のテストコードをtestで始まるメソッド名で定義することで、テストフレームワークを利用することができます。
例えば Jun4Pharo の Jun2dPoint クラスの asArray メソッドをテストするための、Jun2dPointTestクラスの testAsArray メソッドを以下に示します。
testAsArray
| x y z p |
x := 2.
y := -3.
z := 4.
p := x , y.
self
assert: p asArray
equals:
{x.
y}
上記の例のように、テストクラスの名前を、テスト対象のクラス名+Testとして、テストメソッドの名前を test+テスト対象のメソッド名 とするのが慣習となっています。
SystemBrowser でテスト
上記のテストクラス名とテストメソッド名の慣習に従うとツールがその対応関係を理解し、以下のように System Browser 上から単体テストに合格した場合にテスト対象のクラスやメソッドを実行することができます。
丸アイコンをクリックすると、テスト結果がボタンの色で示されます。
もちろん、同じく System Browser 上でテストコード側からテストを実行したり結果を見ることができます。テストコード側ではメソッド単体だけでなく、テストクラスの全テストメソッドを実行することもできます。
System Browser 上での単体テストの実行UIは、開発初期などでクラスやテストクラスをモリモリと書いていく過程での単体テストに向いています。
TestRunner でテスト
開発プロジェクト全体について単体テストを一括して実行したり、テストカバレッジを計測する時などは、 TestRunner が便利で、複数のパッケージ、複数のテストクラスを選択して一括実行することができます。
Pharo でコンソール
Jenkins を始めとする汎用の開発管理ツールを効果的に利用するためには、GUI だけでなく、コンソール上でのコマンドラインで実行できることが求められます。本節では Pharo をコマンドラインオプションを利用して制御する方法を紹介します。
コマンドラインオプション
Pharo の Virtual Machine のオプションとして、--headless を指定すると、GUI を立ち上げずに Pharo 環境を立ち上げることができます。さらに、イメージファイルに続いて --listを指定すると、Pharo環境へのコマンドラインオプションの一覧が得られる。MacOSX 上で実行した場合の結果を以下に示します。
Currently installed Command Line Handlers:
Fuel Loads fuel files
config Install and inspect Metacello Configurations from the command line
save Rename the image and changes file
update Load updates
printVersion Print image version
st Loads and executes .st source files
test A command line test runner
clean Run image cleanup
eval Directly evaluates passed in one line scripts
使えそうなオプションが並んでいます。とりあえず、save、config、test があれば最低限のビルド&テストはできそうです。
CommandLineHandler
コマンドラインオプションは Pharo 環境内の CommandLineHandler クラスのサブクラスによって処理されます。既存のサブクラスを参考にしながら新しい Handler クラスを定義すれば、新しいコマンドラインオプションを定義することができます。
Pharo で Jenkins
Inria の Pharo Contributions で動かしている Jun4Pharo のスクリプトを以下に示します。
# jenkins puts all the params after a / in the job name as well :(
export JOB_NAME=`dirname $JOB_NAME`
wget --quiet -O - get.pharo.org/$PHARO+$VM | bash
./pharo Pharo.image save $JOB_NAME --delete-old
./pharo $JOB_NAME.image --version > version.txt
REPO=http://smalltalkhub.com/mc/tomooda/Jun4Pharo/main
./pharo $JOB_NAME.image config $REPO ConfigurationOfJun --install=$VERSION --group=default
./pharo $JOB_NAME.image test --junit-xml-output "Jun.*"
zip -r $JOB_NAME.zip $JOB_NAME.image $JOB_NAME.changes
このスクリプトでやっていることは
- まずは wgetで Pharo のバージョンと VM を指定してダウンロードスクリプトを取得してきて、それを実行してカレントディレクトリ内に展開します。
- そのままジョブ名でイメージファイルを保存して、さらに、バージョン名をversion.txtに記録しておきます。
REPO=行より下からが本番で、
- config オプションで CI 対象である Jun4Pharo を smalltalkhub のレポジトリから読み込んで、
- Junで始まるテストクラスを実行して XML ファイルに junit と同じ形式で出力します。
- 最後に、できあがったイメージファイルをチェンジファイルといっしょに zip アーカイブにします。
なお、このスクリプトは同じく Inria 内の Pharo Contributions の他のプロジェクトのをコピーして適当に修正したものです。eval オプション等を使えばもっと色々なことができるでしょう。
PharoLauncher
Jenkins サーバで定期的にイメージを作成しているので、作成した zip をダウンロードしてくれば簡単にパッケージを試用してみたり、まとまった人数に統一した開発イメージを供給することができます。
例えば Jun4Pharo も、https://ci.inria.fr/pharo-contribution/job/Jun4Pharo/PHARO=40,VERSION=last,VM=vm/ で最近のテスト結果の推移を確認して、最新のイメージの zip をダウンロードしてくることができます。
それを Pharo 上で簡単に操作できるようにしたのが PharoLauncher です。
インストール&使い方
PharoLauncherは http://www.smalltalkhub.com/#!/~Pharo/PharoLauncher で開発されています。
MCHttpRepository
location: 'http://www.smalltalkhub.com/mc/Pharo/PharoLauncher/main'
user: ''
password: ''
から ConfigurationOfPharoLauncher の最新版を取得して、ConfigurationOfPharoLauncher loadするか、あるいは Inria の CI サーバ の https://ci.inria.fr/pharo/view/Launcher/job/Launcher/PHARO=40,VERSION=stable,VM=vm,label=linux/ あたりからイメージをダウンロードしてくることもできます。
PharoLauncher open
で PharoLauncher を立ち上げることができます。
現在は Inria の CI サーバ内のイメージを取得するようになっていますが、PhLJenkins2Job のサブクラスを定義して PhLTemplateGroupRepository class>>#groups あたりを修正すれば、他の Jenkins サーバも見ることができるようになると思います。
詳しくは http://www.smalltalkhub.com/#!/~Pharo/PharoLauncher をどうぞ。
まとめ
Smalltalk での開発環境も、全てを Smalltalk 内で賄うことに拘らずとも、filetree 等と組み合わせて git & Jenkins という選択肢も実践として現実的になってきました。もちろん、従来のように monticello browser や Test Runner や Versionner を使って、できるだけ人手による作業を Smalltalk に閉じた形で行うこともできます。CI は目的ではなく、あくまで手段の1つに過ぎないので、1つの道具に拘らずに、あくまで多様な道具立ての1つとして Jenkins + Pharo を考えていけばよいのではないかと思います。