Hatena::Groupcatalyst

dann@catalyst このページをアンテナに追加 RSSフィード

2008-03-08

PerlでのWebアプリケーションのテストツール

12:25 |  PerlでのWebアプリケーションのテストツール - dann@catalyst を含むブックマーク はてなブックマーク -  PerlでのWebアプリケーションのテストツール - dann@catalyst  PerlでのWebアプリケーションのテストツール - dann@catalyst のブックマークコメント

Webアプリに限定しているわけではないですが、まとめてみました。

単体テスト

  • Test::Class
  • Test::Base
    • データドリブンのテスト
  • Test::More

Mock

  • mocked
    • Railsのtest/mocks的なもの
  • Test::MockObject ?

カバレッジテスト

  • Devel::Cover

機能テスト

結合テスト

  • Socialtext::WikiTest
    • SeleniumRC+Wikiでのテストに使う。名前空間があれだけれど、Socialtextに依存はしていない。Fixtureだけ各Wiki用に用意すればよい。
  • Test::WWW::Selenium
    • PerlでSeleniumRCをhandle

Smoke test

  • Test::Chimps ?

ファイル変更時の自動テスト

  • Test::Continuous

Continuous Integration

  • buildbot

その他

  • Test::Less
    • 特定のテストスクリプトに tag をつけて特定の範囲だけのテストを実行する

See also:

http://qootas.org/blog/archives/2006/08/post_30.html

    * Test::Chimps をつかってどのリビジョンでどのエラーが発生しているのかを記録
    * Test::Base でテストコードをデータドリブンで書きやすくする
    * Test::Less をつかって特定のテストスクリプトに tag をつけて特定の範囲だけのテストを実行する

疑問点

  • Perl界隈での標準的なMockライブラリがよくわかってない。Test::MockObject あたりかな?
  • Test::Lessは、便利そうなんだけれど、特定範囲という場合の特定範囲のtagにどんなものがありうるのかが、まだわからないなぁ。ここはアプリケーション依存だとは思うのだけれど。

TODO

  • Test::Chimpsを使ってみる。Smoke Testの需要はある気がする。ただ、smoke testだけじゃなくて、buildbot使うだけでいいかもしれない。

いいContinuous Integrationツールは? その2

22:13 |  いいContinuous Integrationツールは? その2 - dann@catalyst を含むブックマーク はてなブックマーク -  いいContinuous Integrationツールは? その2 - dann@catalyst  いいContinuous Integrationツールは? その2 - dann@catalyst のブックマークコメント

buildbotは複数チームで複数ブランチで平行開発しているときには、複数ブランチのテスト結果が一覧でみれるのでいいかなぁと思うんですが、やっぱりテスト結果の見え方がいまいちだなぁと。

ということで、もう少し探してみました。そこで見つけたのが、smolderです。

http://sourceforge.net/projects/smolder

Web-Based Smoke Test Aggregator used by developers and testers to upload (automated or manually) and view smoke/regression tests using the Test Anything Protocol. Details and trends can be viewed in various formats. Notifications of runs and failures via

以下で簡単に紹介されています。

http://www.slideshare.net/mpeters/smolder-introduction

ここで書かれている課題が一番解決したい課題かなぁと。画面イメージを見た感じでも、自分が解決したい課題を解決してくれるツールかなって気がします。ちょっと後で試してみようかな。

 PerlのDIコンテナ - Bread Board

21:08 |  PerlのDIコンテナ - Bread Board - dann@catalyst を含むブックマーク はてなブックマーク -  PerlのDIコンテナ - Bread Board - dann@catalyst  PerlのDIコンテナ - Bread Board - dann@catalyst のブックマークコメント

http://search.cpan.org/~stevan/Bread-Board-0.03/

依存関係を設定するところが一箇所にまとまってしまうところが、ちょっといまいちかなぁという気がしました。Javaだと1世代前のDIコンテナにあたるかなと。

