2016/12/22 このエントリーをはてなブックマークに追加 はてなブックマーク - 気負わず普通にテストしよう

気負わず普通にテストしよう






これはシステムエンジニア Advent Calendar 2016の22日目の記事です。

色んなプロジェクトでのテスト体験や自分で学んだことをもとに、ポエムを書きます。




  • 普通にテストをこなそう
  • 面倒だと感じたら、テストの設計か作業プロセスに問題があるから見直そう
  • テストでは検証したいことを決めて、それに集中しよう
  • ソフトウェアテストについての知識はざっと知っておこう

本来はSIの現場で考えた場合、
UAT(受け入れテスト)やST(システムテスト)などにも言及すべきかもしれませんが、
あくまで僕個人という開発者目線なのでUT、ITが中心の内容になっています。



Javaを用いた金融系の業務システムをつくっているある日でした。
自分の作業がなんか思ったように進まないなぁということに気づきました。



「何に時間を使っているんだろう?」



なんとなく自分の作業時間を計測してみることにしました。




結果として、分かったのは、

「テストケースを考える時間」
「テストを実施する時間」
に自分がかなり多くを費やしていることでした。




どうしてこんなに時間がかかっているか、を考えると2点思いつきました。



1.プロジェクトでやろうとしているテストの目的をハッキリと理解できていない、
もしくはプロジェクトのテストの目的がハッキリとしていない
2.自分自身がテストに関する体系的な知識がない



このあたりを追いかけた結果を書いてみようというお話です。



UTはUnit Testです。単体テストと呼ばれたりします。
ITはIntegration Testの略です。結合テストと呼ばれたりします。

一般的なUT、ITという概念と現場のUTとかITとかいう概念は往々にして異なっています。


UTは、レガシーコード改善ガイドによると、
例えば1クラスのみのテストを指すのみであり、
クラスをまたがった処理をするなどする場合はそれはもうUTではないとのことです。なるほど、と。



レガシーコード改善ガイド



  • JUnitはUTのためのツールか?


もはや、UTの範疇を超えたテストをJUnitが担うように進歩しています。
例えば、分かりやすいもので言えばE2Eテストと呼ばれるもの(Selenium WebDriverなど)。
しかし、JUnitは大体UTという扱いをしているんじゃないでしょうか。
または、CIの一部とかですかね。



  • デベロッパーテスト

デベロッパーテストみたいなものを指してUTということもあります。
機能単体のテストをさしてUTと呼ぶこともあります
(1機能が、実は複数のクラスや機能を結合していたりすることもあります)。





ITといってもIT用の環境で検証するだけだったりもしますし、
ブラックボックス観点でのテストすることを指したりもします。



  • UT・ITの境界

UTとITというの境界というのはとても曖昧で、
現場によって後から意味づけされているというのがほとんどだと思うので、
現場に合わせたUT、ITを満たす検証を行うこと、
そしてUT、ITの定義を正しく定義するようメンテし続けることが重要だと思います。

ということで、今僕がココに居る現場のUT、ITってなんだろうから改めてスタートしました。


テストについて、色々考えるようになるうちに、
やはり基本に立ち返るのが重要だろうなと考えました。

ソフトウェアテストというものがあり、
これが世間一般で行われているシステム開発のテストの起源のような気がするし、読んでみようと。

読んだのは「知識ゼロから学ぶソフトウェアテスト」という本。
読んでみてから今までよく知らずにやろうとしていたことが適切に、
正確に書かれていて今まで読まなかったことを懺悔したい気分になりました。

今まで、自分の関わったプロジェクトにおいてやろうとしていたテストが
全てこの概念に集約されるようでした。




知識ゼロから学ぶソフトウェアテスト 【改訂版】




ウォーターフォール、もしくはイテレーションやインクリメンタルな開発みたいなものであっても、
割とエンタープライズ感のある硬めのシステムであればスクリプトテストが基本となるように思います。


それは顧客との品質担保とかテスト計画の提示とかそういった側面で有効であるとともに、
スクリプトテストが網羅性が高くスタンダードであるからです。


IEEE Standard for Software and System Test Documentation という標準規格があり、
それに基づいたテストを行うものです。


スクリプトテストは全体を網羅ししっかりと計画をすることには長けていますが、
硬直的であり変更に弱い弱点があります。


僕が思うにスクリプトテストだけでなく、
色々なテスト手法をミックスして穴を潰していくことが大事です。

スクリプトテスト一辺倒だとどうしても抜け漏れが出てしまうように思うのだけど、
スクリプトテストは計画を緻密にしたり顧客に納品するとかそういった関係で、
完遂すること自体が目的にすり替わってしまう事がある気がする。


現場のみんなも検証よりもテストの完遂がいつの間にかゴールになっている。こういうときが辛いですね。


これはスケジュールや顧客との同意の問題であって、スクリプトテスト自体が極端に良くないという話ではないです。
単純にプロジェクトを上手く回すことの難しさであると思います。



逆に、「どこまで顧客と同意をとっていてどこは遊べるか」を考えるの重要だと思います。

