Automation QA (Quality Assurance)Senior Automation QA Engineer / QA Architect

エンドツーエンドのビジネスプロセス検証を異種技術スタックにわたって実行できる自動化フレームワークの設計図を作成してください。具体的には、レガシーのメインフレームターミナルエミュレーター(3270)、モダンなREST API、および動的なReactベースのWebポータル間の相互作用を調整し、ビジネスアナリスト向けの統一されたドメイン固有言語(DSL)を維持し、これらの異なるシステム間でトランザクションの整合性のロールバック機能を確保してください。

Hintsage AIアシスタントで面接を突破

質問の背景

デジタルトランスフォーメーションを進めている企業は、ミッションクリティカルなコアバンキングトランザクションが数十年前のCOBOLメインフレーム上で処理されている複雑な「ブラウンフィールド」環境で動作することがよくあります。 同時に、顧客向けのオンボーディングやサービスフローは、ますます多くのモダンなReactベースのWebポータルやモバイルアプリケーションによって処理されています。この技術的な分岐は、QAチームにとって大きな検証の課題を生み出します。彼らは、根本的に異なるアーキテクチャ全体でシームレスでエラーのないデータフローとトランザクションの整合性を確保しなければなりません。

従来、このような環境での自動化の取り組みは多くの場合、専門のチームがメインフレームターミナルエミュレーション(JagacyやExtra!など)、一般的なUI自動化(SeleniumやCypress)、API検証(Rest-AssuredやPostman)に対して別々のツールセットを維持しているため、著しくサイロ化されます。この断片化は、非技術的なビジネスアナリストにはレビューまたは要件と照らし合わせて検証できない、高度に技術的な用語で書かれた壊れやすい統合スイートを生じさせます。さらに、テストが実行中に失敗すると、データ整合性が壊滅的な問題を引き起こすことがしばしばあり、メインフレームアカウントが作成されたまま、対応するWebポータル検証が未完了の状態になり、孤立したテストデータでダウンストリーム環境を汚染してしまう可能性があります。

この特定の質問は、モバイルReactアプリケーション、Kafkaイベントバス、Javaマイクロサービス層、および最終アカウントのプロビジョニングがIBM z/OSメインフレームで行われる複雑な「新規顧客オンボーディング」ワークフローを検証するのに苦労しているフォーチュン500の金融サービス企業から生じました。この組織は、これらの技術的な分断をつなぎながら、現代のDevOpsパイプラインで期待される機敏性を維持できる統一された自動化戦略を必要としていました。この課題はさらに、ビジネスアナリストが各システムの技術的な実装を理解することなくテストシナリオを作成し、理解する必要があるというニーズによって複雑化されました。

問題

核心の課題は、即時のDOM更新とイベント駆動の相互作用を期待する非同期Web自動化と、明示的な画面スクレイピングと正確なカーソル位置指定に依存する3270メインフレームのブロックモードターミナルエミュレーションとの根本的なインピーダンスミスマッチにあります。RESTful APIsは、ターミナルセッションのセッションの継続性が欠如した、ステートレスなリクエスト-レスポンスパラダイム内で動作するため、さらなる複雑さを引き起こします。これらのアーキテクチャスタイルを橋渡しするには、高レベルのビジネスアクションをシステム固有のコマンドに変換できる抽象化レイヤーが必要です。

DSL(ドメイン固有言語)を維持することは、テストステップの技術的な実装がシステム間でこんなにも広がる場合、非常に困難になります。Web要素は通常CSSセレクターやXPath式を使用して識別され、API検証はJSONパスアサーションとスキーマ検証に依存し、メインフレームとの相互作用はフィールド座標、画面ラベル、またはF1やEnterなどの特定のキーシーケンスに依存します。堅牢な抽象化戦略がなければ、DSLはすぐに技術的なロケーターやシステム固有の専門用語で clutter され、その本来の目的であるビジネスと技術の利害関係者間のコミュニケーションの手段を台無しにしてしまいます。

さらに、これらの分散システム間で真のトランザクションの整合性を保証するには、テストフレームワークアーキテクチャ内で直接サーガまたは補償トランザクションパターンを実装する必要があります。このことは、テストレイヤーがメインフレームの二相コミットプロトコルや分散トランザクションマネージャにネイティブのフックを持たない場合には簡単ではありません。Webポータルでテストの失敗が発生した後にメインフレームのトランザクションがすでにコミットされている場合、フレームワークは環境の整合性を回復するための明示的なロールバック手続きをトリガする知性と能力を持つ必要があります。これには、標準的なtry-catchブロックをはるかに超えた高度な状態追跡とエラーハンドリングメカニズムが必要です。

