トップ  > メモ一覧  > カテゴリ「開発テスト」の絞り込み結果 : 3件

3件中 1 〜 3 表示  1 

No.3839【引用】PHPでTDD&CIワークショップにいってきました

PHPでTDD&CIワークショップにいってきました
php , TDD
PHPでTDD&CIワークショップ にいってきました。スタッフのみなさん、会場を提供してくれた GREE のみなさんには感謝感謝です。
独学ながらTDDについて学んでるところなんですが、やっぱり同じ目的を持って勉強会に参加している方の手法や姿勢をみていると刺激になります。はじめての ペアプロ も楽しかったです。 jenkins の セッション もすごく興味深いのであとでおさらいしてみたいですね。
さて、僕が参加したTDDセッションではおな...

引用元

更新:2011/06/24 10:44 カテゴリ: web開発  > 開発テスト ▲トップ

No.2145 いまからでも間に合う開発者テスト

いまからでも間に合う開発者テスト

By kzys on 3 月 1, 2010 in mixi.

はじめまして。開発部じゃない加藤和良です。

最近、mixi では Buildbot をつかった継続的インテグレーションをはじめています。安定版の mixi のソースコードにコミットすると Buildbot がそれを検知し、自動的にテストが走るようになりました。

ここでの「テスト」は Test::Simple や prove(1) をつかった、Perl でかかれた開発者テストを指しています。mixi の開発者テストをとりまく環境は、ここ数年でかなり改善されました。今回はその歩みをふりかえりながら、テストの無いコードベースをどこからどうやって変 えていったかという話をしたいと思います。

開発環境

はじめに、前提となる mixi の開発環境について説明します。mixi では複数人の開発者がひとつのマシンで作業を行います。それぞれの開発者は、あらかじめ割り当てられたポートで Apache を起動し、自分の好きなエディタでソースコードを編集しながら生活しています。

開発環境

memcached は各マシンに一台。そして、沢山の MySQL 群や、数台の Tokyo Tyrant, Shindig などは社内のほぼ全員が同じものを共有しています。

当然のことながら、これらのサーバーは皆さんがお使いの 本番の mixi で使っているものとは、別のものです。以下で「日記」とか「ボイス」とか書いてあるのは、開発者が開発環境でつくっているデータをさすことに、あらかじめ注意してください。

2007年4月 – t/ の追加と当時の問題

mixi のソースコードは以下のように配置されています。

lib/, t/ があるのは CPAN モジュールでもありがちですが、t/ の下に lib/ と同じような階層構造があるのは、ちょっと珍しいかもしれません。

  • /
    • lib/
      • Mixi/Application/Object.pm
    • t/lib/
      • Mixi/Application/Object/leave.t

この t/ フォルダは、2007年4月ごろにレポジトリに追加されました。ここから mixi の開発者テストの歴史がはじまるわけですが、当時のテストまわりにはいくつかの問題がありました。

一般に、テストを書きやすいコードは、以下のような性質を持っていると思います。

テストしやすい

  • 結果を左右する入力をどこから与えるべきかわかりやすい
  • 結果がどこに出力されているかわかりやすい
  • それ以外の副作用が無い

たとえば、文字列のうち HTML 上で特殊な意味をもつものをエスケープする関数や

is(escape('foo & bar'), 'foo & bar');

スタックを表現するクラスなどは「テストを書きやすい」部類のコードと呼べます。

my $stack = Stack->new;
ok(! $stack->pop);
$stack->push(123);
is($stack->pop, 123);

しかし、当時の mixi のコードベースには、前述の性質をそなえていないものが多くありました。

  • 入力として、どこかの環境変数を読んでいたり、どこかのデータベースの情報を読んでいたり、new しづらいクラスを使っている
  • 出力が標準出力への print だったり、データベースのどこかへの更新や削除だったり、例外処理で exit してしまったりしている
  • 副作用としてどこかのデータベースや memcached に更新や削除を行ってしまう

