手動テストから卒業しよう!FlaUIで実現するWindows FormsアプリのUI自動化テスト超入門
こんにちは!頼れる先輩エンジニアのSysArchです。
日々の開発の中で、「画面のボタンを押して、値を入力して、結果が正しいか確認する」という手作業の繰り返しに疲れていませんか?
「仕様を少し変更するたびに、全画面をポチポチ手動でテストしている……」「RPAの『操作記録マクロ』を使ってみたけれど、画面のレイアウトが少し変わっただけで動かなくなってしまった……」
そんな悩みを抱えているあなたに、今回は「プログラムコードでWindows Forms画面を完全に制御し、テストを自動化する極意」を伝授します!
使うツールは、.NETの世界で非常に高い評価を得ているUIテストフレームワーク「FlaUI(フラ・ユーアイ)」です。この記事を読めば、VB.NETを使ってアプリを自動で立ち上げ、文字を入力し、ボタンをクリックして、結果が正しいかを検証(アサーション)する一連の流れが完全に理解できます。
「ここをクリアすれば、Visual Basic (VB.NET) の基本と自動テストの基礎はバッチリですよ」
さあ、手動テストの退屈な作業から脱却し、スマートな自動化の一歩を踏み出しましょう!
—
1. なぜ「マクロ記録」ではなく「FlaUIのコード」なのか?
画面自動化と聞くと、マウスの動きをそのまま記録する「マクロ記録ツール」や簡易的なRPAを思い浮かべるかもしれません。しかし、これらは現場で以下のような問題(罠)に直面します。
- 画面の座標が変わると動かなくなる(解像度やウィンドウ位置に依存する)
- ボタンの文字が変わるとエラーになる
- アプリの起動速度のゆらぎに対応できず、処理が空振りする
これらを解決するのが、MicrosoftがWindowsに標準搭載しているアクセシビリティ(支援技術)用の仕組み「UI Automation (UIA)」です。
FlaUIは、このUI Automationを非常にシンプルに、かつ強力に扱えるようにしたライブラリです。
【自動化の構造イメージ】
[ あなたが書くVB.NETコード ] (テストの司令塔)
│
▼
[ FlaUI (UIA3) ] (要素をスマートに特定・操作)
│
▼
[ Windows Forms アプリ ] (テスト対象:ボタンやテキストボックス)
FlaUIを使えば、ボタンの「座標」ではなく、プログラム内部の「ID(識別子)」を狙い撃ちして操作できます。そのため、画面のどこにボタンがあろうが、裏に隠れていようが、確実に操作を再現できるのです。
—
2. 【準備】テスト対象となるWindows Formsアプリを作る
まずは、テストされる側のシンプルなWindows Formsアプリケーションを作成しましょう。
今回は、「2つの数値を入力して『足し算』ボタンを押すと、結果が表示されるアプリ」を作ります。
2.1. 画面レイアウトとコントロールの設定
Visual Studioで「Windows Forms アプリ (.NET Framework または .NET)」プロジェクトを新規作成します。名前は `SimpleCalculator` としましょう。
画面に以下のコントロールを配置します。
| コントロールの種類 | 名前 (Name プロパティ) | 役割 |
| :— | :— | :— |
| `TextBox` | `txtNumber1` | 1つ目の数値を入力 |
| `TextBox` | `txtNumber2` | 2つ目の数値を入力 |
| `Button` | `btnCalculate` | 足し算を実行するボタン |
| `Label` | `lblResult` | 計算結果を表示するラベル |
> 💡 先輩のアドバイス:`Name` プロパティが命!
> Windows Formsでは、コントロールの `Name` プロパティ(例: `txtNumber1`)が、自動テスト側から要素を特定するための「AutomationId(自動化ID)」としてそのまま利用されます。ここを分かりやすい名前にしておくことが、UIテストを成功させる最大の秘訣です。
2.2. アプリのコード (Form1.vb)
ボタンがクリックされたときの処理を以下のように記述します。
Public Class Form1
”’
”’
Private Sub btnCalculate_Click(sender As Object, e As EventArgs) Handles btnCalculate.Click
‘ 入力値の取得と簡単なバリデーション(検証)
Dim num1 As Double
Dim num2 As Double
If Double.TryParse(txtNumber1.Text, num1) AndAlso Double.TryParse(txtNumber2.Text, num2) Then
‘ 計算結果をラベルに表示
Dim result As Double = num1 + num2
lblResult.Text = result.ToString()
Else
‘ エラー時はエラーメッセージを表示
lblResult.Text = “Error”
End If
End Sub
End Class
プロジェクトをビルドして、`SimpleCalculator.exe` が生成されることを確認してください。この実行ファイルのパス(例: `C:\TestApp\SimpleCalculator.exe`)を後ほどテストコードで使用します。
—
3. テストプロジェクトの作成とFlaUIの導入
次に、このアプリを外側から自動操作してテストする「テストプロジェクト」を作ります。
3.1. テストプロジェクトの作成
1. 同じソリューション(または新しいソリューション)に、「MSTest テスト プロジェクト」(VB.NET)を新規追加します。
2. プロジェクト名を `Calculator.UITests` とします。
3.2. NuGetパッケージのインストール
テストプロジェクトの「NuGet パッケージの管理」を開き、以下のパッケージを検索してインストールします。
- `FlaUI.UIA3` (Windows 7以降のモダンなOSに最適化されたUI Automation用ライブラリ)
これで自動テストを書く準備はすべて整いました!
—
4. 【実践】FlaUIを使った自動テストコードの執筆
それでは、いよいよ本命の自動テストスクリプトを書いていきましょう。
初学者の方でも一行ずつの意味が理解できるよう、丁寧なコメントと解説を添えています。
4.1. 自動テストのソースコード (CalculatorTests.vb)
Imports Microsoft.VisualStudio.TestTools.UnitTesting
Imports FlaUI.Core
Imports FlaUI.Core.AutomationElements
Imports FlaUI.UIA3
Public Class CalculatorTests
‘ テスト対象アプリの実行ファイルへのパス(環境に合わせて書き換えてください)
Private Const AppPath As String = “C:\TestApp\SimpleCalculator.exe”
”’
”’
Public Sub Test_Addition_ShouldShowCorrectResult()
‘ 1. アプリケーションを自動起動する
‘ Process.Start と同等の処理を FlaUI が安全に行います
Using app As Application = Application.Launch(AppPath)
‘ 2. UI Automation のインスタンスを作成(UIA3を使用)
‘ この UIA3 クラスが、Windows の画面要素を解析する「目」になります
Using automation As New UIA3Automation()
‘ 3. アプリのメインウィンドウを取得
‘ アプリが起動してウィンドウが表示されるまで、FlaUIが自動で少し待機してくれます
Dim window As Window = app.GetMainWindow(automation)
Assert.IsNotNull(window, “メインウィンドウの起動に失敗しました。”)
‘ ウィンドウのタイトルをログに出力(デバッグ用)
Console.WriteLine($”接続完了: {window.Title}”)
‘ 4. 画面上のコントロールを「AutomationId (Nameプロパティ)」で特定する
‘ FindFirstByCondition は、画面ツリーから目的の要素をピンポイントで探すメソッドです
Dim txtNum1 As TextBox = window.FindFirstByAutomationId(“txtNumber1”).AsTextBox()
Dim txtNum2 As TextBox = window.FindFirstByAutomationId(“txtNumber2”).AsTextBox()
Dim btnCalc As Button = window.FindFirstByAutomationId(“btnCalculate”).AsButton()
Dim lblRes As Label = window.FindFirstByAutomationId(“lblResult”).AsLabel()
‘ 5. 値を入力する
‘ Enter() メソッドを使うことで、人間がキーボードで打ち込んだように入力できます
txtNum1.Enter(“15”)
txtNum2.Enter(“27”)
‘ 6. 計算ボタンをクリックする
btnCalc.Click()
‘ 💡 プロの知見:描画や計算の「ほんの少しのズレ」を考慮し、ミリ秒単位で待つ
‘ 今回のような一瞬で終わる処理でも、このゆとり(ウエイト)を入れることで、
‘ テストが環境によってランダムに落ちる現象(Flaky Test)を防げます。
System.Threading.Thread.Sleep(500)
‘ 7. 結果を検証(アサーション)する
‘ 15 + 27 = 42 になっているか確認
Dim actualResult As String = lblRes.Text
Dim expectedResult As String = “42”
Assert.AreEqual(expectedResult, actualResult, $”計算結果が異なります。期待値: {expectedResult}, 実際の値: {actualResult}”)
End Using ‘ UIA3Automation の破棄
‘ 8. アプリケーションを安全に閉じる
‘ Using ブロックを抜ける際、または明示的な Close でアプリのプロセスを確実に終了させ、
‘ メモリやプロセスのゾンビ化を防ぎます
app.Close()
End Using
End Sub
End Class
—
5. コードのポイント解説:初心者が陥りやすい「3つの壁」
テストコードを動かす上で、多くのビギナーがつまずくポイントを整理しました。ここを意識すれば、あなたのスクリプトの安定性は劇的に向上します!
壁①:「要素が見つからない (ElementNotAvailableException)」
アプリが起動するスピードは、PCのCPU負荷状況によって毎回異なります。アプリが立ち上がる前にボタンを探そうとすると、「そんな要素はありません」とエラーになってしまいます。
- 解決策: FlaUIの `app.GetMainWindow(automation)` は内部で適切な待機処理(リトライ)を行ってくれます。個別要素の表示が遅れる場合は、`window.WaitUntilClickable()` などの待機メソッドを挟む習慣をつけましょう。
壁②:アプリのプロセスが裏で残り続ける(ゾンビプロセス)
テストが途中でエラー(Assert失敗など)になった際、アプリを閉じる処理を通らないと、テストを実行するたびに裏で `SimpleCalculator.exe` が大量に起動したままになってしまいます。
- 解決策: 上記コードのように、`Using app As Application = …` という `Using` 構文 を使いましょう。テストが途中で失敗して例外が発生しても、.NETの仕組みによって必ず最後に `app` の終了処理が実行され、安全にプロセスが回収されます。
壁③:テスト対象のビルド出力パス
`AppPath` に指定するパスは、テストプロジェクトからアクセスできる場所である必要があります。相対パスで指定することも可能ですが、最初は絶対パスで確実に動くことを確認するのがオススメです。
—
6. CI/CDパイプライン連携への道
テストコードがローカル環境で動くようになったら、次はチーム全員のメリットとなる「CI/CD(継続的インテグレーション)」への組み込みを考えましょう。
GitHub ActionsやAzure Pipelines、JenkinsなどのCIツールと連携することで、「誰かがコードを書き換えてGitHubに保存(プッシュ)したら、自動で画面テストが走り、バグがないか検証される」という夢の開発環境が手に入ります。
6.1. コマンドラインからの実行
テストの実行は、コマンドプロンプトやPowerShellから以下のコマンドを叩くだけです。
dotnet test Calculator.UITests.vbproj
これだけで、裏でアプリが自動起動し、テスト結果がコンソールにパス/フェイルとして出力されます。
6.2. CI環境(クラウド)で動かす際の超重要注意点!
「クラウド上のGitHub Actionsで動かしたら、UIテストが全部エラーになった!」というのは、自動化エンジニアが必ず一度は通る道です。
- 原因: GitHub Actionsなどの標準の仮想マシン(ランナー)は「非対話型(デスクトップ画面がない状態)」で動作しています。Windows Formsは画面(GUI)が描画されないとコントロールの生成に失敗するため、テストが動きません。
- 対策:
1. Self-hosted Runner(セルフホストランナー)を使用し、実際にWindowsデスクトップ画面がアクティブにログインされている物理PCまたはVM上でテストを実行する。
2. クラウド環境であれば、スクリーン解像度を設定し、インタラクティブモード(GUIセッションを維持する設定)でエージェントを起動する。
この「画面が必要である」という制約さえクリアすれば、夜中に自動で画面が動き、朝起きるとテストレポートが届いているという、極上の自動化ライフが実現します。
—
7. まとめ
お疲れ様でした!
手動での「ポチポチテスト」から脱却し、プログラムで画面を制御する第一歩を踏み出すことができましたね。
今回学んだ要素をおさらいしましょう。
1. `AutomationId` (Nameプロパティ) を一意に決めて、座標に依存しないテストを書く
2. `Using` 構文 を使って、テスト対象プロセスのライフサイクル(起動と終了)を完璧に管理する
3. `Thread.Sleep` や待機処理 を適切に挟み、環境のブレに強い頑健なテストにする
「ここをクリアすれば、Visual Basic (VB.NET) の基本はバッチリですよ」
UI自動化は、最初は少し難しく感じるかもしれませんが、一度作ってしまえば何百回、何千回もの退屈なテストをあなたの代わりに一瞬で終わらせてくれる「頼れる相棒」になります。ぜひ、ご自身のプロジェクトにもFlaUIを取り入れて、スマートで快適な開発ライフを送りましょう!
何か分からないことがあれば、いつでも頼れる先輩を頼ってくださいね。応援しています!
