Monthly Archives: 10月 2009

Cucumber+WebratでPHPアプリのテストをする

sudo gem install cucumber mechanize rspec webratPHP – cucumber – GitHub

を参考にCucumberでPHPアプリケーションの受け入れテストを作成・実行してみます。さらにこのチュートリアルでは日本語でテストを記述してみます。

Cucumberのインストール

Ruby 1.9.1をすでにインストールしてある環境です。まずはCucumber・Webrat・mechanize・rspecをインストールします。

$ sudo sudo gem install cucumber mechanize rspec webrat

ディレクトリの作成

テストするPHPアプリのトップディレクトリに以下のディレクトリを作成します。

features
features/support
features/step_definitions

環境設定ファイルの作成

features/support/env.rbを以下の内容で作成します。RSpecやWebratを読み込んで、各種設定を行っています。Seleniumを利用するといった場合はこのファイルを編集して設定を変更します。

# RSpec
require 'spec/expectations'
 
# Webrat
require 'webrat'
 
require 'test/unit/assertions'
World(Test::Unit::Assertions)
 
Webrat.configure do |config|
  config.mode = :mechanize
end
 
World do
  session = Webrat::Session.new
  session.extend(Webrat::Methods)
  session.extend(Webrat::Matchers)
  session
end

Cucumberのコマンドライン引数の設定

Cucumberのコマンドライン引数のデフォルトを設定するために以下の内容でルートディレクトリにcucumber.ymlを作成します。–language jaを指定することで日本語でテストを記述できるようになります。以下のdefaultではコマンドラインに結果が出力されますが、結果をHTMLで出力する設定を記述しておき、テスト実行時に適宜設定を指定することができます。

default: --language ja features

ステップの作成

features/step_definitionsディレクトリにwebrat_steps.rbとresult_steps.rbの2つのテストステップファイルを作成します。

features/step_definitions/webrat_steps.rb
Webratでページにアクセスしたりボタンをクリックしたりできるステップを作成します。

# -*- encoding: UTF-8 -*-
 
前提 /^(.*)ページを表示している$/ do |path|
  @response = visit "http://localhost/php_with_cucumber#{path}"
end
 
もし /^(.*)ページを表示する$/ do |path|
  @response = visit "http://localhost/php_with_cucumber#{path}"
end
 
もし /^"(.*)"ボタンをクリックする$/ do |button|
  @response = click_button(button)
end
 
もし /^"(.*)"リンクをクリックする$/ do |link|
  @response = click_link(link)
end
 
もし /^"(.*)""(.*)"と入力する$/ do |field, value|
  @response = fill_in(field, :with => value) 
end
 
もし /^"(.*)"から"(.*)"を選択する$/ do |field, value|
  @response = select(value, :from => field) 
end
 
もし /^"(.*)"をチェックする$/ do |field|
  @response = check(field) 
end
 
もし /^"(.*)"のチェックを外す$/ do |field|
  @response = uncheck(field) 
end
 
もし /^"(.*)"を選択する$/ do |field|
  @response = choose(field)
end
 
もし /^パスが"(.*)"のファイルを"(.*)"に添付する $/ do |path, field|
  @response = attach_file(field, path)
end

ページの表示ではhttp://localhost/php_with_cucumberを直に書き込んで、テストを記述するfeatureファイルではアドレスを省略できるようにしています。

features/step_definitions/result_steps.rb
結果の検査を行うステップを作成します。

# -*- encoding: UTF-8 -*-
 
ならば /^"(.*)"と表示される$/ do |text|
  response_body.to_s.force_encoding("UTF-8").should =~ /#{text}/m
end
 
ならば /^"(.*)"と表示されない$/ do |text|
  response_body.to_s.force_encoding("UTF-8").should_not =~ /#{text}/m
end
 
ならば /^(\w+)メッセージが表示さる$/ do |message_type|
  @response.should have_xpath("//*[@class='#{message_type}']")
end
 