結果、テストを書くのがむずかしかったり、せっかく書いたテストが、誰かが日記を消したり、マイミク関係を解消したのをきっかけに突然失敗するよう になったり、テストを実行したらどこかのボイスの投稿が消えるかも、みたいな不安で他人が書いたテストを動かしづらかったり、といったことが起こりがちで した。

2008年12月 – Mixi::Test::Fixtures

これらの問題を解決するべく、2008年12月ごろ Mixi::Test::Fixtures という新しいライブラリが追加されました。

Mixi::Test::Fixtures は、RailsDjango にある “fixture” の仕組みを、mixi のコードベースに導入するためのライブラリです。具体的には、以下のような動作を行います。

  1. テストの実行直前に、一時的なデータベースを作成
  2. 指定された YAML から、データベースに値を挿入
  3. テストの実行
  4. テストの実行直後に、いろいろ変更のあったデータベースを削除

mixi は OR マッパを使っていない部分もいろいろあり、手書きの SQL が MySQL を期待しているところが多々あります。そのため、一時的なデータベースにも SQLite のようなインプロセスのデータベースは使わず、MySQL をそのまま使っています。テストの実行前後に CREATE DATABASE / DROP DATABASE が走るのはなかなか富豪的です。

Mixi::Test::Fixtures の導入によって

  • テストが、いつ変わるかわからないデータベース上の情報に依存している
  • テスト実行後にデータベース上に様々なデータが作成・削除され、2回目以降の実行では前提となる条件が変わってしまう

といった問題は回避できるようになりました。

その後、何度かのバージョンアップがあり、現在ではデータベース以外に

  • memcached
  • メールの送信
  • 外部への HTTP アクセス

も Mixi::Test::Fixtures で差し替えが可能です。これらの動作を模倣するのはデータベースに比べるとずっと簡単なので、インプロセスで代替のコードが動くようになっています。

2009年4月 – ブラックリストの導入

Mixi::Test::Fixtures 導入以後、新しいテストについては、だれでもいつでも安心して実行できるようになりました。ただ、古いテストのなかには、まだ fixture への移行がすんでいないものもあり、気軽に実行するのは不安がありました。

一方で、すべてのテストを実行したいという要求もありました。コードの変更が予想外の部分をこわしていないかを確かめるためには、なるたけ多くのテストを実行したほうが安心です。

この中途半端な状態をなんとかするために2009年4月ごろ導入されたのが、ブラックリストと、それを使って「ホワイトな」テストを列挙する仕組みです。

まず t/blacklist.yaml に

patterns:
 - "^t/lib/Mixi/Official/Member/.*$"
files:
 - t/lb/Mixi/Application/DB/Ad.t
...

と、だれもが気軽に実行するのがまだ難しいテストを列挙していきます。これを元に list-tests というスクリプトが

% ./script/devel/list-tests
t/lib/Mixi/Application/Object/leave.t
...
%

t/ 以下をなめて blacklist.yaml にマッチしないテストの一覧を出力します。これを

% prove -lv `./script/devel/list-tests`
....

といった感じで prove(1) にわたすことで、誰もが何時でも実行できるテストだけを、簡単に実行することができます。列挙までして prove(1) の実行は行わないのは

% prove -lv `./script/devel/list-tests | grep Application`
....

のように他のソフトウェアとの連携を考えてのものです。

ブラックリストの導入に関しては

  1. 実行に注意が必要なテストはだめなので、修正するか消す
  2. t/, xt/ などテストをいれるフォルダを二つに分ける
  3. 個々のテストに plan skip_all => ‘…’; みたいなものを記述する

というやりかたもあったと思います。

ただ、1 は修正が完了するまでテストの全実行をあきらめなくてはいけないこと、かといって締切を設定し、それまでに修正されないテストは消す、となるとテストが消 えすぎること、そもそも「実行に注意が必要なテストはだめ」というのが微妙で、書いた人しか実行できないテストでもないよりはマシなことを考えて、無しに なりました。

