BT

最新技術を追い求めるデベロッパのための情報コミュニティ

寄稿

Topics

地域を選ぶ

InfoQ ホームページ アーティクル 反復的で自動化された、継続的なパフォーマンステスト

反復的で自動化された、継続的なパフォーマンステスト

我々の産業は、中間結果を生成し、機能要件を (そのつど) 再考すれば、ひどいシステム開発の遅れを回避できるということを学んできました。また我々は、単体テストと機能テストを定期的に実行していれば、バグのより少ないシステムを構築できるということも学んできました。しかし、アプリケーションのパフォーマンスを考えたとき、我々はアプリケーションが完成に近づくまでは、パフォーマンスのテストを滅多に行いません。我々が機能テストで行ってきた、反復、自動化、継続という教えをパフォーマンスについても同様に適用できるでしょうか?

今日我々は、単体テストの完了を伴うビルドは時間ごと、日ごと、もしくは週ごとに行われるべきか、議論を戦わせています。100%のカバレッジと50%のカバレッジのどちらを目指すべきかについても議論していることでしょう。そのプロセスの詳細についても論戦し、話し合い、熟考していることでしょう。しかし、単体テストを伴う自動ビルドを実行する事はベストプラクティスである、と言う点についてはほとんど全ての人が賛同します。しかしパフォーマンスのテストに関しては、限られた議論しかされていないか、全く行われていません。

時期尚早か、ちょうどよい時期か

なぜパフォーマンステストが、最後の時期まで延期されるのかにはいくつかの理由があります。こうした理由の多くは、アプリケーションのテスト自動化を我々がほとんど、もしくは全く行わない理由と非常に似ています。自動ビルドのセットアップを行うのは、時間と努力、献身を必要とします。こうした献身こそが最も重要な関心事である事を、ビジネス上正当化するのは、単に難しいです。結局我々はプログラマなので、次から次へと機能を追加し、テストに時間を割かないようにすることが望まれているのです。単体テストを書くのは時間がかかりますし、機能などを開発する方が良い時間の使い方です。

しかし我々が既に行っているように、単体テストにテストコードを用いる、と言うやり方を形式化することによって、単体テストを我々は開発プロセスにコッソリ忍び込ませることができました。これにより、こうした形式化は大きな投資増を必要とすることなく受け入れられました。一度ビジネスがその価値を見出し始めると、物事はどんどんいい方向に向かいました。こうした経験をパフォーマンスのテストにも拡張できる、と信じられていたのは自然な流れでしたが、単純にそうはいきませんでした。パフォーマンステストのサポートに必要とされる投資はより大きく、その潜在的な利益は非常に小さいように見えるのです。結局のところ、開発中のシステムではテストの対象となるものが存在しないので、パフォーマンステストを行うことができません; 結局のところ、パフォーマンスとは単により多くの、もしくはより良いハードウェアを入れればよいという問題なのではないでしょうか?

なぜパフォーマンステストはより多くの投資を必要とするように見えるのかは、いくつかの理由があります。単体テストと違って、パフォーマンステストは開発者がこれまで行ってきたような物ではありません。このことにより、すでに行われている何かを形式化すると言うよりも、新しい活動として捉えられてしまうのです。しかし、現在我々が行っている単体テストは、単体テストが形式化される以前に行っていた、非形式的なテストよりもはるかに多くのことを行っています。こうしたことから、形式化されたパフォーマンステストを開発サイクルに組み込むために必要な投資には、認識と実際の間に隔たりが存在すると言えます。

早期のパフォーマンステストに対しては、別の意見もあります; それは時期尚早で、テストするものはなにも存在せず、得るものは非常に少なく、あまりに細かすぎるパフォーマンスチューニングであり、パフォーマンステストの完了したシステムにとってのみ有用なくらい細かすぎ、パフォーマンステストのセットアップは複雑すぎて時間がかかりすぎ、そのプロセスは変わりやすい、などなど。こうした様々な理由は的外れではありません。どんなパフォーマンステストグループのマネージャーに聞いても、最も時間を必要とするのはテスト環境でアプリケーションの操作を行うことだ、と答えるでしょう。この作業は非常に骨が折れ、彼らがテストできるアプリケーションの数が実際に制限されるほどです。彼らが実際にパフォーマンステストを行えているのは、デプロイされているアプリケーション全体の50%以下だ、とこっそり教えてくれた人もいます。

