2018-02-04

3分で自動テストの全体像がわかるようにまとめてみた

品質保証チームにもうすぐ半年いることになります。ここ最近、自動テストの重要性が叫ばれています。しかし、実際の現場にいると、なんでも自動テストしようとするのは誤りであるという声を多く聞きます。また、過度な自動テストに対する期待を聞くことも多くあります。


今回は、自分の仕事の実体験を含めて、自動テストの全体像がわかるようにまとめてみたいと思います(新卒の知識なのでそこまであてにしないでください。)


システムテスト自動化 標準ガイド CodeZine BOOKS
翔泳社 (2014-12-17)
売り上げランキング: 17,628


自動テストを導入するとどんないいことがあるのでしょうか、また、どんな問題があるのでしょう。今回は、システムテスト自動化標準ガイドという本を参考に、まとめてみたいと思います。




1. 自動テストとは何じゃらほい



自動テストには、様々な種類があります。それは以前に紹介した、初めての自動テストにもある通り、大きく分けて以下の3種類があります。


  1. 単体テスト:プログラマーのデバック向けのテスト
  2. 統合テスト:単体テストで通ったモジュール(部品)を組み合わせて行うテスト
  3. UIテスト:実際に利用するシステムのユーザーフローに沿ったテスト



2. 開発者向けのテストと、品質保証向けのテスト



開発者の中でよく行われるのは、単体テスト統合テストですね。こちらは、プログラム自体のテストになり、その入力と出力の処理結果が可視化されるので、ホワイトボックステストと呼ばれています。実際にユーザーが触れるUIではなく、システムの中身だけでテストを行います。


これらのテストは、コードの修正時に不具合を発見し、より早く開発を進めるために書くことが多く、自動化されやすいです。rubyでいうRSpecのソースコードを読んてみると、なんとなくどんなことをしているのかイメージがつくと思います。RSpec テストコード書き方 サンプル _φ(・・*)

require 'rails_helper'

RSpec.describe Admins::TasksController, :type => :controller do
  describe "GET #index" do
    login_admin
    before(:each){ create_list(:task, 3)}

    context "デフォルト(条件指定のパラメータがない場合)" do
      before(:each){ get :index }

      it "解決済み(done: true)は返さない" do
        create(:task, done: true)
        expect(assigns(:admins_tasks).pluck(:done))
          .to_not match_array([true])
      end

      it "返される数は、20件以下のlimitがかかっていること" do
        create_list(:task, 21)
        expect(assigns(:admins_tasks).count(true) <= 20).to eq true
      end
    end

    it "params[:note_id]で指定があれば、それを返すこと" do
      note = create(:note)
      task = create(:task, note_id: note.id)
      get :index, note_id: note.seq
      expect(assigns(:admins_tasks).count).to eq 1
    end

    describe "params[:search]で検索条件があれば、それを返すこと" do
      it "コメント検索" do
        comment = "コメント"
        task = create(:task, comment: comment)
        get :index, search: {comment: comment}
        expect(assigns(:admins_tasks).last.comment).to eq comment
      end

      it "メモ検索" do
        memo = "メモ"
        task = create(:task, memo: memo)
        get :index, search: {memo: memo}
        expect(assigns(:admins_tasks).last.memo).to include memo
      end
    end

    it "renders ther :index template" do
      get :index
      expect(response).to render_template :index
    end
  end

  describe "POST #create" do
    context "with valid attributes" do
      it "saves the new record in the DB" do
        expect{
          xhr :post, :create, task: attributes_for(:task, note_id: note.id)
        }.to change(Task, :count).by(1)
      end

      it '@task_note_seq be valid' do
        xhr :post, :create, task: attributes_for(:task, note_id: note.id)
        expect(assigns(:task_note_seq)).to eq note.seq
      end
    end

    context "with invalid attributes" do
      it "does not save the new record in the DB" do
        expect{
          xhr :post, :create, task: attributes_for(:invalid_task, note_id: note.id)
        }.not_to change(Task, :count)
      end
    end
  end


  describe "PATCH #update" do
    login_admin
    let(:task) { create(:task) }

    context "valid attributes" do
      it "locates the requested" do
        xhr :patch, :update, id: task, task: attributes_for(:task)
        expect(assigns(:task)).to eq(task)
      end

      it "changes attributes :done" do
        xhr :patch, :update, id: task,
          task: attributes_for(:task, done: true)
        task.reload
        expect(task.done).to eq true
      end

      it "changes attributes :memo" do
        memo = "メモ"
        xhr :patch, :update, id: task,
          task: attributes_for(:task, memo: memo)
        task.reload
        expect(task.memo).to include memo
      end
    end

    context "with invalid attributes" do
      it "does not change" do
        xhr :patch, :update, id: task,
          task: attributes_for(:task, done: "test")
        task.reload
        expect(task.done).not_to eq "test"
      end
    end
  end
