テスト自動化

手動テスト

アジャイルな開発者は自動テストの重要性を強調しています。 短いサイクルで、手動で回帰テストを行うことは不可能です。ですが、それは手動テストが全く不要という意味でしょうか。いいえ、いくつかの手動テストは推奨しますが、それは伝統的なスクリプトベースの手動テストとは異なります。

手動テストを自動化する

開発者はよく主張します。 “ネットワークコネクションが切れたようなテストを自動化するのは不可能だ”, “ハードウェア障害があったときのテストはできない”。我々の回答は多くは”いいえ、そうではありません” や “それは可能です”。

Exploratory Testing in an Agile Contextの著者、Elisabeth Hendrickson氏は次のように述べています。

あなたがスクリプトベースの手動テストを作成できているのであれば、それは自動化できると私は思います

手動テストの手順を完全に同じように自動化することは難しいかもしれません。例えば、コネクションをロストするテストケースで、ネットワークケーブルを自動で切断することはほぼ不可能かもしれません。そのような時は、自動テストでは別のアプローチで表現します。物理的にケーブルを外すのではなく、自動テストではケーブルが外れた時のレスポンスをするように制御します。

全てを自動化する価値はありますか?Hendricksonによれば、

スクリプトテストで作成し、実行するテストケースは自動化する価値が十分あるケースである

なぜでしょうか。イテレーティブでインクリメンタルな開発はイテレーションの最後にコード凍結はせず、イテレーション毎に変更がある可能性があることを意味します。なので、手動の回帰テストは毎イテレーションほとんどの手動テストをすることを意味します。自動テストはそのコストをすぐに回収します。

特に複数のフィーチャーチームでコードを共同所有している大規模な開発では、自動テストによるセーフティネットはとても重要です。テスト自動化の努力をする価値があります。

手動テストをする

全てのテストを自動化することは価値がないかもしれないし、不可能かもしれない。
これらのテストは手動でやる必要があります。

  • 人の意見と創造性を必要とするテスト – インターフェースが良いかどうかを判断するには人が必要です – ユーザビリティテスト。探索的テストでは、探索する次のステップを決めていく人が必要です。

  • 物理的な動きが必要なテスト – 例えば、物理的構成があるシステムテスト。これらはシミュレーションで自動化することはできます。ですが、最終的なテストでは、実際の構成が必要になることがあります。

  • 高価なテスト – 本番環境の処理能力で実行するテストは高価な可能性があります。なので、1度か2度しか実行されません。これはリスクを遅延させます。このリスクはより安価なテストで早期に実行すべきです。 – 例えば、シミュレートした環境で処理能力のテストをします。 – これにより、高価なテストは単なる最終的なチェックになります。

探索的テスト

Perfect Software and Other Illusions about Testingでは、Gerald Weinbergが、「完璧なテストは迷信です。全てのテストが可能ですか?」と言います。それはできません。可能なテストシナリオの数は無限です、それゆえ全てのテストを自動化することは無限の努力を意味します。代わりに、予想される全ての自動テストと予期しないケースを見つけるための手動探索的テストにできる限り効率的に時間を使います。
探索的テストの概要

et.png
探索的テスト

探索的テストとはなんでしょうか。”学習、テスト設計、テスト実行” [Bach03] 。これはテストケースの設計と実行が分かれていて、設計を最初にしてから実行するという逐次的なステップの伝統的なスクリプトベースのテストとは対照的です。 探索的テストの狙いは人のテスト実行中の創造性を最大限活用することです。無意識にスクリプトに沿うよりもフィードバックと観察を使用します。テスターはシステムを探索し、学習し、テスト設計のための情報として活用します。これが良い具体例です。

Gitaが2Dモデリングアプリケーションをテストしていると想像してみてください。はじめに彼女はテストセッションのゴールを定義します。探索的テストではこれをミッション、またはチャーターと呼びます。彼女のチャーターは”コントロールポイントをドラッグで形を変更することを探索する”です。
彼女は形を取り、それをキャンバスにドロップし、その上にいくつかのコントロールポイントを作成します。彼女はそれらの1つをドラッグして、何が起こるかを観察します。この観察(学習)に基づいて、彼女は次のステップ(設計)を決定し、それを実行します(実行)。形状は新しい形になりますが、コントロールポイントをドラッグしているときに、形状が一時的に本来あるべきではない形になっていることに気づきます。したがって、彼女は偶発的な変形を再現できるまで、それをドラッグして動かし続けます。
この例では、詳細な先入観のあるスクリプトやテストケースはありません。その代わりにチャーター、対象を絞っています。最初のステップはシステムを観察し、その観察から次のアクションを決定します。これがテスト設計です。伝統的なテストテクニックや経験をこの設計ステップでは適応します。

et.png
探索的テスト

自動テスト

メンテナンスがしやすいテストを作る

“自動テストはテストのメンテナンス負荷を増やす”はよく耳にする反対意見です。テストのメンテナンスには労力がかかりますが、いくつか簡単なテクニックでそのコストを最小限にすることができます。

  • テスト間の重複を取り除く
  • テストを削除する
  • UIを介してのテストをしない
  • テストを頻繁に実行する