JavaのDIコンテナも、最初はこんな感じで、依存関係を設定するところが全てXMLで記述されていたんですが、これはとてもよくなかったなと思っていました。XMLだったのがよくなかったというのもあるんですが、依存関係を設定する部分が、実際の依存関係をインジェクトされる側との距離が遠すぎるというのが一番良くなかったなと思っています。

最近のDIコンテナは、依存関係のインジェクションが必要なクラスに、JavaのAnnotationでメタデータを記述するようになっているので、該当のクラスをみれば、どのようなものがインジェクトされるのか、インジェクトされるもののScopeが何なのかというのがすぐにわかるようになっています。

Annotaionは、PerlだとAttribteに近いのかもしれません。あんまり、Attributeのことをわかってないかもしれませんが...

# yappoさんの記事がわかりやすそうなので、後で見る。

http://blog.yappo.jp/yappo/archives/000348.html

まだ、0.03なので、どのような方向で進むかはわかりませんが、DIコンテナとして使うには時期尚早かなという気がしました。当面必要なのは、Configurationをフレームワークに依存しない形で参照すればいいだけなので、それでいこうかなと。

Catalystアプリの開発で使える周辺ツール

20:48 |  Catalystアプリの開発で使える周辺ツール - dann@catalyst を含むブックマーク はてなブックマーク -  Catalystアプリの開発で使える周辺ツール - dann@catalyst  Catalystアプリの開発で使える周辺ツール - dann@catalyst のブックマークコメント

今のところ、以下のものですね。

capistranoもbuildbotも、言語を選ばずに使えそうなのと、出来はよさそうなのでもう少し使い込もうかなと思ってます。capistranoruby, buildbotはpythonと、Perlとはあまり関係ないんですが、他の言語を使うのも楽しいのでそれでいいかなと。

いいCIツールは?

20:40 |  いいCIツールは? - dann@catalyst を含むブックマーク はてなブックマーク -  いいCIツールは? - dann@catalyst  いいCIツールは? - dann@catalyst のブックマークコメント

Perl界隈で何かいいCIツールがあれば、それを使ってみようかと思ったのですが、さっと探した感じではなさそうだったので、buildbotを使ってみることにしました。pythonで記述されてますが、python専用のCIツールではないです。使ってみた感じだと、一通りCIツールとしての機能はもっているかなという印象です。

他に何かいいツールがあれば、だれかエロイ人教えてください!

# miyagawaさんからTest::Continuousを教えてもらったのですが、ちょっと自分が思っているCIツールとは違うかなぁと。Test::Continuousは、ZenのAutotestと殆ど同じで、ファイル変更タイミングでテストが走る仕組みなので、個人で使うツールかなぁと。スケジュールビルドをして、日に1-2回の単位でデグレードをチェックをして、チーム全体で結果を共有するっていう用途で使いたいなぁと。

Continuous Integrationのイメージは大体以下のページに書かれています。

http://www.martinfowler.com/articles/continuousIntegration.html

JavaだとContinuumとかCruiseControlにあたるものかなぁと。

複数ブランチのビルド結果を一覧できるbuildbot

| 20:40 |  複数ブランチのビルド結果を一覧できるbuildbot - dann@catalyst を含むブックマーク はてなブックマーク -  複数ブランチのビルド結果を一覧できるbuildbot - dann@catalyst  複数ブランチのビルド結果を一覧できるbuildbot - dann@catalyst のブックマークコメント

とある会社で開発していたときは、15人程度で開発をやっていました。複数の開発チームに分かれて、開発チームごとにブランチが切り、平行して開発を進めていました。その会社ではCIツールは自作していたのですが、全体の開発のブランチの状況が一覧できなかったのは、よくなかったなと思いました。

buildbotでは、各ブランチのビルド・テスト結果が一覧してみれるので、なかなかいいなと思っています。Windows上でも動作するようなので、複数のプラットフォームでテストするようなプロダクトや、複数ブランチで平行して開発しているようなところでは結構使えるんじゃないかと思いました。

これが、割と多くのプロジェクトで使われている理由なのかなという気もします。