ならば /^(.*)リクエストが失敗する/ do |_|
  @response.should_not be_successful
end
 
ならば /ページ読み込みが成功する/ do
  @response.code.should == "200"
end

今回のテストでは使用しないステップも含まれています。実際に動作するか検証してませんが、こんな感じで作成するということで参考にしてください。

テスト対象のコード

実際にはテストを記述してコードを作成していくかもしれませんが、今回はすでに作成した以下のPHPコードをindex.phpとして保存してテストしてみます。機能はテキストエリアにテキストを入力してSubmitをクリックすると、入力したテキストが表示されるというものです。

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="ja">
 
<head>
    <title>PHP with Cucumber</title>
</head>
<body>
    <h1>PHP with Cucumber</h1>
 
    <?php if(!isset($_GET['text']) or empty($_GET['text'])) print '<p>テキストを入力してください。</p>'; ?>
 
    <form action="/php_with_cucumber/index.php" method="get">
        <p><textarea name="text" rows="10" cols="100"></textarea></p>
        <p><input type="submit" value="Submit" /></p>
    </form>
 
    <p class="printed_text"><?php if(isset($_GET['text'])) print $_GET['text']; ?></p>
 
    <p><a href="./">リセット</a></p>
</body>
</html>

テストの作成

テストを作成します。featuresディレクトリにshow.featureファイルを作成します。ページの表示・結果の表示・表示のリセットをテストします。

機能: トップページの表示とサブミット
 
  シナリオ: トップページの表示
    もし /ページを表示する
    ならば ""と表示される
    かつ "テキストを入力してください。"と表示される
 
  シナリオ: テキストの入力と結果の表示してリセットする
    前提 /ページを表示している
    もし "text"に"テスト用のテキストです。"と入力する
    かつ "submit"ボタンをクリックする
    ならば "テスト用のテキストです。"と表示される
    かつ "テキストを入力してください。"と表示されない
    もし "リセット"リンクをクリックする
    ならば "テキストを入力してください。"と表示される

もっと機能があれば機能ごとにファイルを分割します。またこの例では、テスト内容は不十分ですので、ステップやシナリオを追加して試してみてください。

テストの実行

ではテストを実行してみます。コマンドラインでルートディレクトリに移動してcucumberを実行します。

$ cucumber
Using the default profile...
機能: トップページの表示とサブミット
 
  シナリオ: トップページの表示                                # features/show.feature:3
    もし /ページを表示する                                 # features/step_definitions/webrat_steps.rb:7
    ならば ""と表示される # features/step_definitions/result_steps.rb:3
    かつ "テキストを入力してください。"と表示される                    # features/step_definitions/result_steps.rb:3
 
  シナリオ: テキストの入力と結果の表示してリセットする     # features/show.feature:8
    前提 /ページを表示している                # features/step_definitions/webrat_steps.rb:3
    もし "text"に"テスト用のテキストです。"と入力する # features/step_definitions/webrat_steps.rb:19
    かつ "submit"ボタンをクリックする         # features/step_definitions/webrat_steps.rb:11
    ならば "テスト用のテキストです。"と表示される      # features/step_definitions/result_steps.rb:3
    かつ "テキストを入力してください。"と表示されない    # features/step_definitions/result_steps.rb:7
    もし "リセット"リンクをクリックする           # features/step_definitions/webrat_steps.rb:15
    ならば ページ読み込みが成功する              # features/step_definitions/result_steps.rb:19
    かつ "テキストを入力してください。"と表示される     # features/step_definitions/result_steps.rb:3
 
2 scenarios (2 passed)
11 steps (11 passed)
0m0.029s

すべてのシナリオがパスしました。ここで、たとえば「ならば “テスト用のテキストです。”と表示される」を「ならば “テストのテキストです。”と表示される」に変更してCucumberを実行してみると、11 steps (1 failed, 4 skipped, 6 passed)となります。コマンドラインではカラーで表示されるので、真っ赤な画面だったらfailedで、緑だったらpassedです。