2 は、ファイルの移動に Subversion が弱いことと、2つの分割ですまなくなったときにどうしよう、というのが不安なところでした。

3 については、柔軟で良さげなので、将来的にはここに落ち着くんじゃないかと思っています。いまになって思えば、最初からこれでも良かったかもしれないですね。

2009年5月 – Test::Apache2

Mixi::Test::Fixtures とブラックリストは mixi 全体にかかわる部分でした。ここからは、各々のコードに関わる細かな部分に目をむけてみようと思います。

Test::Apache2 は mod_perl ハンドラのテストを書くためのライブラリです。目的だけみれば Apache::Test によく似ていますが、本物の Apache を立ち上げないでインプロセスで動くところが大きなちがいです。mod_perl 特有の細かな状況 (具体的にはあんまり把握していません) についてテストを書くのには向きませんが、反面、実行速度が速く準備も簡単です。

Test::Apache2 は2009年の5月ごろに mixi の安定版で使えるようになりました。現在では mixi から切り出して CPAN 上で配布しているので、mixi の外でも使えます。

既存の mod_perl ハンドラの挙動をとりあえずテストで囲いたい、みたいなときに、ちまちま Test::MockObject で Apache2::RequestRec を模倣するよりは便利だと思うので、ぜひ試してみてください。

2009年12月 – Test::Exit

Test::Exit は exit の呼び出しをテストするためのライブラリで、Andrew Rodland さんが開発されています。

...
exits_nonzero {
  invalid_op(); # なかで exit(1) する
};
done_testing;

こんなふうにつかえます。mixi では例外処理のなかで exit してしまう CGI ノリのコードがごくまれにあり、そういうものに対処するために2009年12月ごろにつかいはじめました。

Test::Exit には当時 exit($status); のみ対応していて exit; のような引数なしの呼び出しをうまく扱えないバグがあったのですが、これはパッチを送って 0.03 で直してもらいました。

こういうごくニッチなところにも先人がいるのは、CPAN というか Perl のすごいところだなあと思います。

まとめ

というわけで、mixi の開発者テストのいままでの歩みをふりかえってみました。今年に入ってからは Buildbot の設定をいろいろ詰めているのですが、これはまだ固まりきっていないので、紹介はまた次の機会に。

Buildbot

mixi の開発者テストまわりの仕組みは、基本的に「テストのことを考えずにだらだらコードを書いても、後から挽回できるように」できています。できているというか、そうせざるをえなかった、というのが実際のところです。

そのため、ださいところや、無理矢理なところも多々ありますし、実行速度も結構遅かったりします。ただ「テスト書きたいのは山々なんだけど、既存 コードに手をいれるのはきつくて、次の機会をうかがっている」というありがちな状況からは一歩抜け出せました。「おれ、新しいフレームワーク (or ライブラリ or 言語) がきたら、次はテスト書くんだ」なんてのは、良くない類のフラグを立てているだけであると、個人的には思います。

引用元

更新:2010/03/02 06:25 カテゴリ: web開発  > 開発テスト ▲トップ

No.1569 PHPで快適なテスト駆動開発を-Stagehand_TestRunnerの特徴と使い方を知る

先日、今年の 1 月以来となる Stagehand_TestRunner の最新バージョン 2.7.0 のリリースを行いました。コマンドラインのテストランナーを提供するこのプロダクトは、テスト駆動開発 (TDD: Test Driven Development) をより快適にすることを目的としています。

今回は Stagehand_TestRunner の特徴と使い方をご紹介いたします。

Stagehand_TestRunner とは?