テスト間の重複を取り除く

コードの重複は複雑性、曖昧さ、欠陥による追加のメンテナンスを起こします。これは実装コードと同様にテストコードにも当てはまります。重複の取り除くことでこれを回避します。

テストのワークフローはよく重複を起こします。1つの親シナリオと、少しの違いの複数のバリエーションケースで構成するためです。1つのステップが変更されると、これらのすべてのテストのワークフローを変更する必要があります。この重複はビジネスルールに集中したデータドリブンテストや、重複をテストライブラリやフィクスチャで分離することで回避します。

私たちはよくある間違いをしたチームを指導しました。彼らは自動テストをイテレーションの最後まで遅延させます。残りの4日間は全て自動テスト作業が残っています。これらのタスクはテストスペシャリストによって実施されていましたが、今ではチーム全体でそれを実施します。

彼らは1日のワークショップをしました、1人のスペシャリストがチーム全体にコーチします。その後、2つのペアと1つのモブに分かれて、自動テストを並行に進めます。面白いこと起きました、プログラミングに経験豊富なチームメンバがテストの重複で追加のコストがかかることに不満を感じました。以前は、誰もそれ気づかず、テストスペシャリストがプログラミングの経験は薄く、気にしていませんでした。今では、皆が関わるため、テストの質が大幅に改善しました。

価値がないテストを削除する

テストは複数の目的を提供します。仕様として役に立ち、検証ができて、システムのリグレッションを防ぐセーフティネットとして機能します。

自動テストが不要になる時は、他のテストのサブセットになった時にがあります。不要なテストを保持していても、利益はありません。さらに、メンテナンスのコストとテスト実行スピードを低下させます。

UIを介してのテストを回避する

ユーザインターフェース(UI)は頻繁に変更される傾向があります。UIを介してのテスト実行はテストのロジックに変更がなくても、これらの変更に対して弱くさせます。これはメンテナンスコストを増やします。

なので、UIを介したテストではなく、替わりにアプリケーションのロジックをAPIを通して直接実行します。このアプローチのもう1つの良いところは、UIの遅いテストから、テストの実行を高速化します。

テストを頻繁に実行する

昔、私達は大きなグループとウォーターフォールスタイルで仕事をしました。伝統的なテスト自動化のアドバイスは、最も重要なケースだけを選択し、専任の自動テストチームがリリースの後にすることでした。まずそれをやりました、そして次のリリース後にテストを実行しました…すると全てのテストが失敗しました。それを修正するの多くの時間を使うので、彼らは全てを手動でテストすることを決めました。

リリース毎に1,2度のテストを実行することはCPU利用を小さくすることには効果的に見えます。ですが、多くの変更があり、多くのテストが失敗し、大きな単位のメンテナンス作業が必要です。その代わりに、CIシステムを利用してテストに頻繁に実行し、多くのCPU利用がありますが、テストを修正するための作業が単純で小さいため、メンテナンス作業が少なくなります。もし高コストのテストメンテナンスがあるのであれば、十分に頻繁なテスト実行していない可能性があります。

非機能を機能と同じように扱う

非機能のテストを自動化し、継続的に実行することは効果的です。
最後までそれを遅延させることは、大きなリスクを最も痛みがある場所に移動させることになります。例えば、システムがあるパフォーマンスレベルが必要な場合、早期にテストをして、早期に目標を達成します。そして新しい機能を追加する時に継続的に実行して、システムがパフォーマンスの目標を下回っていないか確認していきます。

非機能はよく特別に扱われます。それらは具体化できず、テストもできないを思っているためです。
それは残念です。要求ワークショップの中で、非機能も機能と同じように見なし、それを明確にするために具体例を用いたテストを作成します。

ロングランテストを継続的に実行する

非機能のテストは通常のCIシステムのサイクルで実行ができないことがよくあります。
それらは実行時間が長い可能性があるためです。安定性のテストは数週間かかるかもしれません。
あるチームではそれらをリリースの近くまで遅延させ、フィードバックサイクルを遅らせました。
それは良いアイデアではありません。

ロングランテストを遅いサイクルでCIシステムで常に実行します。
テストと同じように扱います。それらが失敗した際には、コードをチェッキンした全ての人に通知してください。それがパスしたら、最新のビルトでテストをすぐに再実行します。このような方法で、フィードバックサイクルを出来る限り短くします。

仮想化・コンテナ化を使用する

テストを高速化するために、ハードウェアへの投資を抑えるために、VirtualBoxVMWareなどの仮想マシンを使用してください。別の仮想マシンとして、DockerなどのLinux仮想コンテナもあります。

市販のテストツールの使用を避ける

私達は一度、商用の”自動テスト”を行うGUIツールを開発している会社をコーチしました。
彼らの自動テストツールを開発のテスト自動化を支援するコーチングの依頼でした。

多くの商用テストツールがあります。私達は、それらに満足している人にほとんど会ったことがありません。多くは非常に複雑で、堅牢なテスト自動化よりもレポーティングや’管理’に重点を置いています。商用のツールよりも、開発者が本当の問題を解決したフリーのオープンソースツールを優先します

テスト自動化ツールの例:

もっと多くあります。上記は一般的なツールです。