end


このテストは、実際にブラウザを操作せず、内部にユーザーのデータを作成し、DBにいれて・・・という操作を、UIを経由せずにプログラム上で実行し、それが正しい結果を取得できているか調査しています。UIとは完全に分離したテストなわけですね。



逆に、今回の本で説明されているのは、3のUIテスト(総合テスト・機能テスト)は、中のプログラムを直接見るわけではないので、ブラックボックステストと呼ばれています。



この本で扱っているのは、どちらかというとUIテスト・ブラックボックステストの自動化の部分になります。


2. UIのテストってどんなことするん?


このUIテストは、例えばECサイトで「買い物を行う」というユーザーの欲求をもとに説明すると、例えば以下のような行動を実際に品質保証チームがブラウザで操作し、要求を満たせているか確認するわけですね。


  • ブラウザを起動する
  • ログインする
  • 買い物一覧を検索する
  • 買い物一覧画面に飛ぶ
  • 詳細ページに飛ぶ
  • 購入ボタンを押す
  • 確認画面に飛ぶ
  • 決定を押す
  • 購入完了ページに移る


「え?そんなことしなくても、単体テストと結合テストやれば済むじゃん」と思われるかもしれませんが、例えば単体テストで商品の閲覧から購入までのテストが通っていたとしても、UIの部分のソースコードが間違っていたら、要求は満たせません(購入ボタンのリンク切れが起こっている可能性もありますし、javascriptが動作していないかもしれません)また、仮にテストが通ったとしても、ユーザーにとっては不便かもしれません(確認画面を押すのに、10秒待たないといけない設定になっていたら、それは品質保証が指摘すべきです)



3. 自動テストで自動化するのは、UIテストの中でどのようなテストか