Stagehand_TestRunner とは、PHPUnitSimpleTest といった PHP のテスティングフレームワーク向けに書かれたテストの実行に特化した Piece Framework のプロダクトで、下記のような特徴があります。

  • 指定されたディレクトリに含まれるテストの実行
  • 指定されたファイルに含まれるテストの実行
  • 指定されたファイルの指定されたテストのみの実行 (PHPUnit のみ)
  • テスト結果の色付け
  • 指定された PHP スクリプトのテスト実行前のプリロード
  • 指定されたディレクトリの変更の監視および変更検出時のテストの実行
  • Growl へのテスト結果の通知
  • JUnit XML フォーマットによる、指定されたファイルへのテスト結果のロギング (PHPUnit および PHPT)
  • 詳細な進捗リポートの出力 (PHPUnit および PHPT)
  • PHPUnit, PHPT, SimpleTest, PHPSpec のサポート

これらの特徴は、TDD による PHP アプリケーションの開発を強力にサポートします。

Stagehand_TestRunner のインストール

Stagehand_TestRunnerPEAR パッケージ として提供されており、Piece FrameworkPEAR チャネルpear.piece-framework.com からインストールすることができます。

pear channel-discover pear.piece-framework.com
pear install piece
/stagehand_testrunner

今回のバージョンから、新たに多くのパッケージへの依存が追加されました。中には beta バージョンのパッケージも含まれているため、PEAR の構成 Preferred Package State (preferred_state) が stable になっている場合は、手作業でそれぞれの依存パッケージをインストールする必要があります。これが面倒な場合は、一時的に Preferred Package State (preferred_state) を beta に変更してからインストールを行ってください。

ちなみにこれらの依存パッケージの多くは、Stagehand_TestRunner から再利用可能なコードを分離することによって作成されたものです。これらのパッケージについては後日改めてご紹介いたします。

次に先述の特徴を実現するコマンドラインを解説します。

指定されたディレクトリに含まれるテストの実行

phpunitrunner DIRECTORY
phpunitrunner
-R DIRECTORY

指定されたディレクトリをスキャンし、テストを実行します。-R オプションを指定した場合、下位ディレクトリを再帰的にスキャンします。

runs-tests-in-the-specified-directory.png

指定されたファイルに含まれるテストの実行

phpunitrunner FILE

指定されたファイルに対してのみテストを実行します。

runs-tests-in-the-specified-file.png

指定されたファイルの指定されたテストのみの実行 (PHPUnit のみ)

phpunitrunner -m METHOD1,METHOD2,... FILE

指定されたファイルに含まれる指定されたテストメソッドを実行します。カンマによって複数のメソッドを指定することができます。

これまでバージョンでは、特定のテストのみを実行したい場合それ以外のテストをコメントアウトするといった泥臭い作業が必要でした。

runs-only-the-specified-tests-in-the-specified-file.png

テスト結果の色付け

phpunitrunner -c DIRECTORY_OR_FILE

結果の色付けによって、テストにパスしたかどうかがわかりやすくなります。

先述のスクリーンショットはすべて -c オプション付きで実行されたものです。

指定された PHP スクリプトのテスト実行前のプリロード

phpunitrunner -p FILE DIRECTORY_OR_FILE

include_path, オートローディング、エラーハンドリングなど、テストの実行のための準備を行うためのスクリプトを指定することができます。指定されたスクリプトは、テストランナー本体がロードされるよりも前に実行されます。

実際の例を見てみましょう。下記は、Piece Framework のプロダクト、Stagehand_AccessControl のスクリプトです。

tests/prepare.php
<?php
error_reporting
(E_ALL | E_STRICT);

set_include_path
(realpath(dirname(__FILE__) . '/../src') . PATH_SEPARATOR .
                 get_include_path
()
                 
);

require_once
'PHPUnit/Framework.php';
require_once
'Stagehand/Autoload.php';

$loader
= Stagehand_Autoload::legacyLoader();
$loader
->addNamespace('Stagehand');
Stagehand_Autoload
::register($loader);