CatalystアプリをbuildbotでContinuous Integration

| 20:29 |  CatalystアプリをbuildbotでContinuous Integration - dann@catalyst を含むブックマーク はてなブックマーク -  CatalystアプリをbuildbotでContinuous Integration - dann@catalyst  CatalystアプリをbuildbotでContinuous Integration - dann@catalyst のブックマークコメント

buildbotはPythonで記述されたCIツールで、割と多くのプロジェクトで使われているようです。

http://buildbot.sourceforge.net/manual-0.7.5.html

どのような形で結果が見えるのかは、djangoのページなどを参照するのがわかりやすいです。

http://buildbot.djangoproject.com/

buildbotでは、スケジュールに応じてビルド・テストなどを行い、ビルド・テストの結果をメールやIRCなどで通知させることができます。CIツールはテスト数が多くなってきたときに活躍します。日に数回、全体の単体テスト・機能テストを全て実行するようにしておくと、プロダクトのデグレードは減ります。

前置きはおいといて、実際にbuildbotの設定方法を見ていきましょう。

インストール

sudo aptitude install buildbot

マスターの作成

% buildbot create-master ~/Buildbot/master/MyApp

マスターの設定

% vim ~/Buildbot/master/MyApp/master.cfg

master.cfgには、大きく分けて、大体以下の4つの設定をします

  • sourcesに、何をチェック対象にするかを記述
  • scheduleに、どのようなタイミングでsourceをチェックするかを設定
  • buildersに、ビルドやテストのステップを記述
  • statusに、ビルド結果の通知方法を記述

master.cfgは、以下のような感じに書きます。

# -*- python -*-
# ex: set syntax=python:

# This is a sample buildmaster config file. It must be installed as
# 'master.cfg' in your buildmaster's base directory (although the filename
# can be changed with the --basedir option to 'mktap buildbot master').

# It has one job: define a dictionary named BuildmasterConfig. This
# dictionary has a variety of keys to control different aspects of the
# buildmaster. They are documented in docs/config.xhtml .


# This is the dictionary that the buildmaster pays attention to. We also use
# a shorter alias to save typing.
c = BuildmasterConfig = {}

####### BUILDSLAVES

# the 'bots' list defines the set of allowable buildslaves. Each element is a
# tuple of bot-name and bot-password. These correspond to values given to the
# buildslave's mktap invocation.
c['bots'] = [("MyApp-bot","buildbot")]


# 'slavePortnum' defines the TCP port to listen on. This must match the value
# configured into the buildslaves (with their --master option)

c['slavePortnum'] = 9989

####### CHANGESOURCES
# the 'sources' list tells the buildmaster how it should find out about
# source code changes. Any class which implements IChangeSource can be added
# to this list: there are several in buildbot/changes/*.py to choose from.

from buildbot.changes.svnpoller import SVNPoller
source_code_svn_url='http://192.168.0.30/svn/MyApp/trunk'
svn_user='buildbot'
svn_password='password'

svn_poller = SVNPoller(
    svnurl=source_code_svn_url,
    svnuser=svn_user,
    svnpasswd=svn_password,
    pollinterval=60*1, #seconds
    histmax=10,
    svnbin='/usr/bin/svn',)

c['sources'] = [ svn_poller ]

####### SCHEDULERS

## configure the Schedulers
# When to run builds
from buildbot import scheduler
daily = scheduler.Periodic("daily", ["MyApp-Builder"], 24*60*60)
code_changed = scheduler.Scheduler(name="code_changed",
    branch=None,
    treeStableTimer=10*60,
    builderNames=["MyApp-Builder"])
c['schedulers'] = [ daily,code_changed ]

####### BUILDERS
# How to build the software
builders = []

from buildbot.process import factory
from buildbot.steps import source,shell
f1 = factory.BuildFactory()
f1.addStep(source.SVN,
    svnurl=source_code_svn_url,
    mode="clobber")
