レガシーの呪縛を解く:FlaUIで実現するWindows Forms自動テストの極意
Windows Forms(WinForms)は、その開発効率の高さから、今なお業務アプリケーションの現場で現役で稼働しています。しかし、その「レガシー」というレッテルが、テストの不在と手動リグレッションテストの地獄を正当化する免罪符になってはいないでしょうか。
本稿では、UIオートメーションライブラリ「FlaUI」を用い、CI/CDパイプラインに組み込み可能な堅牢なテスト基盤を構築するアーキテクチャを伝授します。
—
1. なぜ「手動テスト」がプロジェクトを腐らせるのか
WinFormsアプリのUIテストを自動化しない最大の理由は「UIコントロールへのアクセスが不安定」という先入観です。しかし、UIテストが失敗するのは、FlaUIのせいではなく、「テスト容易性を考慮しないUI設計」に根本原因があります。
- AutomationIdの欠如: Nameプロパティに依存したテストは、多言語対応やUIリファクタリングで即座に崩壊します。
- 密結合なロジック: フォームのイベントハンドラに直接データベース操作が書かれていると、テスト実行時に外部環境の影響を強く受けます。
これらを解決するのが、「Page Object Pattern(POP)」の導入と「AutomationIdの徹底」です。
—
2. FlaUIによるテスト自動化の極意:コード実装
まずは、テスト対象のWinFormsアプリケーションを起動し、特定のコントロールを操作する最小構成の実装例を示します。
‘ FlaUI.Core と FlaUI.UIA3 をプロジェクトにインストールしておくこと
Imports FlaUI.Core
Imports FlaUI.Core.AutomationElements
Imports FlaUI.UIA3
Public Class WinFormsTestBase
‘ アプリの起動と終了を管理するライフサイクル
Public Shared Sub TestLoginScenario()
‘ アプリケーション起動
Using app = Application.Launch(“C:\Path\To\YourApp.exe”)
Using automation = New UIA3Automation()
Dim window = app.GetMainWindow(automation)
‘ AutomationIdで特定する(これが鉄則)
‘ プロパティ設定: Control.AutomationId = “txtUsername”
Dim usernameBox = window.FindFirstDescendant(Function(cf) cf.ByAutomationId(“txtUsername”)).AsTextBox()
Dim loginButton = window.FindFirstDescendant(Function(cf) cf.ByAutomationId(“btnLogin”)).AsButton()
‘ 操作実行
usernameBox.Enter(“AdminUser”)
loginButton.Click()
‘ アサーション:期待値の検証
Dim statusLabel = window.FindFirstDescendant(Function(cf) cf.ByAutomationId(“lblStatus”)).AsLabel()
If statusLabel.Text <> “ログイン成功” Then
Throw New Exception(“テスト失敗:ログイン処理が期待通り動作しませんでした。”)
End If
End Using
End Using
End Sub
End Class
実務でハマらないための設計指針
1. AutomationIdを全コントロールに付与せよ: デザイナー画面で個別にプロパティを設定するのが面倒なら、フォームのコンストラクタで再帰的にIDを自動付与するベースクラスを設計するのも手です。
2. 待機処理(Wait)の最適化: `Thread.Sleep`は禁止です。`Retry.While`や`Wait`メソッドを使い、要素が描画されるまで「待つ」設計を徹底してください。
3. データベースの分離: テスト実行時は、開発環境のDBではなく、SQLiteやインメモリDBを参照する構成プロファイルを切り替えられるようにします。
—
3. CI/CDパイプラインとの連携(Jenkins/GitHub Actions)
自動テストは「ローカルで動く」だけでは無意味です。ビルドのたびにテストが走り、失敗すれば即座にデプロイを止める。このサイクルこそが保守性の源泉です。
- ヘッドレスモード: WinFormsはGUIアプリのため、CI環境(サーバー上)で実行するには、セッション接続が必要です。
- 失敗時のスクリーンショット: FlaUIは、要素が見つからない等のエラー時に自動でスクリーンショットを保存する機能があります。これをビルドアーティファクトとして残す設計をしてください。
‘ テスト失敗時にログとスクリーンショットを保存するラッパー例
Try
‘ 操作コード
Catch ex As Exception
Dim screenshot = window.Capture()
screenshot.Save(“Error_Screenshot.png”)
Throw
End Try
—
4. 最後に:プロフェッショナルの矜持
「VB.NETだから古い」「WinFormsだから自動化できない」という言い訳は、技術者の怠慢です。FlaUIは、レガシーなWindowsアプリケーションを、モダンなCI/CDパイプラインの中に引きずり込むための強力な架け橋となります。
UIテストを書き始めると、自然と「テストしにくいコード」を避けるようになり、結果としてアプリケーションのアーキテクチャが洗練されていきます。これが、私が提唱する「テスト駆動による設計の自浄作用」です。
今日から、UIのプロパティひとつひとつに心を込め、AutomationIdを刻み込んでください。それが、10年後もメンテナンス可能なシステムを作るための、唯一の近道です。