「ココを守ればココはラフでも良い」という共通認識をチームとして形成すれば
負担を軽減することが可能です。




irofさんの発表とかを見たりするうち、
テストが面倒なものと感じること、
または周囲がそう感じることがあることに自覚的になりました。

※どちらもJJUG CCCで発表されていた
「よくある業務開発の自動化事情」
「テスト自動化のまわりみち」です。
割と影響を受けました。というか心に引っかかったという感じです。



そして、それからずっと自分なりにその面倒臭さの原因を考えていましたが、
これは結構根深いんじゃないかと思います。


面倒臭さの原因は、ハッキリ言ってしまうとテスト設計の怠慢と言って良いような気がします。

なので、極論、面倒だと思ったら何かが欠けてテスト実施者に何かを押し付けてしまっている状況である、ということです。



具体的に考えると以下の観点があるかと思います。

  • 準備、実施、検証というプロセスの内容が曖昧であること(テストケースの問題)
  • 準備、実施に時間がかかること(テスト作業の問題)

だと思います。




テストを行うと言いつつ、
実際にはテストケースの洗い出しを探索的に行っているということが実は多いと思うのです。






例えば、以下のようなテストケースはよくあります。

例1)

  • 準備
    事前にAをしておく

  • 実施
    Bを実施

  • 検証
    正常に動作すること

「検証」、いわゆる期待値が曖昧である例です。
これは検証内容の確認というところからテスト実施者が入る必要があるため負担が上がりますし、検証すべき観点がぼやけます。

例2)

  • 準備
    事前にAをしておく

  • 実施
    Bの状態にする

  • 検証
    Cであること

「実施」が曖昧な例です。
Bの状態にするためにはシステム上どういったオペレーションをする必要があるのか、の調査やヒアリングから始めないといけません。

例3)

  • 準備
    事前にAをしておく
    事前にBをしておく
    事前にCをしておく
    事前にDをしておく
    事前にEをしておく
    事前にFをしておく

  • 実施
    Gを実施にする

  • 検証
    Hであること

「準備」に負荷が多い場合です。
これはインフラや環境構築プロセスに問題がある場合でテストの実施検証がぼやけてしまうパターンです。

僕の現場では感覚的には例3が一番多く、シナリオライクなオペレーションを大量に要するものでした。
次に例2のものが多く、システム仕様が多岐に渡り業務ドメインの理解が不足していること、情報が共有されていなことなどが問題でした。

こういった事が原因で「テストが面倒」になってしまうんだと思います。

本来は「検証」のみをやりたいのです。
検証自体は皆に安心や品質の担保的なものを与えてくれて嬉しいもののはずなんです。

いかに、「準備」「実施」の負荷を下げ「検証」要件を明確にするかが重要だと思います。


声高にテストをやろう!という人はいます。

これは啓蒙としては素晴らしいんだけど、
そんな声を大きくして言うべきことかというとそうじゃなくて
(結果的に声を大にして主張しないといけない状況になっているからそうなんでしょうけど)。

テストはやって当たり前だし
別に力む必要もないのだと思います。

ただつくったものに対して正しく動くかを検証するだけ。

ソレをプログラマーが行うのは普通でしか無いんです。だから「普通」にやれば良いんだと思います。


テストの本質は検査して証明すること。

こういうこと言うと、敬遠されるかもしれないけど、テストというのはただの証明であると思います。

追加したロジックを利用した時に
結果が正しくなることを証明する。
これがテストであり、検証であると思う。


例えば数学では定理や公式とかがあったりします。
XXはYYである、これは正しいか?という問題があった時、
ただ単に定理や公式を並べるだけではダメで、
それらを組み合わせて問題が解けることを示さないといけません。


証明では、XXがAがBした時YYである。(QED)とか書けば良いわけですが、
これがテストにあたるんではないかと思います。




これらを考えた後のアクションとして、
僕は

  • UTは何を検証したいのか?
  • ITは何を検証したいのか?

を考えてテストケースを書くようになりました。

そうすると、かなりプロジェクトのプロセスの流れに乗りやすくなったように思います。

ゴールが明確になったおかげでゴールを目指したテストケースを作れるようになったし、
テストケース作りで悩んだら相談もあまり的はずれなものにならなくなったように思います
(これは体感的なものでしか無いのですが)。

また、タスクの洗い出しなども色々と逆算して行うことが以前に増して出来るようになったと思います。


あと、テストの面倒臭さを無くすことにも集中しました。

具体的には高度な自動化とかを出来たわけでもなく
簡単なシェルの作成、作業手順の見直しと言った地味なものですが
かなりテストの検証の部分に集中できたと思います。




「何のためのテストか」「今どの場面か」を考えることです。
それが設計だと思います。


また、準備・実施をなるべく簡略化出来る仕組みを作り「検証」に集中することです。
そうするとテストが面倒ではなくなり、「普通に」テストをすることが出来るようになっていくはずです。





0 件のコメント:

コメントを投稿

GA