f1.addStep(shell.ShellCommand, command=['perl', 'Makefile.PL'])
f1.addStep(shell.ShellCommand, command=['make'])
f1.addStep(shell.ShellCommand, command=['make', 'test'])

b1 = {'name': 'MyApp-Builder',
    'slavename': 'MyApp-bot',
    'builddir': 'myapp_build_dir',
    'factory': f1,}
c['builders'] = [b1]

####### STATUS TARGETS
# 'status' is a list of Status Targets. The results of each build will be
# pushed to these targets. buildbot/status/*.py has a variety to choose from,
# including web pages, email senders, and IRC bots.


from buildbot.status import html
from buildbot.status import words
htmlStatus = html.Waterfall(http_port=8010)
ircStatus = words.IRC(host="irc.example.net", nick="buildbot",
                              channels=["#myapp-test"])
c['status'] = [htmlStatus,ircStatus]

c['status'] = [htmlStatus,ircStatus]

# from buildbot.status import mail
# c['status'].append(mail.MailNotifier(fromaddr="buildbot@localhost",
#                                      extraRecipients=["builds@example.com"],
#                                      sendToInterestedUsers=False))
#
# from buildbot.status import words
# c['status'].append(words.IRC(host="irc.example.com", nick="bb",
#                              channels=["#example"]))
#
# from buildbot.status import client
# c['status'].append(client.PBListener(9988))


####### DEBUGGING OPTIONS

# if you set 'debugPassword', then you can connect to the buildmaster with
# the diagnostic tool in contrib/debugclient.py . From this tool, you can
# manually force builds and inject changes, which may be useful for testing
# your buildmaster without actually commiting changes to your repository (or
# before you have a functioning 'sources' set up). The debug tool uses the
# same port number as the slaves do: 'slavePortnum'.

#c['debugPassword'] = "debugpassword"

# if you set 'manhole', you can ssh into the buildmaster and get an
# interactive python shell, which may be useful for debugging buildbot
# internals. It is probably only useful for buildbot developers. You can also
# use an authorized_keys file, or plain telnet.
#from buildbot import manhole
#c['manhole'] = manhole.PasswordManhole("tcp:9999:interface=127.0.0.1",
#                                       "admin", "password")


####### PROJECT IDENTITY

# the 'projectName' string will be used to describe the project that this
# buildbot is working on. For example, it is used as the title of the
# waterfall HTML page. The 'projectURL' string will be used to provide a link
# from buildbot HTML pages to your project's home page.

c['projectName'] = "MyApp"
c['projectURL'] = "http://192.168.0.30/"

# the 'buildbotURL' string should point to the location where the buildbot's
# internal web server (usually the html.Waterfall page) is visible. This
# typically uses the port number set in the Waterfall 'status' entry, but
# with an externally-visible host name which the buildbot cannot figure out
# without some help.

c['buildbotURL'] = "http://192.168.0.30:8010/"

スレーブ用のアカウント作成

アカウント名はbuildbotで。

スレーブの作成

スレーブのアカウントで、スレーブ作成

buildbot create-slave /home/buildbot/Buildbot/slave/MyApp 192.168.0.30:9989 MyApp-bot buildbot

スレーブの設定ファイルは、buildbot.tacに記述されている。

マスターとスレーブの起動

master% buildbot start /home/buildbot/Buildbot/slave/MyApp
buildbot % buildbot start /home/buildbot/Buildbot/master/MyApp

これで、上記のmaster.cfgの設定では、Subversionにチェックインされたコードがあればビルドされます。また、Dailyでビルドされます。結果は、http://192.168.0.30:8010/で見ることができます。

テストが失敗していれば、その部分が「赤く」表示されます。

Catalystアプリのテストと書いていますが、make testしているだけなので、他のものでもテストできます。

設定・実行の際の注意点

  • 記述が間違っている場合のエラーメッセージが貧弱なので、エラーがでたらStackTraceを見て、どこが間違っているかを探す。
  • twistd.* は消してから、buildbot start を実行しないとダメ

ゲスト



トラックバック - http://catalyst.g.hatena.ne.jp/dann/20080308