自動テスト、4つの罠と5つの教訓
■一般化した自動テスト
XP(eXtreme Programming)やTDD(Test Driven Development)の流行や、Ruby on Railsのようなフル・スタックのWebフレームワークが自動テスト・フレームワークを備えるようになった影響で、最近の開発者の間では自動テストという概念が普通になってきました。
以前は自動テストといった場合、開発者の間ではJUnitのようなテスティング・フレームワークを使った単体テストの自動化が中心でした。しかし、最近では機能テストの世界でもSeleniumをはじめとするオープン・ソースのツールが登場してきたことによって、画面ベースの機能テストも積極的に自動化していく動きが進んでいます。
僕がテストの研究を大学でしていた10年前では逆にJUnitは誕生したばかりで、自動テストといえば、商用の画面キャプチャー・ベースの機能テスト・ツール(以下、キャプチャー&リプレイ・ツール)が一般的でした。
ですので、ちょっと前までの開発の経験があるが、Java時代以降ではあまり実装に関わっていないような方、あるいはもっとそれ以前の方にとって、自動テストというと画面ベースのツールだったり、逆に純粋にバッチだったりすることが多いです。
このキャプチャー&リプレイ・ツールによる自動テストというのは、テストについて初心者であればあるほどインパクトが大きく、魅力的に見えるものです。そのために、陥る罠もたくさんあります。
今回は僕自身のプロジェクトの実体験をもって、このキャプチャー&リプレイ・ツールを使った場合に陥りがちな自動テストの罠についてお話したいと思います。
■小錦からの無茶な要求
2年前のことですが、弊社存亡の危機とまでいわれたとあるプロジェクトがありました。このプロジェクトをリカバリーするために凄腕PMをはじめ、老若男女部署会社国籍の区別なくあらゆるメンバーが隔てなく集められました。勇者たちは総勢550名。彼らの血と汗、そしてお客様の力強い忍耐力によって最終的には無事にサービス・インできました。
当時、社内の部門でちょっと暇そうに見えたのか、はたまた自動テスト・スペシャリストの腕を買われたのか(多分これは違うと思います)分かりませんが、このプロジェクトに僕も参加することになりました。
そして、ある凄腕PMが率いるテスト・チームにて、統合テストの自動化の任務に就くことになりました。この凄腕PMがすごく怖かったのですが、それもさることながら、さらに僕の上にはオーストラリアから来た自動テストの達人なる小錦のような巨漢の自動テスト・リーダーがいました。
まず、プロジェクトの現状を調査して、各テスト・フェーズでどのようなテストがされていて、どの部分が自動化されているかを調査したところ、
単体テストが自動化されていません
恐るべきことに、まったく単体テストの自動化などを考慮しないで作られていたアーキテクチャーだったため、単体テストを自動化するのが非常に難しく、単体テストの自動化がされていなかったのです。単体テストの自動化がされていないということは、単体テストのフル・リグレッションが非常に難しいことを意味し、デグレードが発生したり、統合テスト以降で単体レベルのバグが見つかったりします。
統合レベルの機能テストの自動化が本来効果を発揮するのは、単体テストが自動化されている場合です。単体テストが自動化されていないと、統合テストのテスト・スクリプトを作っている最中でそもそもテストが失敗してしまったり、自動テストの実行の際に、単体レベルのバグが原因で失敗してしまい、本来の統合レベルのデグレードが検出できなかったりと、統合テストの自動化の意義が薄れてしまいます。
しかし、そのテスト・チームのリーダーは言いました。
「単体テストが自動化されていないことは分かっている。システムの品質も悪いことは分かっている。しかし、自動化して欲しい」
■自動テスト、4つの罠
●罠1 単体テストの自動化をしていないプロジェクトほど、自動テストについてまったく分かっていないため、それ以降のテストを自動化して挽回しようとする。
さらに日本語が分からず、プロジェクトの状況もよく分かっていない(まあ、英語のレベルがしょぼくて伝えられていない僕も問題なのですが)小錦から、恐るべき発言が飛び出しました。
"In my experience, all test scenarios should be automated. And we can."
いや、その、無理だろう……。このお客様のシステムは日本に1つしかない業務で、業務自体も恐ろしく難しく、アプリケーションとツールとのマッチングも去ることながら、まず業務フローとテスト・ケース自体を理解することが非常に困難だったのです。このような状況ですべてのテスト・シナリオを自動化することなど、Kent Beckでも無理でしょう。しかも、恐るべきことに、この発言が出たときに自動テストを設計・実装するメンバーは僕ただ1人だったのです。総勢550人ものメンバーがいるというのに。
●罠2 対象システムの難しさを知っていない人間ほど、とんでも発言をする。たとえ、自動テストの経験が長く、ツールに造詣が深くても、とんでも発言をする場合がある。
とはいえ、このプロジェクトで仕事を断ったら首になるという雰囲気ですので、不可能でも可能にするしかありません。いつかのツールを検討し、まあ、実際選択肢はなかったのですが、使用することになったのが、Rational Functional Tester(以下RFT)というRationalのキャプチャー&リプレイ・ツールです。RFTの名誉のために言っておくと、僕はRFTをはじめ複数のキャプチャー&リプレイ・ツールを使ったことがありますが、ほかのツールと比べても遜色なく、スクリプト自体がJavaもしくはVisual Basic .NETで記述できるため、独自スクリプト言語が多いほかのテスト・ツールと比べてもスクリプトが作成しやすいです。
ただし、それでも本来、テスト・ツール(特にキャプチャー&リプレイ・ツール)には得手不得手と対象アプリケーションに対するフィット&ギャップがあり、機能テストのテスト自動化を実施する場合、最初からアプリケーション側も自動テスト・ツールを考慮してコーディング標準などを定める必要があります。特に最近のAjaxをはじめとするRIAについては、ツールによってサポート範囲が大きく異なるので注意する必要があります。
案の定、このアプリケーションもRFTを使うことなどまったく考慮されず作られておりましたので、アプリケーション上のボタンやリンクを正しく認識させるのに工夫が要りました。このようなアプリケーションと自動テスト・ツールのフィット&ギャップの調査はツール両立性検証と呼び、本来パイロットの開始前に実施しておくべきものです。
パイロットの初期段階であるサブ・システムの中でも正常フローで最も簡単なシナリオをようやく自動化し、デモを見せてみたところ、以下のようにリーダーから返ってきました。
「何だ、できるじゃないか。じゃあ、バンバン作り始めてくれ」
しかし、ここでサブ・システムのベテラン・アーキテクトから別途注文が来ました。
「画面ベースの比較では不十分なので、実行結果のテーブルの突合せをして欲しい」
比較するテーブル数とカラム数はとんでもなく多く(本当に正規化されているのか不明ですが、なぜか列が256行を超えているテーブルがたくさんありました)、とてもRFTからデータベースのGUIツールを呼んで比較できる量ではありません。
●罠3 現場から使用する自動テスト・ツールとアンマッチングな要望があがってくる可能性が高い。
状況をよく分かっていない小錦が
"Use data pool. You can do with data pool."
とか言ってきます。データ・プールとはRFTの機能の1つで、データ駆動型のテストを実現するものですが、ここでのテーブルの比較の要件にはアンマッチングです。これを説明するのも大変だったのですが、ベテラン・アーキテクトとつめて、ツールを自作し、組み込むことにしました。
ベテラン・アーキテクトから自動化の範囲をお聞きし、業務チームの方々、そして小錦と方針を決め、テスト自動化の範囲とスケジュールが決定しました。
とても僕1人では無理でした。さすが凄腕PMだけあって、すぐさま開発メンバーを調達してきました。Javaの開発経験のある協力会社さんの若手3名でした。
その若手3名、さらには厳しいスケジュールの中、業務チームで自動テストに興味を持って協力してくださる勇者の方々3名と一緒に自動テストのプロジェクトが始まったのですが……。
プロジェクト自体の雰囲気が非常にピリピリしていたこと、凄腕PMと小錦からのプレッシャー、実質ほとんど分煙されていないといってもよかったプロジェクト・ルームの劣悪な空調環境、疲労困憊して下宿の部屋の掃除もほとんどしていなかったことなど、悪条件が重なり、それまで少しずつ症状は出ていたのですが、ある朝「それ」はマックスに達しました。喘息です。急性喘息の発作が起こり、プロジェクト・ルームへ行けなくなってしまったのです。午後、症状が治まったら病院に行く予定だったのですが、一向に症状は治まらず、立ち上がって動くことさえできません。夜にはついに呼吸困難に陥り、救急車を呼んで緊急入院という最悪の事態となりました。
「IT業界の恐るべき実態:彼女いない暦=年齢(30歳) 喘息の発作で股引を履きながら壮絶なる孤独死!」などと、「SPA!」や「アエラ」で特集されてしまいそうな悲しいスペックです。こんなので死んだら間違いなく成仏できません。というか、こんな状態で死んだら笑いものです。……ですので、死にませんでした。
あと3分遅れていたらチアノーゼを起こして危なかったという状況だったのですが、1週間の入院と、その後の1週間の自宅療養の末にカムバックすると、「大丈夫でしたか?」の挨拶も早々に、テスト自動化に戻りました。
戻ってきて、若手3名と共にぶつかった最初の困難が、業務チームへの仕様確認です。自動テストがお客様に報告するWBSには見えない裏タスクだったことから、ただでさえ激務な業務チームの方々からはなかなか協力が得られず、テスト・スクリプトの前にテスト・ケースの理解と妥当性確認のために多くの時間がとられました。
●罠4 統合テスト以降の自動テストの成功にはトップとボトムの両方の協力が必要だが、プロジェクトの後半から始めるとその協力が得られない場合が多い。
僕はかなり人との交渉が苦手なたちだったので、これが手こずり、かといって若手3人に任せるわけにもいかずと、進捗は芳しくなくと、再び凄腕PMと小錦の逆鱗に触れてしまいました。しかし、そこはさすが凄腕PM。人のマネジメントが得意な協力会社さんリーダーを僕の補佐としてつけてくれました。やはり、その方は長年の経験もあって、コミュニケーションの経路の作り方が優れており、業務チームとの協力関係をスムーズにしてくれました。
協力会社さんリーダーの参加によってパイロットも回し終え、ようやく本開発において自動テスト・チームも流れに乗ってきました。うまい具合にスクリプトを作れるようになってきました。
しかし、それはなんとサービス・イン直前で、残念ながら成果が出るのがあまりに遅かったため、テスト自動化はそれ以上の拡大をせず、駄目開発者の烙印を押された僕はサービス・インとともにプロジェクトを離脱、テスト自動化は一部別のメンバーに引き継いで、細々と自動化したシナリオをリグレッションするにとどまりました。
ただしサービス・インの前日、非常に重要な業務でのリグレッションの際に、自動テストがデグレードを発見して大活躍したので、入院したまでの苦労は多少報われたのかなと思います。
■自動テスト成功の鍵は「人と組織」「プロセス」「業務知識」
長くなりましたが、これが僕の実体験に基づく自動テストの罠です。罠からは逆に教訓が得られます。
教訓は以下のとおりです。
- 教訓1 プロジェクトでテスト自動化を計画に入れている場合、自動化の検討はテストの全体計画の最初に含めましょう
- 教訓2 最もコストが低く、かつ効果の高いところから自動化しましょう。まず、単体テストの自動化から考えましょう
- 教訓3 テスト・ツールとのフィット&ギャップはツール両立性検証をするだけでなく、パイロット実施にも詳細に検討し、開発チームへフィード・バックしましょう。特にHTMLでのオブジェクト認識については早期に問題を明らかにし、開発チームに対応してもらいましょう
- 教訓4 自動テストの実現には業務チーム、基盤チーム、構成管理チーム、PMO、お客様とあらゆる利害関係者の協力が不可欠です。多数の利害関係者が関与することになる統合テスト以降のテストの自動化を検討する場合、できるだけ早い段階、できればアーキテクチャー設計の段階でチームを結成し、各チームとのコミュニケーション・パスを確立しておきましょう。コミュニケーション・パスの問題点はパイロット実施時に洗い出し解消しましょう
- 教訓5 業務の理解は必須です。事前学習でも限界があるような、あまりにも特殊な業務の場合、業務のキーパーソンが限られている可能性が高いので、技術的な問題よりもコミュニケーション・パスの確保に全力を注ぎましょう
以上、自動テストの成功はほとんどツール自体の能力とは関係なく、人と組織、プロセス、業務知識なのでした。あれ、RFTほとんど関係なかったですね。上記5つの教訓を抑えていれば、実はツール単体で見た場合、どのツールを使ってもほとんど変わりがなかったりします。
ツールの差異が出てくるのはRIAへの対応や他のツールとの統合だったりするわけですが、その部分では各社のツールには様々な差異がありますので、パイロットの前のツールの両立性検証のフェーズで検証することになります。他のRationalツールとの統合におけるRFTの優位点はまた別の機会にて。