最後に、自動化フレームワークは、センシティブな資格情報をテストスクリプトに直接埋め込むことなく、異なる認証メカニズムを安全に処理する必要があります。Webポータルはしばしば最新のOAuth2やSAMLフローを使用し、多要素認証(MFA)を組み込み、REST APIはAPIキーやJWTトークンに依存し、レガシーなメインフレームは静的ユーザープロファイルを使用してRACFやACF2プロバイダーに対して認証します。環境固有の注入機能を持つ集中型の暗号化された資格情報ボールトを維持することが、セキュリティポスチャーを維持しながらシステム間の認証をシームレスに可能にするために不可欠です。

解決策

これらの複雑さに対処するため、フレームワークは**六角形のアーキテクチャ(ポートとアダプター)**パターンを使用して設計されるべきであり、テストドメインロジックと外部システムの相互作用の間の厳密な分離を強制します。enterCustomerData(), verifyAccountCreation(), rollbackTransaction()などの高レベルのドメインメソッドを宣言する抽象的なApplicationDriverポートインターフェースを定義します。このインターフェースは、DSLレイヤー(Cucumberステップ定義やSpecFlowバインディングなど)と連携できる唯一の契約として機能し、実装の詳細から完全に分離します。

具体的なアダプター実装は、システム固有の技術的な詳細を処理します。SeleniumWebAdapterはポートメソッドをブラウザの相互作用に変換し、RestAssuredAdapterはHTTPコールを実行してJSONレスポンスを解析し、HllapiMainframeAdapterは高水準言語APIを利用してキーを送信し、画面バッファを読み取り、3270エミュレーター上のフィールド内容を検証します。各アダプターは、自身の技術スタックに適したリトライロジック、明示的な待機メカニズム、エラーハンドリング戦略をカプセル化します。状態を変更するアクションを正常に完了したアダプターは、原始データ型を返すのではなく、中央値としてドメインイベント(AccountCreatedEventなど)を中央のTestEventBusに発行します。

トランザクションの整合性を維持するために、テストシナリオ中に実行されたすべてのCompensableActionオブジェクトの順序付きログを維持するテストサーガオーケストレーターを実装します。ワークフロー内のいずれかのステップが例外とともに失敗した場合、オーケストレーターは自動的に以前に成功したアクションのcompensate()メソッドを逆の順序で実行し、メインフレームアカウントを削除したり、API予約を無効にする補償トランザクションを実行します。このパターンは、テスト環境が常に清潔でいることを保証し、テストが途中で失敗しても孤立したデータの蓄積を防ぎます。

異種スタック全体の状態管理は、TestContextをファーストクラスの市民として扱うことにより実現され、リッチなドメインオブジェクトを原始的な文字列の代わりにThreadLocal<DomainContext>に格納し、テストステップ間の密接な結合を防ぎます。Reactアダプターは、コンテキスト内にCustomerProfileオブジェクトを格納し、メインフレームアダプターが後でそのワークフローの部分を実行するためにそれを取得します。このアプローチにより、DSLはセッションIDや画面座標のような技術的な識別子ではなく、ビジネスエンティティに焦点を当てることができます。

これらのコンポーネントを結び付けるために、Google Guava EventBusやリアクティブストリームのような軽量メッセージングバスを利用して、アダプターが直接のメソッド呼び出しなしに状態変更を通信できるようにし、メインフレームフローとWeb検証フローを分離します。HllapiMainframeAdapterがアカウントを正常に作成したとき、それはアカウント詳細を含むイベントを発行し、SeleniumWebAdapterがそれを消費して適切な検証画面に自動的に移動します。このテストフレームワーク内でのイベント駆動アプローチは、現代のマイクロサービスアーキテクチャを反映し、個々のシステムインターフェースが変更されたときのメンテナンスオーバーヘッドを大幅に削減します。

// ポートインターフェース定義 public interface BankingDriver { void enterCustomerData(Customer customer); AccountDetails submitAccountCreation(); void verifyAccountInPortal(AccountDetails account); void rollbackAccountCreation(AccountDetails account); } // HLLAPIを使用したメインフレームアダプター public class MainframeAdapter implements BankingDriver { private final HllapiWrapper hllapi; private final EventBus eventBus; @Override public AccountDetails submitAccountCreation() { hllapi.sendKey("@E"); // Enterキーをシミュレート waitForScreen("アカウント作成"); String accountId = hllapi.getTextByLabel("アカウント番号:"); AccountDetails details = new AccountDetails(accountId); eventBus.post(new AccountCreatedEvent(details)); return details; } @Override public void rollbackAccountCreation(AccountDetails account) { hllapi.sendKeys("DELETE " + account.getId()); hllapi.sendKey("@E"); verifyScreen("削除確認済み"); } } // トランザクション整合性のためのサーガオーケストレーター public class TestSagaOrchestrator { private final List<CompensableAction> executedActions = new ArrayList<>(); public void execute(Runnable action, Runnable compensation) { try { action.run(); executedActions.add(new CompensableAction(action, compensation)); } catch (Exception e) { compensate(); throw new TestFailureException(e); } } private void compensate() { Collections.reverse(executedActions); for (CompensableAction action : executedActions) { try { action.compensate(); } catch (Exception ex) { publishToDeadLetterQueue(action, ex); } } } }

