TestrailとRedmineの連携・障害チケットPushする

# TestRailからRedmineの障害チケットをPushする
TestRail上で、テストFailとした際に、Redmine上に障害チケットを起票する。
以下のURLに、やり方記載されていますが、つまずいたところの備忘録。

https://docs.testrail.techmatrix.jp/testrail-integration/tools-redmine
http://docs.gurock.com/testrail-integration/defects-plugins-custom
http://docs.gurock.com/testrail-integration/defects-plugins-examples

TestRailはサーバー版を利用しており、Redmine側のAPIをTestRailから呼び出せる必要がある


# やりたいこと
Redmine上の障害チケットの管理項目をTestRailのpushダイアログから入力できるようにする。

障害チケットとPushダイアログ上の入力項目は平仄をとる。
（つまり、障害チケット上プルダウンの選択項目であれば、Pushダイアログ上のプルダウンで表示させ、しかも、選択される値も同じもとなるようにする）


原則として、以下のような手順
①TestRail上のプッシュダイアログ画面に、項目追加
②RedmineのAPIを用いて、プルダウンの内容を取得
③TestRailに入力されたテスト結果を取得し、プッシュダイアログに表示
④入力内容をRedmineに連携

なお、
>Original: <TestRail>/app/plugins/defects/Redmine.phpCopy 
>To: <TestRail>/custom/defects/Redmine_custom.php

とカスタム用のファイルを作成し、以降はRedmine_custom.phpを修正する。
※詳細は[公式](http://docs.gurock.com/testrail-integration/defects-plugins-examples)を参照

## ①TestRail上のプッシュダイアログ画面に項目追加
Redmine_custom_defect_pluginクラス(Redmine_custom.php内に記載)の、prepare_push 関数を修正する。例えば、ドロップダウンを追加する場合は、以下のような項目を追加する。

```php:Redmine_custom.php
'sprint' => array(
  'type' => 'dropdown',   // string(文字列), text(複数行)も利用可 
  'label' => '表示名',    // ダイアログ上の表示名
  'remember' => true,     // 前の入力値を記憶するかどうか(true)
  'required' => true,    // 必須項目か
  'size' => 'compact'    // 表示サイズ　1行表示(full)、ちいさめ(compact)
  'rows' => 2            // typeをtextにした場合の行数
),
```

なお、追加したい対象の項目に似たものを追加するのが楽。


## ②RedmineのAPIを用いて、プルダウンの内容を取得
プルダウンの表示内容をRedmineと同期しない場合はこちらのステップは不要。

Redmine_apiクラスに、関数(get_XXXX)を新規追加。

```php:Redmine_custom.php
public function get_priority()
{
    // Redmineから、「優先度」を取得
    $response = $this->_send_command('GET','enumerations/issue_priorities'); 
    return $response->issue_priorities;

}
```

TestRailには、_send_command 関数という、RedmineのAPIをキックする関数が準備されているのでそちらを利用する。
取得したい項目に応じて、[RedmineのAPI](http://www.redmine.org/projects/redmine/wiki/rest_api)を参照し、適切な引数を設定する。

なお、対象の項目が、Redmineの標準項目でない場合（障害チケットによく追加される「検出工程」や「対象機能」など）、カスタムフィールドのIDが必要になる。
IDと値は[カスタムフィールド取得用のAPI](https://www.redmine.org/projects/redmine/wiki/Rest_CustomFields)をブラウザ等で実行すれば確認できるので、実際の環境に合わせて確認する。

また、以下のようなメソッドを作成しておき、カスタムフィールドのIDごとに、値と表示内容が取得できる。※ただ、毎回APIキックするので、ダイアログ開くのが若干遅くなる。。。

```php:Redmine_custom.php
public function get_custom_field($custom_field_id)
{
    $response = $this->_send_command('GET', 'custom_fields'); // APIの呼び出し
    $result = array();

    // IDを検索
    foreach ($response->custom_fields as $custom_field)
    {
        if($custom_field->id == $custom_field_id){
            // 値を取得
            foreach($custom_field->possible_values as $custom_field_value)
            {
                $c = obj::create();
                $c->id = (string) $custom_field_value->value;
                $c->name = (string) $custom_field_value->label;
                $result[] = $c;
            }
        }
    }
    return $result;
}

```

## ③TestRailに入力されたテスト結果を取得し、プッシュダイアログに表示
prepare_field 関数を修正する。

Redmineから取得したプルダウンの場合。

```php:Redmine_custom.php
// 優先度を追加
case 'priority':
  $data['default'] = arr::get($prefs, 'priority'); //前回起票時と同じ値を初期値とする場合
  $data['options'] = $this->_to_id_name_lookup(
    $api->get_priority() // 前ステップで追加したgetメソッド
  );
  break;
```

プルダウンではなく、Stringやテキストの場合は以下のコードを追加。
追加する場所がプルダウンの場合と異なるので注意。

```php:Redmine_custom.php
// テキストを追加する
case 'precondition':
  $data['default'] = $this->_get_precondition_default(
    $context);
  break;

```
なお、上記の例は、TestRail上に「前提条件」というカラムを追加し、そこに入力されている値をダイアログ上の初期値として表示させている。

```php:Redmine_custom.php
private function _get_precondition_default($context)
{
    return $context['tests'][0]->case->custom_preconds;
}

```
$context には、TestCaseやRunなどのTestRail側の情報が保持されている。
その構造は、TestRailをデバッグモードにして、ログから取得することができる。
※TestRailでログを出力する方法は[こちら](https://www.gurock.com/testrail/docs/customization/ui-scripts/debugging)
ただし、設定ファイルを変更し、[デバッグモード](https://www.gurock.com/testrail/docs/user-guide/howto/enabling-debug)に設定変更する必要がある。
ログの場所：(TestRailルートディレクトリ)/logs/log-YYYY-MM-DD.php


## ④入力内容をRedmineに連携
add_issueメソッドに追加
カスタムフィールドではない場合

```php:Redmine_custom.php
$issue->priority_id = $options['priority'];
```

カスタムフィールドの場合、IDと値を配列で渡す。

```php:Redmine_custom.php
$issue->custom_fields = array(	
  array(	
    'value' => $options['phase'],	
    'id' => 15, //②で取得したカスタムフィールドのID
  ),
```

# まとめ
その他、細かいけど。。。
・カスタムフィールド取得するAPIが、Redmineで強めの権限(管理者？)持ってるユーザでないと実行できない。
・RedmineのAPIで取得できるデータ件数が100件までしかできない。
・RedmineとTestRailとユーザとPWは共通だけど、SSOみたいなことはできていない。TestRail側でユーザ名とPWを入れる必要がある
・Redmine上で必須項目になっているものは、もれなくTestRailにも追加する必要がある。

など、いくつか工夫して回避した部分あり。
あと、公式のサイトで調べて出るところ（主に、TestRail上のAdmin画面でできるような設定）は、だいぶ省略しているので、もっかいやる場合はそこから見直し必要。

ただ、どこまでリッチに作りこむか、利用するメンバーの規模感に応じて検討。