redmine.tokyo第23回LT「Redmineプラグインのテスト自動化を頑張っている話」の補足と続き

この記事は、[Redmine Advent Calendar 2022](https://adventar.org/calendars/7683) の22日目の内容になります。(が、遅れてしまって申し訳ありません...:bow:)

# はじめに

2022/11/05(土)の[redmine.tokyo 第23回勉強会](https://redmine.tokyo/projects/shinared/wiki/%E7%AC%AC23%E5%9B%9E%E5%8B%89%E5%BC%B7%E4%BC%9A)で「Redmineプラグインのテスト自動化を頑張っている話」というLTをしましたが、時間配分が全くできてませんでした...。
特に後半の説明箇所を飛ばしてしまいましたので、説明できなかった箇所の補足と、続きで少し試してみたことを記載しようと思います。

<iframe src="//www.slideshare.net/slideshow/embed_code/key/MZ3ITz9uB4uMei" width="595" height="485" frameborder="0" marginwidth="0" marginheight="0" scrolling="no" style="border:1px solid #CCC; border-width:1px; margin-bottom:5px; max-width: 100%;" allowfullscreen> </iframe> <div style="margin-bottom:5px"> <strong> <a href="//www.slideshare.net/geosanak/redminepdf" title="Redmineプラグインのテスト自動化を頑張っている話" target="_blank">Redmineプラグインのテスト自動化を頑張っている話</a> </strong> from <strong><a href="//www.slideshare.net/geosanak" target="_blank">Ko Nagase</a></strong> </div>

# GitHub Actionsでのテスト自動化設定

<!-- GitHub Actionsでのテスト自動化設定 (1 / 8) -->
[![redminepdf/9](https://image.slidesharecdn.com/redmine-221106063724-8fb7c75f/85/redmine-9-638.jpg)](https://www.slideshare.net/geosanak/redminepdf/9)

`test.yml` ファイルのリンクは以下で、右上の `Raw` ボタン上で右クリックし、リンク先を別名で保存すればファイルをダウンロードできます。
https://github.com/sanak/redmine_text_blocks/blob/main/.github/workflows/test.yml

<!-- GitHub Actionsでのテスト自動化設定 (2 / 8) -->
[![redminepdf/10](https://image.slidesharecdn.com/redmine-221106063724-8fb7c75f/85/redmine-10-638.jpg)](https://www.slideshare.net/geosanak/redminepdf/10)
[GitHubコードリンク](https://github.com/sanak/redmine_text_blocks/blob/main/.github/workflows/test.yml#L3-L14)

冒頭の `env:↓  PLUGIN_NAME` の箇所は、ワークフロー全体での環境変数で、ここではプラグインのフォルダ名を指定します。
[環境変数 - GitHub Docs](https://docs.github.com/ja/actions/learn-github-actions/environment-variables)

また、 `on` 配下はワークフローのトリガーを指定している箇所で、指定したブランチ(`main` と `master`)へのプッシュ・プルリクエスト時のみ、ワークフローが起動されることを意味しています。
[ワークフローのトリガー - GitHub Docs](https://docs.github.com/ja/actions/using-workflows/triggering-a-workflow)
ワークフローのトリガーには、他にも [スケジュールされた時刻(cron形式)](https://docs.github.com/ja/actions/using-workflows/events-that-trigger-workflows#schedule) や [手動トリガー](https://docs.github.com/ja/actions/using-workflows/triggering-a-workflow#defining-inputs-for-manually-triggered-workflows) も可能なので、状況に応じて使い分けることができるかもしれません。

<!-- GitHub Actionsでのテスト自動化設定 (3 / 8) -->
[![redminepdf/11](https://image.slidesharecdn.com/redmine-221106063724-8fb7c75f/85/redmine-11-638.jpg)](https://www.slideshare.net/geosanak/redminepdf/11)
[GitHubリンク](https://github.com/sanak/redmine_text_blocks/blob/main/.github/workflows/test.yml#L26-L36)

テストのマトリックス(組み合わせ)を指定している箇所です。
[ジョブにマトリックスを使用する - GitHub Docs](https://docs.github.com/ja/actions/using-jobs/using-a-matrix-for-your-jobs)

Redmineのみで、RedMicaのサポートが不要であれば、 `redmine: [...]` の箇所は `redmine_version: [4.2-stable, 5.0-stable, master]` などと変更可能と思いますが、RedMicaはRedmineにとっても両輪のような形で引き続き重要なように思います。
なお、RedMicaについては、先月末に2.2がリリースされましたので、
[RedMica 2.2 バージョンアップのお知らせ |プロジェクト管理・タスク管理はMy Redmine](https://hosting.redmine.jp/news/2022/11/redmica-2_2_0-update/)
今だと以下の行を追加することも可能のはずです。
```yml
{ repo: redmica, version: stable-2.2 },
```

Rubyも12/25(日)のクリスマスに3.2がリリースされましたので、Redmine本家側での対応を待ってから、以下のように `ruby_version` の配列末尾に追加することでテスト可能と思います。
[Feature #38099: Ruby 3.2 support - Redmine](https://www.redmine.org/issues/38099)
```yml
ruby_version: ['2.6', '2.7', '3.0', '3.1', '3.2']
```

<!-- GitHub Actionsでのテスト自動化設定 (4 / 8) -->
[![redminepdf/12](https://image.slidesharecdn.com/redmine-221106063724-8fb7c75f/85/redmine-12-638.jpg)](https://www.slideshare.net/geosanak/redminepdf/12)

こちらでは、先ほどのマトリックスから除外する組み合わせを `exclude` 配下で指定しています。
[ジョブにマトリックスを使用する - マトリックス構成の除外 - GitHub Docs](https://docs.github.com/ja/actions/using-jobs/using-a-matrix-for-your-jobs#excluding-matrix-configurations)

例えば、先ほどのRuby3.2が追加された状態の場合、Ruby3.2のビルドがサポートされるのはRedmine・RedMicaの各masterブランチになると思われますので、その他を除外する場合は以下を `exclude` 配下に追加する形になると思います。
```rb
        exclude:
          :
          - redmine: { repo: redmine, version: 4.2-stable }
            ruby_version: '3.2'
          - redmine: { repo: redmine, version: 5.0-stable }
            ruby_version: '3.2'
          - redmine: { repo: redmica, version: stable-2.0 }
            ruby_version: '3.2'
          - redmine: { repo: redmica, version: stable-2.1 }
            ruby_version: '3.2'
          - redmine: { repo: redmica, version: stable-2.2 }
            ruby_version: '3.2'
```

<!-- GitHub Actionsでのテスト自動化設定 (5 / 8) -->
[![redminepdf/13](https://image.slidesharecdn.com/redmine-221106063724-8fb7c75f/85/redmine-13-638.jpg)](https://www.slideshare.net/geosanak/redminepdf/13)

赤字箇所は、プラグインのアップストリームにテスト目的のプルリクエストを投げないようにしましょうという注意書きです。
(GitHubのデフォルトのターゲットリポジトリ・ブランチが、自分のフォークリポジトリ・ブランチになっていると、誤りがなくて助かるところではあります...:sweat_smile:)

<!-- GitHub Actionsでのテスト自動化設定 (6 / 8) -->
[![redminepdf/14](https://image.slidesharecdn.com/redmine-221106063724-8fb7c75f/85/redmine-14-638.jpg)](https://www.slideshare.net/geosanak/redminepdf/14)

テスト自動実行の確認手順を記載しています。私のリポジトリでのリンクも貼っておきます。

https://github.com/sanak/redmine_text_blocks/actions

<!-- GitHub Actionsでのテスト自動化設定 (7 / 8) -->
[![redminepdf/15](https://image.slidesharecdn.com/redmine-221106063724-8fb7c75f/85/redmine-15-638.jpg)](https://www.slideshare.net/geosanak/redminepdf/15)

こちらも当時のリンクが残ってましたので、貼っておきます。

https://github.com/sanak/redmine_text_blocks/actions/runs/3350392379

ちなみに、上記のエラーの原因は、確認の結果、Redmine本体側の `Gemfile` にあることが分かり、修正パッチを作成して取り込んで頂きました。:smile:

[Patch #37883: Limit mocha version to < 2.0.0 when Ruby version is < 2.7 to avoid test error - Redmine](https://www.redmine.org/issues/37883)

<!-- GitHub Actionsでのテスト自動化設定 (8 / 8) -->
[![redminepdf/16](https://image.slidesharecdn.com/redmine-221106063724-8fb7c75f/85/redmine-16-638.jpg)](https://www.slideshare.net/geosanak/redminepdf/16)

こちらもGitHubのリンクを貼っておきます。

https://github.com/sanak/redmine_text_blocks#readme


<!-- 補足 -->
[![redminepdf/17](https://image.slidesharecdn.com/redmine-221106063724-8fb7c75f/85/redmine-17-638.jpg)](https://www.slideshare.net/geosanak/redminepdf/17)

> - Redmineプラグインでテストを記述してなくても、DBマイグレーションやZeitwerkチェックとしてだけでも有効

DBマイグレーションに関しては、私の場合PostgreSQLは日常的に利用していても、MySQLはほぼ使ってないので、その点で役に立ちました。

また、Zeitwerkチェック(`rake zeitwerk:check`)も、普段から意識して実行していないと忘れがちになるので、注意が必要です。

> - システムテスト関連のコメントアウト箇所を外せば、システムテスト(E2E、ブラウザテスト)の実行も可能 (ただし、2〜3倍時間がかかります)

こちらは、以下の37行目〜43行目のコメントアウト箇所を外せば実行可能です。
(ただし、時間がかかるので、組み合わせを1つのみ(Redmineのmasterブランチ、Ruby3.1、MySQL)に絞る形にしています。)
https://github.com/sanak/redmine_text_blocks/blob/main/.github/workflows/test.yml#L37-L43
```yml
        # # System test takes 2~3 times longer, so limit to specific matrix combinations
        # # See: https://docs.github.com/en/actions/using-jobs/using-a-matrix-for-your-jobs#expanding-or-adding-matrix-configurations
        # include:
        #   - system_test: true
        #     redmine: { repo: redmine, version: master }
        #     ruby_version: '3.1'
        #     db: mysql
```

> - Redmine本体のコメントアウト箇所を外せば、プラグインがRedmine本体の挙動に影響を与えないことの確認も可能 (こちらはさらに時間がかかります)

こちらは、最後の方の185行目〜198行目のコメントアウト箇所を外せば実行可能です。
https://github.com/sanak/redmine_text_blocks/blob/main/.github/workflows/test.yml#L185-L198
```yml
      # - name: Run core tests
      #   env:
      #     RAILS_ENV: test
      #     PARALLEL_WORKERS: 1
      #   working-directory: redmine
      #   run: bundle exec rake test

      # - name: Run core system tests
      #   if: matrix.system_test == true
      #   env:
      #     RAILS_ENV: test
      #     GOOGLE_CHROME_OPTS_ARGS: "headless,disable-gpu,no-sandbox,disable-dev-shm-usage"
      #   working-directory: redmine
      #   run: bundle exec rake test:system
```

こちらも、テスト実行に時間がかかる点はご注意ください。

<!-- 今後の課題 -->
[![redminepdf/18](https://image.slidesharecdn.com/redmine-221106063724-8fb7c75f/85/redmine-18-638.jpg)](https://www.slideshare.net/geosanak/redminepdf/18)

> - ジョブが並列実行されるGitHub Actionsでも、初期状態のtest.yml(組み合わせ数:60)で7〜11分ほどかかるので、テスト実行時間の短縮化を図る
>   - GitHub Actions自体の機能が年々向上してきているので、そちらに期待したいというのもあったり...

現状、 `test.yml` の可読性を上げ、重複を避けたいという思いから、PostgreSQLのテスト時にもMySQLサービスも同時に立ち上がる作りになっていて、そのこともテスト実行に時間がかかる一因となっているかもしれません。

redmine.tokyo第23回の後、Redmine本体側のGitHub Actionsテストでは、複合アクションを利用することで、
[複合アクションを作成する - GitHub Docs](https://docs.github.com/ja/actions/creating-actions/creating-a-composite-action)

重複箇所を別のアクションとして切り出し、ワークフロー側ではマトリックス定義だけに絞ることも可能そうに思われましたが、様々なケースが想定されるRedmineプラグインの場合のGitHub Actionsの最適解がどのような形になるかはまだ見いだせてません...。

https://github.com/sanak/redmine/pull/2

> システムテスト(E2E、ブラウザテスト)はChromeのインストールなどでさらに時間がかかるので、良い方法を検討する

システムテストに関しては、まだプラグインに組み込めてないのと、Redmine本体側の方でもランダムに失敗していると思われる箇所がありますので、インストールもさることながら、引き続き調査・検討を行っていく予定です。

<!-- 謝辞 -->
[![redminepdf/20](https://image.slidesharecdn.com/redmine-221106063724-8fb7c75f/85/redmine-20-638.jpg)](https://www.slideshare.net/geosanak/redminepdf/20)

LT発表時に流してしまいましたが、発表にあった `test.yml` は上記にある様々な先行事例を参考に組み合わせたものになります。
Redmineパッチ会の方々や、Redmineプラグイン・関連プロジェクト開発者の方々には改めてお礼申し上げます。

# おわりに

本年もコミュニティの方には大変お世話になりました。
redmine.tokyo第23回も当日オフライン参加できて本当に良かったです。

来年も引き続き、よろしくお願いいたします！

また、Redmineパッチ会も月1回ペースで開催しておりますので、ご興味ある方おられましたら、是非ご参加ください。

https://redmine-patch.connpass.com/

それでは、良いお年を！