八葉の日記

日々、感じたことをまとめる場として利用する

めも

Humble Object at XUnitPatterns.com


Example: Humble Dialog

Many development environments let us build the user interface
visually by dragging and dropping various visual objects ("widgets")
onto a canvas.
多くの開発環境では、さまざまなビジュアルオブジェクト(「ウィジェット」)を
キャンバスにドラッグアンドドロップすることで、ユーザーインターフェイスを視覚的に
構築できます。

They let us add behavior to these visual objects by selecting one of
the possible actions or events specific to that visual object and typing
logic into the code window the IDE presents us with.
これらのビジュアルオブジェクトには、ビジュアルオブジェクトに固有の可能なアクション
またはイベントの1つを選択し、IDEが提示するコードウィンドウにロジックを入力することによって、
ビジュアルオブジェクトにビヘイビアを追加できます。

This logic may involve invoking the application behind the user interface or it
may involve modifying the state of this or other visual objects.
このロジックは、ユーザインタフェースの背後でアプリケーションを呼び出すことを伴い得るか、
またはこのまたは他の視覚的オブジェクトの状態を変更することを含み得る。

Visual objects are very hard to test efficiently because they are tightly coupled
to the presentation framework that invokes them.
ビジュアルオブジェクトは、それらを呼び出すプレゼンテーションフレームワークに密接に結合されて
いるため、効率的にテストすることは非常に困難です。

The test would need to simulate that environment to provide the visual object with
all the information and facilities it requires.
テストでは、ビジュアルオブジェクトに必要なすべての情報と機能を提供するために、その環境を
シミュレートする必要があります。

This makes testing very complicated, so much so that many development teams don't
bother testing the presentation logic at all.
これはテストを非常に複雑にするので、多くの開発チームはプレゼンテーションロジックのテストを
全く気にしません。

This leads to Production Bugs caused by untested code and Untested Requirements.
これは、テストされていないコードとテストされていない要件によって引き起こされるProduction Bugsに
つながります。

To create the Humble Dialog, we extract all the logic from the view component into
a non-visual component that is testable via synchronous tests.
ハンブルダイアログを作成するために、ビューコンポーネントからロジックのすべてを非同期テストで
テスト可能な非ビジュアルコンポーネントに抽出します。

If this component needs to update the view object's (the Humble Dialog's) state, the Humble Dialog is passed in as an argument.
このコンポーネントがビューオブジェクト(ハンブルダイアログ)の状態を更新する必要がある場合、ハンブルダイアログが引数として渡されます。

When testing the non-visual component, we typically replace the Humble Dialog with a Mock Object that is configured with the indirect input values and the expected behavior (indirect outputs.)
非ビジュアルコンポーネントをテストするときは、通常、間接入力値と予想される動作(間接出力)で構成されたモックオブジェクトをハンブルダイアログに置き換えます。

In some GUI frameworks, where the Humble Dialog has to register itself with the framework for each event it wishes to see, the non-visual component can register itself instead of the Humble Dialog (as long as that doesn't introduce unmanageable dependencies on the context) and this makes the Humble Dialog even simpler because these events go directly to the non-visual component and require no delegation logic
Humble Dialogが見たい各イベントのフレームワークに自分自身を登録しなければならないGUIフレームワークでは、非ビジュアルコンポーネントは、ハンブルダイアログの代わりに自身を登録することができます。コンテキスト)、これらのイベントは非ビジュアルコンポーネントに直接移動し、委譲ロジックを必要としないため、Humble Dialogをさらに単純化します

The following code sample is from a VB view component (.ctl) with some non-trivial logic.
次のコードサンプルは、VBのビューコンポーネント(.ctl)のロジックです。

It is part of a custom plug-in we built for Mercury Interactive's TestDirector tool.
Mercury InteractiveのTestDirectorツール用に作成したカスタムプラグインの一部です。

///////////////////////////////////////////////////////////////////////////////
' Interface method, TestDirector will call this method
' to display the results.Public Sub ShowResultEx(TestSetKey As TdTestSetKey, _ TSTestKey As TdTestKey, _
ResultKey As TdResultKey)
Dim RpbFiles As OcsRpbFiles
Set RpbFiles = getTestResultFileNames(ResultKey)
ResultsFileName = RpbFiles.ActualResultFileName
ShowFileInBrowser ResultsFileName
End Sub