Stagehand_LegacyError_PHPError
::enableConversion();

指定されたディレクトリの変更の監視および変更検出時のテストの実行

phpunitrunner -a DIRECTORY
phpunitrunner
-a -w DIRECTORY1,DIRECTORY2,... DIRECTORY

指定されたディレクトリについて、ファイルの追加および削除、更新日時の変更の監視を行います。変更が検出されると、直ちにテストが実行されます。

デフォルトの監視対象はテストディレクトリですが、-w オプションによって監視対象のディレクトリを追加することができます。これによって、テストコードだけでなくプロダクトコードや構成ファイルなども監視することができます。

実際のスキャンにかかった時間によって監視間隔が調整されます。下限は 5 秒です。

Growl へのテスト結果の通知

phpunitrunner -g DIRECTORY_OR_FILE
phpunitrunner
-g --growl-password=PASSWORD DIRECTORY_OR_FILE

Growl に対してテストの結果を通知します。パスワードが必要な場合、--growl-password オプションによってパスワードを指定することができます。

JUnit XML フォーマットによる、指定されたファイルへのテスト結果のロギング (PHPUnit および PHPT)

phpunitrunner --log-junit=FILE DIRECTORY_OR_FILE

指定されたファイルにテストの結果を JUnit XML フォーマットで書き込みます。

この機能は、筆者らが現在開発中のプロダクト MakeGood との連携用として追加されたものですが、継続的インテグレーション (CI: Continuous Integration) ツールとの連携にも役立つでしょう。

詳細な進捗リポートの出力 (PHPUnit および PHPT)

phpunitrunner -v DIRECTORY_OR_FILE

この機能によって、PHP の Fatal error などでテストの実行が途中で終了する場合に、問題を引き起こしているテストを簡単に特定することができます。

prints-detailed-progress-report.png

PHPUnit, PHPT, SimpleTest, PHPSpec のサポート

テスティングフレームワークと Stagehand_TestRunner コマンドとの対応関係は下記のとおりです。

  UNIX Windows
PHPUnit phpunitrunner phpunitrunner.bat
PHPT phptrunner phptrunner.bat
SimpleTest simpletestrunner simpletestrunner.bat
PHPSpec phpspecrunner phpspecrunner.bat

おわりに

Stagehand_TestRunner は TDD を最大限にサポートできるように設計されており、より便利なツールにするべく日々改良を続けています。また、Stagehand_TestRunner をバックエンドとする Eclipse ベースのテストランナー MakeGood のリリースも計画中です。

PHP で TDD を行っている方、これから行いたい方、PHPUnitSimpleTest を直接お使いの方も、この機会に是非お試しください。皆様のご意見、ご感想、パッチなどお待ちしております。

参考文献

引用元

更新:2009/10/06 09:10 カテゴリ: web開発  > 開発テスト ▲トップ
3件中 1 〜 3 表示  1 

FuelPHP

Mac

web開発

プロマネ

マネタイズ

プレゼン

webサービス運用

webサービス

Linux

サーバ管理

MySQL

ソース・開発

svn・git

PHP

HTML・CSS

JavaScript

ツール, ライブラリ

ビジネス

テンプレート

負荷・チューニング

Windows

メール

メール・手紙文例

CodeIgniter

オブジェクト指向

UI・フロントエンド

cloud

マークアップ・テキスト

Flash

デザイン

DBその他

Ruby

PostgreSQL

ユーティリティ・ソフト

Firefox

ハードウェア

Google

symfony

OpenPNE全般

OpenPNE2

Hack(賢コツ)

OpenPNE3

リンク

個人開発

その他

未確認

KVS

ubuntu

Android

負荷試験

オープンソース

社会

便利ツール

マネー

Twig

食品宅配

WEB設計

オーディオ

一般常識

アプリ開発

サイトマップ

うずら技術ブログ

たませんSNS

rss2.0