こんにちは!エンジニアリングの世界へようこそ。今日は、Windows Forms(WinForms)開発において多くの人が頭を悩ませる「UIとビジネスロジックの癒着」を断ち切り、プロフェッショナルなテスト自動化を実現するための極意をお伝えします。
「ボタンを押したら計算して画面を書き換える」――この直感的なコーディングは、規模が大きくなるにつれて保守地獄への片道切符となります。UIの裏側にある「ロジック層」を綺麗に分離し、NUnitとMoqを使ってテストを自動化する方法を、一緒にマスターしていきましょう!
ここをクリアすれば、あなたのVB.NETスキルは一段と洗練されたものになりますよ。バッチリ解説していきますね。
—
1. なぜWindows Formsのテストは難しいのか?
Windows Formsのデフォルトのコードスタイルは、フォームクラスの中に画面の描画処理もデータベースへのアクセスも、計算処理もすべてが詰め込まれがちです。
‘ 【アンチパターン】すべてが混ざり合ったレガシーなフォーム
Public Class MainForm
Private Sub btnCalculate_Click(sender As Object, e As EventArgs) Handles btnCalculate.Click
‘ 入力値の取得、ビジネスロジック、DB接続、画面描画が1箇所に…
Dim input As Integer = Integer.Parse(txtInput.Text)
Dim result As Integer = input 2 ‘ 複雑なビジネスロジックのつもり
lblResult.Text = result.ToString()
End Sub
End Class
このコードの何が問題か分かりますか?そう、「画面(UI)を起動しないとロジックのテストができない」のです。自動テストでは画面の裏でボタンをポチポチ押すわけにはいきません。
これを解決するのが、MVP(Model-View-Presenter)パターンやMVVMパターンといった設計思想です。今回は、WinFormsと相性の良い「Presenter(プレゼンター)パターン」を用いたリファクタリングを実践します。
—
2. テスト可能な構造へリファクタリングする
UIとロジックを切り離すための合言葉は、「画面はただの愚直な表示装置(View)に徹し、脳みそ(Presenter)を外に出す」です。
① Viewのインターフェース化
まずは、フォームが実装すべき「契約(Interface)」を定義します。これにより、Presenterは本物のフォームの代わりに「テスト用のモック(偽物)」と会話できるようになります。
‘ 画面が持っているべき振る舞いの定義
Public Interface IMainView
Property InputText As String
Property ResultText As String
Event CalculateRequested As EventHandler
End Interface
② Presenter(ロジック層)の作成
次に、画面の操作を受け取って計算を行い、結果をViewに返すPresenterを作成します。ここにはWindows Formsのコントロール(`TextBox`や`Button`など)は一切登場しません。純粋なVB.NETのクラスです。
Public Class MainPresenter
Private ReadOnly _view As IMainView
‘ コンストラクタインジェクション(Viewを外から注入する)
Public Sub New(view As IMainView)
_view = view
‘ Viewからのイベントを購読する
AddHandler _view.CalculateRequested, Address OnCalculateRequested
End Sub
‘ ビジネスロジックの本丸
Public Sub OnCalculateRequested(sender As Object, e As EventArgs)
Dim inputVal As Integer
If Integer.TryParse(_view.InputText, inputVal) Then
Dim result As Integer = PerformBusinessLogic(inputVal)
_view.ResultText = result.ToString()
Else
_view.ResultText = “無効な入力です”
End If
End Sub
‘ 独立したビジネスロジック(テスト対象!)
Public Function PerformBusinessLogic(input As Integer) As Integer
‘ 例:2倍する複雑な計算
Return input 2
End Function
End Class
—
3. NUnitとMoqによる単体テストの自動化
ロジックがPresenterに綺麗に分離されたことで、ついにNUnitとMoqを使った単体テストが書けるようになります。
- NUnit: テストを実行・検証するためのフレームワーク。
- Moq: インターフェースの「偽物(モック)」を簡単に作り出すライブラリ。
以下のテストコードを見てください。画面を1ミリも起動せずに、ロジックが正しく動くかを検証できます。
Imports NUnit.Framework
Imports Moq
Public Class MainPresenterTests
Public Sub CalculateRequested_ValidInput_UpdatesResultCorrectly()
‘ 1. 準備 (Arrange)
‘ IMainViewのモック(偽物)を作成
Dim mockView = New Mock(Of IMainView)()
‘ ユーザーが “21” と入力した状態をシミュレート
mockView.Setup(Function(v) v.InputText).Returns(“21”)
‘ PresenterにモックViewを渡してインスタンス化
Dim presenter As New MainPresenter(mockView.Object)
‘ 2. 実行 (Act)
‘ 計算イベントを手動で発火させる
mockView.Raise(Sub(v) v.CalculateRequested += Nothing, EventArgs.Empty)
‘ 3. 検証 (Assert)
‘ ResultTextプロパティに “42” が代ったことが書き込まれたか?を検証
mockView.Verify(Sub(v) Set ResultText(“42”), Times.Once())
End Sub
End Class
これぞプロの技です!UIの描画を待つ必要がないため、このテストは一瞬(数ミリ秒)で完了します。
—
4. CI/CDパイプライン(GitHub Actionsなど)への組み込み
ローカルPCでテストが通るようになったら、次は「人間が実行しなくても、コードをプッシュするだけで自動でテストが走る仕組み(CI/CD)」を作りましょう。
GitHub Actionsなどを利用する場合のワークフローの設定イメージは以下の通りです。
1. リポジトリにコードがプッシュされる。
2. サーバー上で `dotnet test` コマンドが実行される。
3. すべての単体テストがグリーン(成功)になればビルド成功。
4. もしバグが混入してテストが赤(失敗)になれば、自動的にデプロイやプルリクエストがブロックされる。
.github/workflows/dotnet.yml のイメージ
name: .NET Core Test
on:
push:
branches: [ main ]
jobs:
build:
runs-on: windows-latest # Windows FormsのテストにはWindows環境が必要
steps:
- uses: actions/checkout@v3
- name: Setup .NET
uses: actions/setup-dotnet@v3
with:
dotnet-version: ‘6.0.x’ # または対象の.NETバージョン
- name: Restore dependencies
run: dotnet restore
- name: Build
run: dotnet build –no-restore
- name: Test
run: dotnet test –no-build –verbosity normal
このパイプラインがあることで、「うっかり既存の機能を壊してしまった」というミスをデプロイ前に100%検知できるようになります。
—
まとめ
今回は、Windows Formsにおける「レガシーなUIとロジックの分離」、そして「NUnitとMoqを用いたユニットテストの自動化」、さらに「CI/CDパイプライン連携」までの一連の流れを駆け足で解説しました。
- UIとロジックを分離(MVPパターン)することで、テストが書ける構造に生まれ変わる。
- Moqを使ってViewを模倣し、画面なしでPresenterの動作を高速に検証する。
- CI/CDによって品質の番人を自動化する。
Visual Basic (VB.NET) だって、現代的な設計ときちんとしたテスト手法を取り入れれば、モダンなC#アプリケーションに負けない堅牢なシステムを構築できます。
ここをクリアすれば、あなたのVB.NETスキルはもう初学者ではありません。胸を張って「プロのアーキテクト」と名乗りましょう!
次回の解説もお楽しみに!