このUIテストには、段階・目的によっていろいろなテストがあります。JSTQBによると以下のようなテストがあります。


  • 機能テスト(functional testing): コンポーネントやシステムの機能仕様の分析に基づいて実施するテスト。black box testing も参照のこと(JSTQB 用語集から
  • 確認テスト(confirmation testing): 修正が成功したかを検証するために、前回不合格に終わったテストケースを再実行するテスト。(JSTQB 用語集から
  • 回帰テスト(regression testing): 変更により、ソフトウェアの未変更部分に欠陥が新たに入り込ん だり、発現したりしないことを確認するため、変更実施後、すでにテスト済みのプログラムに対して実行するテスト。ソフトウェアや、実行環境が変わる度に実施する。(JSTQB 用語集から


普段仕事でテストしている感じだと、新規機能が開発されて、機能テストを最初に行い、その後バグを見つけて報告、その報告に基づいて機能が修正され、確認テストを行い、最終的には回帰テストを行うといった流れですね。


この最後の、回帰テストを自動化することが、品質保証でいう、いわゆる自動テストです。


4. 回帰テストを自動化するとどんないいことがあるのか


用は、まったくおんなじテストを何度も繰り返すのは、機械で自動化できるからです。そして、回帰テストを自動化するメリットはたくさんあります。


テストをもっと頻繁にたくさん行えるようになる


回帰テストを自動化すると、より早く、いつでもテストすることができるようになるので、ソフトウェアの未変更部分に欠陥が新たに入り込ん だり、発現したりしないことを確認する回数が増えます。そうすると、バグの検出がより早く行えるようになり、開発者へのフィードバックが早くなったり、品質の欠陥をより早く修正することができるようになります。

手動テスティングすべきテストに人を回せる


バグの検出率が一番高いのは、手動テスティングです。実際、一度行われたテストから、エラーが多く検出されることはありません(なぜならテストを最初に実行したときに一番エラーを検出することができ、あとはディグレを検出することしかできないからです)


回帰テストは、多くの時間を取られる割にはバグを見つけられることは少ないので、本来であれば手動テストでより多くのバグを検出する時間に、回帰テストで自動化した時間を充てることができるようになります。




また、同じテスト入力を繰り返し入れ続けるような、単調で退屈な仕事を自動化すると、はるかに正確になるだけでなく、作業者の士気も高まります。また、優れたテスト担当者を解放し、よりよいテストケースの設計に注力させられることができるようになります。


市場に早く提供できる 



いったんテストが自動化されると、手動よりもはるかに速く繰り返され、結果的にテスティングに必要な時間は短くなります。



より早く正確にテストできる 


人間だと、単調でつまらない回帰テストを行っていると、集中力がなくなり、テストを間違えたり、やり直したりする中でかなり時間がかかってしまいます。一方自動化すると、人間の100倍以上の速さでテストを行ってくれ、かつ正確に実行するので、より早く正確にテストをすることができます。






5. 回帰テストを自動化するときの問題点


で、ここからが本題。自動テストを作るときに注意したい点です。


過度な期待:全ては解決できない


ぶっちゃけた話、すべてを自動テスト化するのは誤りです。自動テストは、すでにテストした内容を自動化するだけなので、プログラムに機能を追加したり変更を加えたことによって、今まで普通に動いていた部分が動かなくなっていないかを確認することしかできません。



自動化すべき回帰テスト・すべきではない回帰テストとは


自動化すべき回帰テスト:修正が少ない部分のコンポーネントである


せっかく回帰テストを書いても、機能の修正が大幅で、自動テストコード自体が意味なくなってしまうことも多々あります。自動テストを行う機能が、今後修正が少ない部分であれば、なんどでも使えるので、自動化することを検討するとよいでしょう。逆に、すぐ修正が加わる部分は、自動テストには向いていません。


これは個人的にスクレイピングツールを作成しているときでも感じるのですが、少しHTMLのClassやIDが変わるだけで、自動化スクリプトは全滅します。


また、そういうテストを自動化してしまうと、後で自動テストをメンテナンスするコストが高まり、本来かけるべき新しいバグ検出ができなくなってしまいます。






システムテスト自動化 標準ガイド CodeZine BOOKS
翔泳社 (2014-12-17)
売り上げランキング: 17,628



就活に関するおすすめ記事


就活中には、なるべく採用担当以外のリアルの経験を聞くべき5つの理由

【今だったら絶対にやってた】就活弱者の僕が今になって思う、大学2-3年生の時にやっておくべき3つのこと

メガベンチャーへの就職をしてみたいなら、OBOGに聞いてみよう

エンジニア就職に関するおすすめ記事

新卒未経験でエンジニアになるには?大学生でエンジニア就職している人に知っておいてほしいこと

フリーランス・エンジニアとして独立するときによさそうなミッドワークス(Mid Works)についてまとめてみた


注目の投稿

 PythonのTweepyを利用して、Twitter APIを利用している。 その中で、ハマったポイントをメモしておく。 まず、Searchに関して。 Twitter検索は、クライアントアプリ側では、全期間の検索が可能になっている。 一方で、APIを利用する際は、過去1週間しか...