- UIよりもAPIを優先
- 余計な期待は避けましょう
- 複数のファイルにテストを分割することを推奨
before(:context)
、after
フックでのUIの使用を制限。- テストがブラウザにログインしたままにならないようにします。
- 管理者アクセスが必要なタグテスト
Commit
リソースを優先します。ProjectPush
エンドツーエンドテストのベストプラクティス
UIよりもAPIを優先
エンドツーエンドのテストフレームワークは、ケースバイケースでリソースを作成する機能を持っています。 リソースは、可能な限り API 経由で作成されるべきです。
API経由でテストに必要なリソースを作成することで、時間とコストの両方を節約できます。
リソースについて詳しくはこちらをご覧ください。
余計な期待は避けましょう
テストを無駄のないものにするためには、必要なものだけをテストすることが重要です。
テストする必要のある内容とは関係のない、expect()
ステートメントを追加しないようにしてください。
使用例:
#=> Good
Flow::Login.sign_in
Page::Main::Menu.perform do |menu|
expect(menu).to be_signed_in
end
#=> Bad
Flow::Login.sign_in(as: user)
Page::Main::Menu.perform do |menu|
expect(menu).to be_signed_in
expect(page).to have_content(user.name) #=> we already validated being signed in. redundant.
expect(menu).to have_element(:nav_bar) #=> likely unnecessary. already validated in lower-level. test doesn't call for validating this.
end
#=> Good
issue = Resource::Issue.fabricate_via_api! do |issue|
issue.name = 'issue-name'
end
Project::Issues::Index.perform do |index|
expect(index).to have_issue(issue)
end
#=> Bad
issue = Resource::Issue.fabricate_via_api! do |issue|
issue.name = 'issue-name'
end
Project::Issues::Index.perform do |index|
expect(index).to have_issue(issue)
expect(page).to have_content(issue.name) #=> page content check is redundant as the issue was already validated in the line above.
end
複数のファイルにテストを分割することを推奨
私たちのフレームワークには、仕様ファイルを並列に実行することで機能する、いくつかの並列化メカニズムが含まれています。
しかし、テストは specファイル単位で並列化され、test/example 単位では並列化されないため、既存のファイルに新しいテストが追加されても、より大きな並列化は実現できません。
とはいえ、既存のファイルに新しいテストを追加する理由は他にもあるでしょう。
たとえば、セットアップにコストがかかる状態をテストが共有する場合、そのセットアップを使用するテストが並列化できなくても、セットアップを一度だけ実行したほうが効率的な場合があります。
要約すると
- To-Do: 高価なセットアップを共有するテストを除き、テストを別々のファイルに分割します。
- 禁止: 並列化への影響を考慮せずに、既存のファイルに新しいテストを追加してください。
before(:context)
、after
フックでのUIの使用を制限。
before(:context)
フックの使用は、APIコール、非UIオペレーション、またはログインのような基本的なUIオペレーションのみでセットアップタスクを実行するように制限してください。
失敗時に自動的にスクリーンショットを保存するためにcapybara-screenshot
ライブラリを使用しています。
capybara-screenshot
スクリーンショットはRSpecのafter
フックに保存されます。before(:context)
で失敗した場合、after
フックは呼び出されず、 したがってスクリーンショットは保存されません。
この事実を踏まえると、before(:context)
の使用は、スクリーンショットが不要なオペレーションのみに限定すべきです。
同様に、after
フックは非UIオペレーションにのみ使用されるべきです。 after
テストファイル内のフックにafter
あるUIオペレーションは after
、スクリーンショットを撮影するafter
フックの前に実行されます。これは、UIステータスを障害発生ポイントから遠ざける結果となり、スクリーンショットが適切なタイミングで撮影されません。
テストがブラウザにログインしたままにならないようにします。
すべてのテストは、テスト開始時にログインできることを想定しています。
例をご覧ください:https://gitlab.com/gitlab-org/gitlab/-/issues/34736
理想的には、after(:context)
(またはbefore(:context)
)ブロックで実行されるアクションはすべてAPI経由で実行されます。しかし、UI経由で実行する必要がある場合(API機能が存在しない場合など)は、ブロックの最後でログアウトするようにしてください。
after(:all) do
login unless Page::Main::Menu.perform(&:signed_in?)
# Do something while logged in
Page::Main::Menu.perform(&:sign_out)
end
管理者アクセスが必要なタグテスト
本番環境に対して管理者アクセスを必要とするテストを実行することはありません。
Administrator アクセスを必要とする新しいテストを追加したら、RSpec メタデータ:requires_admin
を適用して、Production やその他のテストを実行したくない環境に対して実行されるテストスイートに、そのテストが含まれないようにします。
注意: ローカルでテストを実行したり、パイプラインを設定したりする場合は、環境変数QA_CAN_TEST_ADMIN_FEATURES
をfalse
に設定することで、:requires_admin
タグを持つテストをスキップすることができます。
Commit
リソースを優先します。ProjectPush
APIを使用する際には、可能な限りCommit
。
ProjectPush
は、Git Command Line Interface(CLI) を使った生のシェルコマンドを使うのに対し、Commit
リソースは HTTP リクエストを行います。
# Using a commit resource
Resource::Commit.fabricate_via_api! do |commit|
commit.commit_message = 'Initial commit'
commit.add_files([
{file_path: 'README.md', content: 'Hello, GitLab'}
])
end
# Using a ProjectPush
Resource::Repository::ProjectPush.fabricate! do |push|
push.commit_message = 'Initial commit'
push.file_name = 'README.md'
push.file_content = 'Hello, GitLab'
end
ProjectPush
を使う例外としては、SSH インテグレーションや Git CLI を使うテストがあります。