Function getTestResultFileNames(ResultKey As Variant) _ As OcsRpbFiles
On Error GoTo Error
Dim Attachments As Collection
Dim thisTest As Run
Dim RpbFiles As New OcsRpbFiles
Call EnsureConnectedToTd
Set Attachments = testManager.GetAllAttachmentsOfRunTest(ResultKey)
Call RpbFiles.LoadFromCollection(Attachments, "RunTest")
Set getTestResultFileNames = RpbFiles
Exit Function
Error: ' do something ...End Function
Example VbViewWithLogic embedded from VB6/HumbleDialog-Not/ResultViewerPane.ctl
///////////////////////////////////////////////////////////////////////////////

=========================================================
Ideally, we would like to test the logic but we are unable to construct the objects passed in as parameters because they don't have public constructors.
理想的には、ロジックをテストしたいのですが、パブリックコンストラクタを持たないため、渡されたオブジェクトをパラメータとして構築することはできません。

Passing in objects of some other type isn't possible either because the types of the function parameters are hard-coded to be specific concrete classes.
関数のパラメータの型が特定の具象クラスにハードコードされているため、他の型のオブジェクトを渡すことはできません。

We can do an Extract Testable Component (page X) refactoring on the executable to create the testable component leaving behind just the Humble Dialog as an empty shell.
テスト可能なコンポーネントを作成して空のシェルとしてHumble Dialogだけを残すように、実行可能ファイルに対してTestable Component(page X)のリファクタリングを行うことができます。

This typically involves doing several Extract Method refactorings (already done in the original example to make the refactoring easier to understand), one for each chunk of logic that we want to move.
これには、通常、リファクタリングを理解しやすくするために元の例で行っていたいくつかの抽出メソッドリファクタリングを実行します。これは、移動するロジックの各チャンクに対して1つです。

We then do an Extract Class refactoring to create our new testable component class.
その後、Extract Classリファクタリングを実行して、新しいテスト可能コンポーネントクラスを作成します。
The Extract Class refactoring may include both Move Method[Fowler] refactorings and Move Field[Fowler] refactoring to move the logic and the data it requires from the Humble Dialog to the new testable component.
エクストラクトクラスリファクタリングには、Moveメソッド[Fowler]リファクタリングとMove Field [Fowler]リファクタリングの両方が含まれており、必要なロジックとデータをハンブルダイアログから新しいテスト可能コンポーネントに移動できます。
Here's the same view converted to a Humble Dialog:
ここでは、同じビューをハンブルダイアログに変換します:

///////////////////////////////////////////////////////////////////////////////
' Interface method, TestDirector will call this method
' to display the results.Public Sub ShowResultEx(TestSetKey As TdTestSetKey, _ TSTestKey As TdTestKey, _
ResultKey As TdResultKey)
Dim RpbFiles As OcsRpbFiles
Call EnsureImplExists
Set RpbFiles = Implementation.getTestResultFileNames(ResultKey)
ResultsFileName = RpbFiles.ActualResultFileName
ShowFileInBrowser ResultsFileName
End Sub

Private Sub EnsureImplExists() If Implementation Is Nothing Then Set Implementation = New OcsScriptViewerImpl
End If
End Sub
Example VbViewAsHumbleDialog embedded from VB6/HumbleDialog/ResultViewerPane.ctl
///////////////////////////////////////////////////////////////////////////////

以下は、ハンブルオブジェクトが呼び出すテスト可能なコンポーネントOcsScriptViewerImplです:
///////////////////////////////////////////////////////////////////////////////
' ResultViewer Implemenation:
Public Function getTestResultFileNames(ResultKey As Variant) _ As OcsRpbFiles
On Error GoTo Error

Dim Attachments As Collection
Dim thisTest As Run
Dim RpbFiles As New OcsRpbFiles
Call EnsureConnectedToTd
Set Attachments = testManager.GetAllAttachmentsOfRunTest(ResultKey)
Call RpbFiles.LoadFromCollection(Attachments, "RunTest")
Set getTestResultFileNames = RpbFiles
Exit Function
Error: ' do something ...End Function
///////////////////////////////////////////////////////////////////////////////

We could now instantiate this OcsScriptViewerImpl class easily and write VbUnit tests for it.
I've omitted the tests for space reasons because they don't really show anything particularly interesting.
このOcsScriptViewerImplクラスを簡単にインスタンス化し、VbUnitテストを作成することができます。私はスペースの理由でテストを省略しました。なぜなら、特に面白いことは何も実際に表示していないからです。