時期尚早すぎる最適化は常に避けるべきである、と言うことに疑問の余地はありません。そうした最適化作業は複雑であり、実装と対応に要する時間が、どんなリターンを生み出すかはわからない、と言うのは特に正しいです。たとえばリストをソートするときに、単純なバブルソートが非常に良く用いられるというのは、それが本当に必要とされているすべてだからです。私たちは、ソート時間がクリティカルで、データ量が保障されているときにのみ、さらに複雑なソートを必要とするのです。これらの要求がどちらも満たされていないうちに、より複雑なソート戦略を実装するのは、時期尚早な最適化だと言えるでしょう。

テスティング コンポーネント

継続的なパフォーマンステストでは、私たちはシステムを構成するより細かい粒度に注目する必要があります。コンポーネントとフレームワークです。単体テストの場合では、クラスを別々にテストして、問題のあるクラスを特定することだけを期待する、と言うことが可能でした。パフォーマンステストの場合は、フレームワークを誤って使用することによるコンポーネント間の競合が、結果として期待するレスポンスタイムをオーバーするという点にあります。こうした事柄は、完全な統合テストによってのみ導き出されます。しかし、どれだけのCPU、メモリ、ディスク、そしてネットワークI/Oを必要としているのかを理解することは、我々がパフォーマンスを予測し、遅延を予防するアクションを採るための役に立ちます (時期尚早な最適化を行うよりも)。

コストに関する疑問に関しては、恐らくその通りです; パフォーマンステストは、開発コストを増加させるでしょう。機能テストと異なり、パフォーマンステストは開発者が普段からチェックするというたぐいのものではなく、機能テストには存在したような、形式化への明確なパスと言うものが存在しません。しかし、そこには二種類のタイプのコストが考えられます。努力に対する直接のコストと、最終ビルドでランダムに発生するパフォーマンス上の問題を全て修正するという隠れたコストです。すぐに経済的な効果 (金と時間/スケジュールのどちらに対しても) が現れるのは、パフォーマンステストをプロジェクトの開発サイクルの最後にしか行わないというものです。しかし、この経済効果は偽物です。これは、テストを減らせばアプリケーションを開発する人月を減らせる、と言っているのと同じことです。ここにはリスクに対する言及がありません。もしあなたが自動車保険に入っていない状態で、ポケットにいっぱいお金を入れて運転していたとしても、事故に会えば失われてしまいます。この業界で我々は多くの"自動車事故"を目にしてきました。テストをしない、と言うのは保険に入らず運転をするようなものです。

パフォーマンスのためのモック

しかし、コストを減らす手助けになる物はあります。開発者は単体テストに必要とされるモックなどを作るものです。そうしたモックはパフォーマンステストに必要とされるものをほとんど含んでいないでしょうが、多くの場合、それらは簡単に手直しすることができます。クレジットカードサービスのために作られた以下のようなモックを見てみましょう。

public class MockCreditAuthorizationServiceProvider
implements CreditAuthorizationServiceProvider {

private double rejectPercentage;
private Random random;
public MockCreditAuthorizationServiceProvider() {
// set the rejectPercentage from a property
random = new Random();
}

public void authorize(AuthorizationRequest request) {
if ( random.nextDouble() > rejectPercentage)
request.authorize();
else
request.deny();
}
}

リスト1. 認証失敗のシミュレーションを含むクレジットカード認証のモックsimulation

このモックは機能テストのために準備したものです。これは機能要求と密接に関連し、いくつかの調節可能な比率に応じてトランザクションを検証します。このモックは、クレジットカードの認証に成功、もしくは失敗するという処理のための機能要求をテストするには十分です。しかしパフォーマンステストのためには、我々が認証サービスに対して抱いている、サービスレベルの取り決めも必要とします。このモックは認証のためだけであってはいけません; 実行と認証のために通常要する時間とともに行われるべきなのです。もしシステムが、同時に5つまでの認証リクエストしか想定していないとすると、これはモックの中に記述される必要があります。こうした要件は、リスト2のように、オリジナルのモックに追加されました。

