ユースケースとテスト設計

 前項(プロトタイプ作成および設計)でとりあえず動くプログラムを作成することができた。しかし、この状態でイテレーションを閉じることができるほど完成度が高いわけではない。そのため不足している機能の実装と、必要最低限のテストが何であるか、つまりユーザから見えるシステム一体なにかを洗い出す。

ユースケース


 ユーザから見えるシステムについてまとめる。ユーザ目線での機能について整理するため、ユースケース図でまとめることができると考えた。
 前項(プロトタイプ作成および設計のルーティングで示したとおり、そこにシステム全体の機能が明記されている。そのルーティング表からみるとユーザから見えるシステムは以下であると考えられる。

  1. アカウント作成機能
  2. 認証機能(ログインとログアウト)
  3. ひとり言機能(一人でチャットを使う、ToDo的な使い方)
  4. マイページの表示機能(ルーム一覧に飛んだり、ログアウトしたり、ユーザ名を表示する画面)

そのため上記の機能について整理する。以下にユーザから見えるシステムを整理したユースケース図を示す。(図が大きくなり最適な配置ではないが現状これ以上きれいな配置にコーディングすることが難しかったため、現状の最善として示す)

ユースケース図
ユースケース図

 利用者は2つに分けられる。初利用者と通常の利用者である。初利用者はアカウントを持っていないのでアカウント作成をする。アカウント作成は認証の特別なケース(プロトタイプでは送信された情報を登録し、登録後に送信された情報で認証する)であると捉えられるようにする。こうすることでアカウント登録と認証処理を共通化できる。
 通常の利用者は、アカウントを持っている。そのためログインを検証できる。ログインに成功した後は、マイページの表示、ログアウト、ルーム一覧からひとり言のルームを選択してToDo・ひとり言を作成することができる。

 上記で、ユースケース図によるユーザから見えるシステムについてはまとめることができたと思う。結果としては前項(プロトタイプ作成および設計)の画面遷移図と似た結果になった。両者とも必要なテストがなにか考えるヒントになるものなので上手く使い分けることを目指す。

テスト設計


 上記でユーザから見えるシステムについてまとめた。しかし、実際には異なる操作を意図せずにする場合がある。そのため以下の2パターンについてテストを考えた。

  1. 成功を期待する場合を少なくとも1通り
  2. 失敗を期待する場合を少なくとも1通り

 本来であれば、失敗のパターンは複数検討すべきである。なぜなら失敗のパターンを網羅的に調査することでセキュリティに関するリスクを軽減できるからだ。しかし、現在はプライベートネットワーク内で動作することを想定している。そのためセキュリティのリスクは少ない。ゆえに優先順位としてセキュリティのリスクを減らすことよりもその他の要素の作り込みを優先するべきであると考えた。

 それではなぜ失敗を期待する条件をテストするか?それは、正しく失敗しないと正しく成功したか?必ず成功するのかの判定が難しいからである。そのため少なくとも1つはなからず失敗するケースを検証しなければならないと考えた。

 そのため判定条件網羅的(または分岐網羅的)な観点でテスト項目を作成する。また、判定条件網羅的にテスト項目を作成するのはコードとしてテストを書く場合とする。手動のテストをで網羅するのは時間がかかるためすくなくともイテレーション1では実行しないことにする。

テストの切り分け

 RailsはMVCパターンで構成される。Vについてはテストできないわけではない。しかし、直接ブラウザで確認した方が今の規模では効率が良いので、テストを書くのはMCのみとする。

テストするべき点を考えるには、ユースケース図および画面遷移図で手動での確認内容、コントローラでルーティングのテスト、モデルでビジネスロジックとバリデーションのテストとして分けて考える。それぞれのテストについて示す。

1.ユースケース図および画面遷移図

 上記ユースケース図および前項の画面遷移図からユーザからの操作と期待する結果についてまとめる。以下に示す。

操作 期待する結果
アカウントを作成する アカウント作成に成功しマイページが表示される。
ログインする ログインに成功しマイページが表示される。
マイページを表示する 認証後にマイページ
(自分の情報、ルーム一覧とログアウトを選択する画面)を表示する。
ルーム一覧を表示する ルーム一覧に自分の名前(ToDo・ひとり言ルーム)のリンクが存在する。
ひとり言ルームを表示する ひとり言ルームを表示する
ひとり言を作成する テキストを入力し送信、サーバでレンダリングされた内容を受信し描画する。
ログアウトする ログアウト画面に遷移する。ブラウザバックすると再認証が要求される。

上記の項目は手動でブラウザから操作して検証する。本件の対象ブラウザはChromeとFirefoxである。しかしイテレーション1で両方のテストをするのは時間的に難しいため今回はFirefoxだけとして確認を行う。

2.コントローラのテスト(機能テスト)

 コントローラの挙動についてはルーティング表の機能を満たすようにテストをすることで達成できるはずだ。以下にルーティングを示す。
また、コントローラテストにおいての失敗するパターンは認証と新規登録に関するものとする。

Verb URI Pattern Controller#Action 動作
GET / auths#show 選択画面を表示
GET /auths/logout(.:format) auths#logout ログアウト画面を表示、
キャッシュを上書き
GET /auths/mypage(.:format) auths#mypage マイページを表示
GET /auths/new(.:format) auths#new ユーザの新規登録画面
GET /auths(.:format) auths#show 選択画面を表示
POST /auths(.:format) auths#create 入力情報を元にユーザを作成
GET /rooms(.:format) rooms#index ルーム一覧表示
GET /rooms/:id(.:format) rooms#show ルームの内容を表示

上記の動作が失敗するパターンについても、それぞれ少なくとも1通り選択しテストを行う。

また、特別な条件として一番最後の/rooms/:id(.:format)ではクッキーを使用している。そのためこの箇所についてはクッキーの内容も正しいか検証する。

3.モデルテスト

 モデルテストはデータとロジックに関する要素をテストする。また、action cableで用いるchannelやconnectionについても整理する。以下に示す。

  • モデルテスト
モデル名 検証内容
User ユーザ名は唯一である。
User ユーザ名はスペースなしの半角英数字のみとする。
User ユーザ名は空を許可しない。
User ユーザ名は1文字以上、16文字未満とする。
User パスワードはスペースなしの半角英数字のみとする。
User パスワードは空を許可しない。
User パスワードは1文字以上16文字未満とする。
Room ルーム名は唯一である。
Room ルーム名はスペースなしの半角英数字のみとする。
Room ルーム名は空を許可しない。
Room ルーム名は1文字以上、16文字未満とする。
UserRoom レコードに記録されたidのユーザが存在する。
UserRoom レコードに記録されたidのルームが存在する。
UserRoom 空のレコードを許可しない。
UserRoom ユーザとルームの組み合わせが唯一である。
Chat レコードに記録されたidのユーザが存在する。
Chat レコードに記録されたidのルームが存在する。
Chat レコードに記録されたidのチャットテキストが存在する。
Chat 空のレコードを許可しない。
ChatText 空のテキストは保存しない。(空白文字だけ、改行だけも禁止)

ユーザ名とパスワードが16文字未満とするのはログアウトに使う特別なユーザ名自体が16文字で構成されるからである。そのため16文字未満とすることで特別なユーザ名・パスワードの存在を忘れて実装ができる。

  • チャネルテスト・コネクションテスト
クラス名 検証内容
Connection 認証
Connection 上記より、認証失敗時はエラーを出す。
RoomChannel ブロードキャスト
RoomChannel データベースに登録
RoomChannel レンダリングは指定のテンプレートで描画されているか?

本来であれば購読されているか?ストリームがあるか?など検証が必要である。しかし、action cableは現在、一人で使用することを考えているため詳細に設定していない。そのためテスト内容としては不十分であるが、イテレーション1としては十分であると判断し簡略化を行った。

また、特別なケースとして最後に、レンダリング結果が想定通りになっているか確かめる。この項目は失敗している場合は単純にミスであるため修正を試みる。

テストフレームワーク

 本件のテストフレームワークは、rails標準のMinitestを使用する。理由は今回行うテストは単純なものばかりなので、RSpecのような多機能なフレームワークを導入する必要はないと考えた。そのため単純なテストフレームワークであり、標準のMinitestが妥当であると考えた。

上記までの設計でテストを作成し挙動が正しいか検証する。