実生活からの状況

2022年にデジタルトランスフォーメーションを進めるグローバルな保険会社とのコンサルティング契約中に、これらの正確な課題を示す重要な「損失報告書(FNOL)」ビジネスプロセスに直面しました。このワークフローでは、ポリシーホルダーがReact Nativeモバイルアプリケーションを介してクレームを提出し、事故の写真をアップロードすることで、ダメージ評価と詐欺検出のためのPythonベースの機械学習マイクロサービスがトリガーされ、最後にレガシーなUnisysメインフレームシステムが金融リザーブを割り当て、ポリシーカバレッジを検証します。既存の自動化戦略は、モバイルアプリ用のCypress、API用のPytest、メインフレームターミナルエミュレーション用のJagacyという3つの異なる非通信スイートに依存していました。

このサイロ化アプローチは、チームが共有Excelスプレッドシートを使用して間接的に請求番号を相互に関連付けることを必要とし、環境汚染が回帰サイクルの深刻なブロッカーになる事態を引き起こしました。危機の瞬間は、モバイルネットワークのタイムアウトが原因でメインフレームがすでに$50,000のリザーブ割り当てをコミットした後にテストが失敗し、金融データが不整合な状態になり、メインフレームシステムプログラマーが4時間もの手動クリーンアップを必要としたときに発生しました。このインシデントは、チームの「クリーンな環境」ポリシーに直接違反し、CI/CDパイプラインを1日全体停止させました。

将来の発生を防ぐために、3つの潜在的な修正戦略を評価しました。最初のオプションは、テスト後のデータベースクリーンアップスクリプトを書いてメインフレームトランザクションを手動で逆転させることを含んでいましたが、セキュリティポリシーにより本番に類似したUATメインフレーム環境への直接的なSQLアクセスが禁止されていたため却下されました。第二のアプローチは、テストの実行を直列化するために悲観的ロックメカニズムを使用した共有テストデータプールを実装することを提案しましたが、これによりスイートの実行時間が20分から4時間以上に延びることとなり、CI/CDにおける並列化の利点を完全に無にしてしまうものでした。最終的に選択した第三の戦略は、テスト自動化フレームワーク自体内にサーガパターンを実装し、アプリケーションの最終一貫性モデルを反映しつつ、数百のテストを並行して実行する能力を維持するというものでした。

実装されたソリューションは、モバイルおよびメインフレームアダプターによって実行されるすべてのアクションを傍受するClaimSagaオーケストレーターを導入しました。モバイルアダプターがネットワークタイムアウトによりStaleElementReferenceExceptionをスローしたとき、サーガは即座にThreadLocalコンテキストに保存されている請求IDを使用してメインフレームアダプター上のreverseReserveAllocation()補償トランザクションをトリガしました。この自動ロールバックメカニズムにより、環境データ汚染が98%削減され、チームは孤立した金融記録を作成することを恐れずに、Jenkinsパイプラインで500の並行スレッドを自信を持って実行できるようになりました。

このテストの信頼性の劇的な向上により、QAチームは手動データクリーンアップから探索的テストやエッジケース分析に焦点を移すことができました。ビジネスアナリストは、重要なポリシーホルダーが重大な事故を報告すると、写真がアップロードされますが、AI評価サービスがタイムアウトします。その場合、財政的リザーブは割り当てられませんなどの単純な英語で書かれたテストシナリオを作成し、レビューすることがついにできるようになりました。これにより、自動化スイートは、すべての3つの技術レイヤーにわたる複雑なビジネスルールを反映した正確な活きた文書として機能することが確保されました。

候補者が見逃しがちな点


エミュレーターとWebポータル間のセッション状態永続性を、アダプター間の緊密な結合を生じさせることなくどのように処理しますか?

初歩的な候補者は、しばしばこの問題を生のセッション識別子やデータベース主キーをステップ定義メソッドから直接返すことで解決しようとし、ステップBがステップAから特定の文字列値を明示的に返さない限り、実行できない脆弱な依存関係を作り出します。このアプローチは、ドメイン駆動設計の原則を根本的に破壊し、ビジネス可読のGherkinステップが厳密に技術的なシーケンスで順序付けられることを強要し、論理的なビジネスフローではなくなります。さらに、実装の詳細がDSLレイヤーに漏れ出し、技術的な識別子がフォーマットを変更する際にテストが脆弱になります。