public class MockCreditAuthorizationServiceProvider
implements CreditAuthorizationServiceProvider {

private double rejectPercentage;
private Random random;
private Expondential serviceDistribution;

public MockCreditAuthorizationServiceProvider() {
// set the rejectPercentage meanServideTime from a property
random = new Random();
this.serviceDistribution = new Expondential( meanServiceTime);
}

public void authorize(AuthorizationRequest request) {
try {
Thread.sleep( this.serviceDistribution.nextLong());
} catch (InterruptedException e) {}


if ( random.nextDouble() > rejectPercentage)
request.authorize();
else
request.deny();
}

リスト2. 認証失敗とサービス実行時間のシミュレーションを含む、クレジットカード認証のモック

こうしてつけ加えられた、それほど些細ではないチャレンジは、適切なテスト環境内でアプリケーションが動作する、と言う結果を得られるのみです。しかし、これは機能テストを行うという点ではまだ問題を抱えていますが、一つのソリューションではあります - 継続して行えるのです。パフォーマンステストを行いたいがための、こうした見え見えのソリューションは、(先に述べたような、多大な) 努力を必要としていません。

ツール

我々が初めにJUnitを手にした時、この整った小さなツールは、我々がテストを組織化し、それらを実行して結果を見るための役に立ってくれました。我々にはANTもあります - Makeの複雑さに怒って書かれたツールです。これらの始まりはつつましいものでしたが、継続ビルドとユニットテストをサポートするツールの爆発的な増加を、我々は今目にしています。しかし、継続的なパフォーマンステストをサポートした物はほとんど目にしません。しかし、パフォーマンステストをサポートしている、と喧伝している既存のツールがないのは確かですが、実は存在します。こうした宣伝不足が示唆するところは、そのサポートが限定的だということです。

最初の制限は、サポートされるテストのタイプです。現在我々にはANT(サイト・英語)とMaven(サイト・英語)、CruiseControl(サイト・英語)があります。これらの美徳はANTとの統合ではありますが、これらは全てApache JMeterの自動的な実行をサポートしています。Apache JMeter(サイト・英語)は、HTTPサーバとアプリケーションのパフォーマンステストに対するニーズから登場しました。他のタイプのテストもサポートしていますが、それはJMS、WS、JDBCを含む、いくつかのよく知られたコンポーネントに限定されています。しかし、Apache JMeterは非常に拡張性が高く、もしわれわれがコンポーネントのテストをするなら、私たちがすべきことはまさに、Apache JMeterを拡張することです。ですが、多くの場合ではそれは理想的なソリューションではありません。他の選択肢は、自分でストレステストの仕組みを作ることしかありません。これも、望ましいソリューションではありません。ツールのサポートが貧弱な間は、継続テストをサポートするツールが時間とともに向上していったように、ツールが改善されていくことを望むしかありません。

Case in Point

ツールのサポートが欠如していることが、継続的なパフォーマンステストの妨げになっているのでしょうか?この答えは、あなたの所属する組織が、どれほど冒険心を持っているかに依存するでしょう。(訳注:つまり、そうしたツールを自分で作る、というリスクを抱えるため) しかし、それを自らが作るという考えを捨て去る前に、このことを考えて見て下さい。継続パフォーマンス (テスト) のプログラムを設けている組織は少ししかありませんが、その解毒的な作用は実証済みで、その結果は確実なものです。あるケースでは、6つの異なる開発チームが協調して最終成果物を作り上げました。パフォーマンスチューニングチームは、開発プロセス中に個々のチームがパフォーマンステストをすることを頼んでいました。もっともパフォーマンスに困難を抱えたコンポーネントは、そのリクエストに従わなかったチームから生成されました。

まとめ

Dave Thomasは「割れ窓理論」(source)について書いています。継続ビルドや単体テストが「割れた窓」を修復したように、継続パフォーマンステストも「パフォーマンスの割れ窓」を修復するでしょう。

Kent Beckは、自動的なビルドによる継続テストを、車の運転と言うたとえを用いて説明しました。あなたが道路を移動しているとき、道路の中央か、自分の車線に留まっているためにはどんな微調整が必要かを、あなたの目は教えてくれます。目をつぶって運転し、カーブを見過ごしたり車線を外れたりしそうになったときだけ一瞬目をあける、なんてことは考えないでしょう。あなたが、(継続したビルドやテストは) 困難だと最初は思えたとしても、時間がたつにつれてそれは簡単になってきます。彼らが言っているのは、反復的で自動化された、継続的なテストやビルドを行うことは、目をしっかり開けて開発を行うことである、と言うことです。

原文はこちらです:http://www.infoq.com/articles/iterative-continuous
このArticleは2007年11月16日に原文が掲載されました)

この記事に星をつける

おすすめ度
スタイル

BT