おまけ

作成したファイルの書庫: php_with_cucumber.zip

最終的なディレクトリ・ファイル構成

.
|-- cucumber.yml
|-- features
|   |-- show.feature
|   |-- step_definitions
|   |   |-- result_steps.rb
|   |   `-- webrat_steps.rb
|   `-- support
|       `-- env.rb
`-- index.php
Log

Safari AdBlockerをインストール

Safariで広告を非表示にしてくれるSIMBL PluginのSafari AdBlockerをインストール。

SIMBL自体は最新だったっけ…。

Log

Libera Memory Residentを導入

メモリのInactive値を監視し設定値以上になったら解放を試みる『Libera Memory Resident』 | Macの手書き説明書を読んで Libera Memory Residentを導入。

Libera Memoryはたまに使っているので、自動化になるのはうれしい。

実際にメモリを解放しているのはPHPスクリプトらしい。

これってlaunchdを使っているということなんで、ログイン項目には追加する必要はないということかな。

Log

LaunchBarからFolderをForkLiftで開く

ForkLiftがAppleScriptに対応してないのでLaunchBarがForkLiftに対応してない。ので、AppleScriptのkeystrokeでなんとか開けるようにした。

on open theString
	set the clipboard to POSIX path of theString
 
	tell application "ForkLift"
		activate
	end tell
 
	tell application "System Events"
		keystroke "g" using {command down, shift down}
		keystroke "v" using command down
		keystroke return
	end tell
end open

これを/Users/r_izumita/Library/Application Support/LaunchBar/Actionsに保存して、LaunchBarのIndexを更新。LaunchBarでフォルダを選択してこのスクリプトを実行すると、ForkLiftでフォルダが表示される。

ファイルの親フォルダを表示する機能は未実装。

日本語入力プログラム「かわせみ」を使ってみた

以前使っていたegbridgeが終了してしまって、しかたなくATOKを使ってました。

が、ついに物書堂さんが発売した日本語入力プログラム「かわせみ」が公開されました。一部機能が削られていますが、かな漢字変換エンジンやインターフェースはegbridge Universal 2のものです。

この文は「かわせみ」で入力しています。

これまでTeslaを使って親指シフトで入力していましたが、かわせみでもTeslaを問題なく使用できました。

そして最も重要な点ですが、egbridge Universalと同様、ATOKより入力に対する反応が速いです。Teslaで親指シフト入力していますが、ATOKだとキー入力し終わったあとにタタタと表示がついてくるといった感じでしたが、かわせみはキー入力した瞬間に表示されます。親指シフトは入力が速いとされてますが、ATOKでは意味ない!って状態だったのが、やっとまともに使えるIMになりました(戻ることができました、かな)。どんなに変換効率が良くても遅くてはストレスですからね。

そしてこれまた重要な変換効率ですが、ATOKと遜色ない感じです。というか、egbridgeエンジンなんで馴染みのものです。

それから、ATOKは環境設定とかキー割当とかのツールが使いにくいですが、egbridgeは使いやすかったので、かわせみも当然使いやすいですね。ただ問題もあって、Dvorakではキー割り当て編集ツールで正しく割り当てられないという障害があります。これはegbridge時代からの問題で、一度US配列にしてキー割り当てしてDvorakに戻すと、割り当てられます(割り当て方に工夫が必要ですが)。

また、要望もあります。句読点変換だと読点入力で毎回変換されてしまうので、句点変換も追加して欲しいです。

価格ですが1ライセンスとファミリーパックがあって、この価格。

ライセンス数:1(1台のみの Macにインストールしてご利用いただけます)

価格:1,995円(税込)

かわせみ ファミリーパック

ライセンス数:3(3台までの Macにインストールしてご利用いただけます)
価格:3,990円(税込)かわせみ | Mac | 物書堂

IMでこの価格は安い。かわせみには体験版がありますが、インストールする前に購入決定。

