Windowsアプリケーションのテスト

そうか、Windowsアプリのウインドウとかコンポーネントも単なるクラスだから、大抵の内容なら普通にテストができるんだ…。Webアプリ脳なので何かSeleniumみたいなものが必要なのかと漠然と思い込んでた。

こんな適当なWindowsアプリケーションがあったら

using System;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Windows.Forms;

namespace WindowsApplication1
{
    // デザイナは省略
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        // "button1" という Button が押されたときのイベント
        private void button1_Click(object sender, EventArgs e)
        {
            // "textBox1" という TextBox に値を設定
            textBox1.Text = "ボタンが押されました";
        }

        // "textBox1" のテキストが変化したときのイベント
        private void textBox1_TextChanged(object sender, EventArgs e)
        {
            // "checkBox1" という CheckBox をトグル
            checkBox1.Checked = !checkBox1.Checked;
        }
    }
}

強引に内部を蹂躙。

using System;
using System.Reflection;
using System.Windows.Forms;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            WindowsApplication1.Form1 f = new WindowsApplication1.Form1();

            // コンポーネントを取得
            TextBox textBox1 = GetField(f, "textBox1") as TextBox;
            CheckBox checkBox1 = GetField(f, "checkBox1") as CheckBox;
            Console.WriteLine("最初の状態: TextBox={0}, CheckBox={1}", textBox1.Text, checkBox1.Checked);

            // ボタン押したときのイベントを起こす
            Button button1 = GetField(f, "button1") as Button;
            CallMethod(f, "button1_Click", button1, null);
            Console.WriteLine("ボタン押下後: TextBox={0}, CheckBox={1}", textBox1.Text, checkBox1.Checked);
        }

        static object CallMethod(object o, String name, params object[] args)
        {
            MethodInfo mi = o.GetType().GetMethod(name, BindingFlags.NonPublic | BindingFlags.Instance);
            return mi.Invoke(o, args);
        }

        static object GetField(object o, String name)
        {
            FieldInfo fi = o.GetType().GetField(name, BindingFlags.NonPublic | BindingFlags.Instance);
            return fi.GetValue(o);
        }
    }
}

こういうのをNUnitなりと組み合わせればテストできそうだけど、本当にこれでいいんだろうか。普通どうやるんだろう?