堅牢なアーキテクチャソリューションは、テスト実行中に一時的なレジストリとして機能するシナリオコンテキストまたはテストデータコンテキストを実装します。これは通常、並行実行中のスレッドセーフを確保するためにThreadLocal<Map<Class<?>, Object>>を使用して実装されます。アダプターは、DSLレイヤーに原始的な値を返すのではなく、しっかりと型付けされたドメインイベントやオブジェクトをこのコンテキストに発行します。たとえば、メインフレームアダプターがアカウントを正常に作成すると、完全なアカウントエンティティを含むAccountCreatedEventを発行し、Webアダプターがその後イベントバスをリッスンするか、コンテキストを照会してそれを取得します。

このイベント駆動型アプローチにより、DSLレイヤーがデータの出所に関して完全に無関係であることが保証されます。たとえば、ポリシー番号が緑色の画面からスクレイピングされた場合でも、JSONレスポンスで返された場合でも、関係ありません。具体的な実装ではなく抽象化に依存することで、フレームワークは依存関係逆転の原則に従い、個々のアダプターをリファクタリングまたは置き換えてもビジネス可読のテストシナリオに影響を与えないようにし、長期的な保守コストを大幅に削減します。


補償トランザクションが失敗することを防ぐ特定のメカニズムは何ですか?それが失敗した場合、システムが不整合な状態に置かれる可能性はありますか?

多くのジュニアエンジニアは、補償ロジック自体がエラーに遭遇するという重大な失敗モードを見落としています。これらのエラーには、メインフレームレコードを削除しようとする際のネットワークタイムアウトや、レコードがすでに同時にバックグラウンドプロセスによって変更されたための検証失敗が含まれます。このシナリオでは、「毒データ」が蓄積され、元のアクションは成功したが、ロールバックが失敗し、テスト環境が恒久的に破損した状態に留まることになります。

その解決策は、インデポテント補償アクションを実装し、複製削除エラーを引き起こすことなく、安全に何度も再試行できるように設計されたアクションを実装することです。これらは、いかなるトランジットインフラストラクチャの障害を優雅に処理できるように、指数バックオフとサーキットブレイカーパターンを備えた堅牢なリトライメカニズムと連携させるべきです。すべてのリトライ試行が尽きた場合、フレームワークは失敗した補償の詳細を永続的な**デッドレターキュー(DLQ)**に発行する必要があります。このDLQは、完全な相関IDとスタックトレースを含むデータベーステーブルまたはメッセージトピックとして実装できます。

さらに、補償を試みる前に検証ゲートを実装して、下流システムの現在の状態を確認する必要があります。たとえば、メインフレームアカウントが存在し、残高がゼロであり、最近のユーザーの変更がないことを確認した後で削除コマンドを発行します。毎晩の自動的な照合ジョブがDLQを処理して、これらの孤立したレコードを手動で処理し、テスト環境が自己回復し、既存のデータ汚染によって重大な回帰が隠されることを防ぎます。


メインフレームの座標ベースの画面スクレイピング(HLLAPI)を使用することが負債と見なされる理由と、画面レイアウトが避けられないほど変化するときのメンテナンス負担を減らすための抽象化方法は何ですか?

候補者はしばしば、行10、列45から読み始める10文字のデータを取得するためにgetText(10, 45, 10)のようなハードコーディングされた行および列の座標を支持します。このアプローチは、初期のテスト開発中に正確かつ決定的に見えるため、その実行を重視しています。しかし、この戦略は、メインフレームアプリケーションが頻繁に画面の変更を受け、新しいフィールドが挿入され、すべての後続の座標オフセットが変更され、警告なしに全体のテストスイートが無効になります。

堅牢なアーキテクチャソリューションは、論理フィールド名(例えば、ACCOUNT_NUMBER_FIELD)を動的検索基準にマッピングする画面オブジェクトモデルを実装します。これにより、メインフレームエミュレータのフィールド識別機能が利用でき、FindFieldPositionSearchFieldのようなHLLAPI機能を介してラベルに関連するフィールドを検索できます(例えば「アカウント番号」というテキストを探す)。実行時に、アダプターは画面バッファ内でラベルテキストを探し、対応する入力フィールドに対する相対オフセットを計算します。画面レイアウトが変更されても、ラベルとオフセットをマッピングするJSON設定ファイルのみが更新され、コンパイルされたJavaコードはそのまま残ります。

さらに、相互作用の開始時に保護されていないフィールド内容の暗号的ハッシュをキャプチャする画面ハッシュまたはチェックスムメカニズムを実装して、ハッシュが期待されるベースラインと一致しない場合に、フレームワークが速やかに「画面不一致」という明確なエラーで失敗するようにします。これにより、テストは無効な位置からガーベジデータを読もうとすることがなく、偽陰性または偽陽性を生成するのを防ぎ、基本的に画面の変更が構成更新を必要とすることを自動化チームに直ちに警告します。