というわけで、ATOKに避難してましたが、今後は「かわせみ」にお世話になります。

Twitterでのユーザサポートは安近短

何があったのか

先日公開された日本語入力プログラム「かわせみ」ですが、バグ報告をしました。
おそらく、かわせみの前身であるegbridgeからのバグだと思います。egbridgeのときに報告しておけばすでに改善されていたかもしれません。が、たしか報告していませんでした。
たいていサイトに行くとお問い合わせフォームを探して、問い合わせを書いて送信します。フォームを探すのも面倒ですし、どう書いたものやらということもありますし、報告してもきちんと対応してもらえるかも分かりません。有り体にいえば面倒。ですが、今回は何が違ったのでしょうか。それは報告したのがTwitterでだったからです。

Twitterでの報告は

Twitterでの報告は簡単に気軽に行えます。相手がTwitterでよくつぶやいていれば、どのような相手かもわかります。返事も早く返ってくるだろうと考えました。
つまりTwitterでのユーザサポートは安近短=安心して、手近にあるTwitterサイトやTwitterクライアントで、手短&短時間で報告返信ができる、ということだと思いました。

実際のやり取り

というわけで、実際のやり取りを見てもらいましょう。

かわせみを開発した物書堂さんのTwitterアカウントにリプライで障害について質問したのが08:24:57。

@monokakido かわせみのキー割り当て編集ツールでDvorak配列だと正しく割り当てられなくて困ってます。たとえば、キーボード刻印でいうとctrl+dもctrl+eもctrl+eになって、実入力だとctrl+.になってしまう。説明難しい…。Twitter / r.izumita: @monokakido かわせみのキー割り当て編集ツ …

物書堂さんから、再現したとの連絡が08:37:30。

@r_izumita 再現しました。これは根が深そうです。大変申し訳ありませんが、こちらのフォームよりお問い合わせください。調査してご案内差し上げます。 https://www.monokakido.jp/m…Twitter / norihito: @r_izumita 再現しました。これは根が深そう …

その間13分弱。
さらにサイトのフォームで連絡して、連絡の連絡をTwitterでつぶやいたのが08:47:33。

問い合わせフォームから送信しました。egbridgeの頃からあるバグだと思います。よろしくお願いします。 RT @monokakido: @r_izumita 再現しました。これは根が深そうです。Twitter / r.izumita: 問い合わせフォームから送信しました。egbridge …

2分後に、フォームが到着したとの返信。08:49:55。

ありがとうございます。フォームは無事に到着しました。エンジニアに調べさせますのでしばらくお待ちください。Twitter / norihito: @r_izumita ありがとうございます。フォーム …

次の日の朝メールを見てみたら、回避策が届いてました。かわせみのユーザサポートはハヤブサでした。

ユーザとしてはTwitterでのサポートが普及ほしいですね。

Log

TreeをMacPortsでインストール

ディレクトリ構造を表示したかったのでTreeをMacPortsでインストールした。

$ sudo port install tree

ディレクトリ1階層のみ表示する場合は

$ tree -d -L 1

Log

nanoをMacPortsでインストール

gitでcommitをしようとしたら、nanoで日本語が表示できなかった。
Snow LeopardのnanoはUTF-8のサポートが有効になっていなかったので、MacPortsでnanoをインストール。

$ sudo port install nano
$ nano -V                                                              [~]
 GNU nano version 2.0.9 (compiled 12:06:31, Oct 27 2009)
 (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
 Free Software Foundation, Inc.
 Email: nano@nano-editor.org	Web: http://www.nano-editor.org/
 Compiled options: --disable-wrapping-as-root --enable-color --enable-extra --enable-multibuffer --enable-nanorc --enable-utf8


ということで、–enable-utf8になってます。

GIT_EDITORも指定。

export GIT_EDITOR=/opt/local/bin/nano

Get Adobe Flash playerPlugin by wpburn.com wordpress themes