【SAPUI5】チュートリアルを見ながらTest Driven Developmentを体験する (3) OPA5

##OPA5テストの歩き方
OPA5テストは、ユーザの操作に関係する機能のテストで使用します。（以下、OPA5のことをOPAと呼びます）
今回は以下のチュートリアルを参照しながら、OPAテストの流れ、考え方について紹介します。
[Step 6: A First OPA Test](https://sapui5.hana.ondemand.com/#/topic/1b47457cbe4941ee926317d827517acb)
[Step 7: Changing the Table to a Growing Table](https://sapui5.hana.ondemand.com/#/topic/016e0d44f8ff47d2bdf4fdad9b7bf7cd)

「チュートリアルを見ながらTest Driven Developmentを体験する」シリーズの目次は[こちら](https://qiita.com/tami/items/5776597e19337f57fa34)

##OPAテストは「話すように書く」
OPAのテストケースはUser Journey、すなわちユーザが何を見て、どう操作するかを説明するように書きます。
以下はこれから実装するテストのコードですが、メソッド名に注目してください。
`iPressOnMoreData`: "MoreData"を押す
`theTableShouldHaveAllEntries`: テーブルにすべてのエントリが表示される
`iTeardownMyApp`: アプリを終了する
ユーザの操作とその結果の説明になっています。

```javascript
	opaTest("Should be able to load more items", function (Given, When, Then) {
		//Actions
		When.onTheWorklistPage.iPressOnMoreData();

		// Assertions
		Then.onTheWorklistPage.theTableShouldHaveAllEntries();

		// Cleanup
		Then.iTeardownMyApp();
```
opaTestファンクションには3つの引数が渡されています。引数はそれぞれ以下の意味を持っています。

- Given ：与えられた条件（前提）　例）アプリを開く
- When ：～という操作をしたら　　例）ボタンを押したら
- Then ：～という結果になる　　　例）メッセージが出る

これらはOPAテスト実行時に設定されるオブジェクトで、それぞれarrangements, actions, assertions（というメソッドの集合）を持ちます。これらメソッドもテストケース作成時に実装します。

- Arrangements：初期状態のステータスを定義する
- Actions：ユーザの操作のよって起きるイベントを定義する
- Assertions：実行結果が想定通りかのチェックを定義する

OPAテストはユーザの行動をイメージし、「話すように」テストケースを書くことから始まります。

##OPAテスト用の設定を確認
今回のテストで使うファイルは、test/integrationフォルダの配下に格納されています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276021/5915b1dc-ad0d-b7fb-48cf-aa378b3656aa.png)
OPAテストはopaTests.qunit.htmlから実行します。
各ファイル、およびオブジェクトの関係は以下のようになっています。
AllJourney.jsというファイルから、ページごとのテストが呼ばれるという構成です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276021/5fbac85f-d5dc-2e7a-8a47-133556af7741.png)
QUnitはjsファイル単位にテスト用jsを作成しましたが、OPAテストの場合はビューごとに作るのが基本です。各ビューに対応するテスト用js（例：Worklist.js）の中でPage Objectと呼ばれるオブジェクトを生成します。Page Objectの中にActions, Assertionsを記述します。Arrangementsは共通で使うことが多いので独立したファイルになっています。（Arrangementsのファイル名はStartjp.js）

Worklistを例に各ファイルのつながりを表すと以下のようになります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276021/5d7acf85-4a7d-83e5-3f99-e0c88bb49eb5.png)

##OPA5でTest Driven Development
流れは前回の[QUnit](https://qiita.com/tami/items/5c5c065381f06aa35b48)と大体同じです。
1. テストを書く
2. 機能を実装する
3. テストを実行する

###実装する機能
現状は全部のデータが一度に表示されます。
パフォーマンスを考慮し、一度にロードする件数を20件に制限します。さらに、"More"（日本語では"さらに表示"というボタンを押すと全データが表示されるようにします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276021/eae539e3-a9cb-5356-19c4-c0d7aab09909.png)

###1. テストを書く
OPAテストでは、XXJourney.jsとXX.jsの2つのファイルが必要です。
XXJourney.jsが「話すように書く」テストで、XX.jsにJourneyで使うactionsとassertionsを記載します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276021/5eca31a9-fe0e-e1ba-54ee-eed5686cafc2.png)

####webapp/test/integration/WorklistJourney.js
変更前は以下のようになっています。

```javascript
	opaTest("Should see the table with all posts", function (Given, When, Then) {
		// Arrangements
		Given.iStartMyApp();
		
		// Assertions：全レコードが表示された状態、かつタイトルに明細数が表示されている
		Then.onTheWorklistPage.theTableShouldHaveAllEntries().
			and.theTitleShouldDisplayTheTotalAmountOfItems();

		// Cleanup
		Then.iTeardownMyApp();
	});
```

