ささいなことですが。

Windowsアプリテスト自動化ライブラリFriendly開発者の日記です。

Friendlyハンズオン 1.用意

これは「Friendly Advent Calendar 2014 - Qiita」の記事です。

今日からは連載形式でハンズオンやってみようかなーって思います。
詳細なドキュメントは公式ページも参照しながらでお願いします。
テスト自動化 Friendly - 株式会社Codeer (コーディア)

今日やること

Frienldyはまだ出てこないです。

1.操作対象のアプリ作成
2.テストプロジェクト作成
3.テストプロジェクトからアプリを起動して終了

操作対象のアプリを作成。

WinFormsアプリでやります。
WPFでもできますよ。
そちらが好みの場合はそうしてください。
f:id:ishikawa-tatsuya:20141208003939p:plain

テスト作成

単体テストで作ります。
まあ、やることはシステムレベルなんですけど、テストフレームワークとしてはこれで十分です。
f:id:ishikawa-tatsuya:20141208003941p:plain

名前変更

まあ、そのままでもいいのですが、ちょっと名前を変えておきます。
f:id:ishikawa-tatsuya:20141208011249p:plain

はい、TargetFormTest.csを開くと以下のものができています。

[TestClass]
public class TargetFormTest
{
    [TestMethod]
    public void TestMethod1()
    {
    }
}

Target.exeを起動して、閉じるコードを書き加える。

ユニットテストの流儀にしたがって書いてみます。
ユニットテストの多くのフレームワークでは、
・テストのセットアップ
・テストの本文
・後片付け
っていう書き方をします。
なのでセットアップで起動して後片付けで閉じるようにします。
まずは、その空関数を書きます。

[TestClass]
public class TargetFormTest
{
    [TestInitialize]
    public void TestInitialize()
    {
    }

    [TestCleanup]
    public void TestCleanup()
    {
    }
    
    [TestMethod]
    public void TestMethod1()
    {
    }
}

では、動きを見てみましょう。
メソッドにブレイクポイントを設定した後
TestMethod1の関数内で右クリックメニューから「テストのデバッグ」を選択してください。
f:id:ishikawa-tatsuya:20141208004554p:plain

そうすると、
TestInitialize

TestMethod1

TestCleanup
の順番で呼び出されます。

では、次にプロセスの起動と終了コード書きます。
この処理に使うのはProcessクラスです。
このクラスは.Netの標準のクラスで、プロセス操作に関する処理が実装されています。
これはMSDNを参照お願いします。
Process クラス (System.Diagnostics)
このクラスは別プロセスをテストするときには頻出のクラスなので使い方を覚えておくと良いです。

Startメソッドは起動するアプリのパスを指定します。
今回は、相対パス書くの面倒なので、参照して、同一フォルダに入れることにします。
f:id:ishikawa-tatsuya:20141208004553p:plain
f:id:ishikawa-tatsuya:20141208004551p:plain

そしてコードはこのように書き換えてください。

using System;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System.Diagnostics;
using System.Threading;

namespace Test
{
    [TestClass]
    public class TargetFormTest
    {
        Process _process;

        [TestInitialize]
        public void TestInitialize()
        {
            _process = Process.Start("Target.exe");
            while (_process.MainWindowHandle == IntPtr.Zero)
            {
                _process.Refresh();
                Thread.Sleep(10);
            }
        }

        [TestCleanup]
        public void TestCleanup()
        {
            _process.CloseMainWindow();
            _process.WaitForExit();
        }

        [TestMethod]
        public void TestMethod1()
        {

        }
    }
}

ここで、ポイントは以下のコードですね。
_process.MainWindowHandleに値が入るまで待っています。
これが必要なのはもちろんテストプロセスと操作対象プロセスが異なるからですね。
起動してもすぐにはメインウィンドウはできていません。

while (_process.MainWindowHandle == IntPtr.Zero)
{
    _process.Refresh();
    Thread.Sleep(10);
}

ちなみに、

_process.WaitForInputIdle();
_process.Refresh();

では、待ちが不十分な場合があります。
例えば、このコードを上の部分の前に付け足しても、
ループの中に入ります。
(つまり、メインウィンドウがセットされないタイミングで処理を返す)
この待ち方が固いです。

実行

これで、またテストを実行すると、プロセスが実行されて、終了します。
右クリックメニューから「実行」を選ぶ
f:id:ishikawa-tatsuya:20141208070020p:plain

一瞬起動して
f:id:ishikawa-tatsuya:20141208070023p:plain

すぐに終了
f:id:ishikawa-tatsuya:20141208070022p:plain


はい、今日はFriendly全然でてきませんでしたねw

明日に続く・・・