初期状態が「全明細を表示」から「20件まで表示」に変わるので、それに伴ってテストの内容を変更します。

```javascript
	opaTest("Should see the table with all posts", function (Given, When, Then) {
		// Arrangements
		Given.iStartMyApp();
		
		// Assertions
		//1. 改ページがされること
		Then.onTheWorklistPage.theTableShouldHavePagination().
		//2. タイトルに明細数が表示されること
		and.theTitleShouldDisplayTheTotalAmountOfItems();
	
	}); 
	opaTest("Should be able to load more items", function (Given, When, Then){
		// Actions: Moreを押したら
		When.onTheWorklistPage.iPressOnMoreData();

		// Assertions: 全件表示されること
		Then.onTheWorklistPage.theTableShouldHaveAllEntries();

		// Cleanup
		Then.iTeardownMyApp();
	});
```

テストケースを2つに分割し、最初のテストは新しい初期状態、すなわちページ番号が表示されることを確認しています。2番目のテストケースではMoreを押して全明細が表示されることを確認します。

####webapp/test/integration/pages/Worklist.js
WorklistJourneyで使う新しいaction, assertionの処理を追加します。

#####Dependencyを追加
まず、dependencyにPressクラスを追加します。ボタンなどを押す操作で使うためです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276021/523a52c0-b6f5-335e-77ec-a5c5c8603c4c.png)

#####Actionを追加
actionsにリストの"More"ボタンを押す操作を記述します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276021/76fc825a-608f-8cf6-df32-9857c384f237.png)
**waitFor**によって指定したIDのビュー、テーブルが表示されるのを待ち、表示されたらボタンを押します。waitForを使わないと画面にUIエレメントが表示されるのを待たずにテストが進んでしまい、エラーになってしまいます。

waitForは以下の動きをします。

- 400 msごとに指定されたエレメントが表示されたかどうかチェックする
- 表示されればsuccessファンクション、または指定した操作が実行される
- 15秒待って表示されなければ失敗とみなし、errorMessageが表示される（15秒は初期値で、変更可能）

Pressについて、ここでは何を押すのか指定していませんが、UIコントロールによってデフォルトの動作が決まっているそうです。（変更したい場合は引数に対象のIDを渡す）
[リファレンス](https://sapui5.hana.ondemand.com/#/api/sap.ui.test.actions.Press)を見ると、
>Control Adapters will find the correct DOM Element

とあり、何らか押せるものがあればそれを押すのだと思われます。

#####Assertionを追加
リストが改ページされているか確認するassertionを追加します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276021/278aef5b-5d4e-8275-aa12-9e27caace8de.png)
さきほどと似た構成ですが、ここでは実行結果が想定結果と合っているかのチェックを行います。想定結果は**matchers**で定義します。Aggregation（リスト）の行数が20ある、という想定になっています。（テスト用のmock dataは23行なので、そのうち20行が表示されていれば正しい）
想定結果と実行結果が一致すればsuccessファンクションが実行されます。

####実行結果
この時点でOPAテストを実行してみると、エラーになります。waitForが働いているため、15秒くらい待ってから結果が出ると思います。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276021/4588bd61-5456-0606-5d1b-b80d287b0466.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276021/017fa624-a662-52c0-78b0-9f5a2c76324b.png)
明細が20行表示されない場合のエラーなので"The table does not have all items"というメッセージはちょっと違う気がするのですが、チュートリアルに従ってそのまま進みます。

###2. 機能を実装する
改ページの機能を実装しましょう。とても簡単で、Tableコントロールのgrouingに"true"を設定するだけです。
####webapp/view/Worklist.view.xml
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276021/0872b24e-b3a9-4a17-e0bc-943e2e978109.png)

実行すると以下のようになります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276021/125be2d8-84c9-f353-1afc-4f0f6bf077f7.png)
「さらに表示」を押すと全件が表示されます。

###3. テストを実行する
OPAテストを再実行すると、今回は正常終了しました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276021/1e947ff0-57bf-984a-a508-830453fbd744.png)

##まとめ
OPA5テストの進め方について、雰囲気をつかんでいただけたでしょうか？
画面でどんな操作を実行するかによってactions, assertionsの書き方が変わってきます。次回以降では、今回とは違った操作に対応するOPA5テストの書き方について紹介したいと思います。

##関連記事
[チュートリアルを見ながらTest Driven Developmentを体験する (2) QUnit](https://qiita.com/tami/items/5c5c065381f06aa35b48)
[チュートリアルを見ながらTest Driven Developmentを体験する (4) ナビゲーション](https://qiita.com/tami/items/c9d5e2d8cc34c07b5a74)