2014年10月2日木曜日

UI オートメーションで自動テスト その2

UI オートメーションの続きです。

前回は、テスト対象のアプリケーションを起動して UI オートメーション要素を取得するところまでを実装しました。
今回は、テキストボックスに文字列を自動入力する処理を実装したいと思います。

自動入力って響きがいいですね。
入力するテストパターンがたくさんあるときは、かなり有効です。

まずは、テスト対象の実装から始めます。

2014年9月18日木曜日

UI オートメーションで自動テスト その1

UI オートメーションを使うと、UI の自動テストができるらしい。

それってスゴイ便利じゃん!
ってことで調べてみました。

UI オートメーションには、4つのコンポーネントがあるみたいです。

  • UIAutomationClient
  • UIAutomationClientsideProviders
  • UIAutomationProvider
  • UIAutomationTypes

今回は、UIAutomationClient と UIAutomationTypes を参照設定に追加して始めます。

2014年9月11日木曜日

StyleCop の警告をエラーに変更

C# で開発をするときは StyleCop を使っています。
コードの標準化ができて可読性が上がってます。

でも、警告なので無視も可能。
エラーにする方法はないかな。。。

2014年8月28日木曜日

Form アプリで、二重起動を禁止する

前回は、WPF アプリの二重起動を禁止する方法を調べました。

前回の記事:
WPF アプリで、二重起動を禁止する

今回は、フォームアプリを調べてみました。

2014年8月21日木曜日

WPF アプリで、二重起動を禁止する

WPF アプリケーションで二重起動を禁止するにはどうすればいいのだろう?
よく使いそうな機能なので覚えておくと使えそう。 

調べたら、Mutex クラスを使えばいいことがわかりました。

2014年7月10日木曜日

ボタン用 ViewModel の作成

今回も Livet を使った MVVM ネタです。

ViewModel を書いていると同じことをたくさん書くので疲れます。
で、今回は ViewModelCommand でボタン用の ViewModel を作成してみました。

using System;
using Livet;
using Livet.Commands;

/// <summary>
/// <see cref="System.Windows.Controls.Button"/> の ViewModel の機能を提供します。
/// </summary>
public class ButtonViewModel : ViewModel
{
    #region Private fields

    /// <summary>
    /// コンテンツ。
    /// </summary>
    private object content;

    /// <summary>
    /// コマンド。
    /// </summary>
    private ViewModelCommand command;

    /// <summary>
    /// コマンドが実行可能かどうかの値。
    /// </summary>
    private bool canExecute;

    /// <summary>
    /// コマンドが実行可能かどうかが変化したことを自動通知するかどうかの値。
    /// </summary>
    private bool autoRaiseCanExecuteChanged;

    /// <summary>
    /// コマンドが実行するメソッド。
    /// </summary>
    private Action execute;

    #endregion // Private fields

    #region Constructors

    /// <summary>
    /// <see cref="ButtonViewModel"/> クラスの新しいインスタンスを初期化します。
    /// </summary>
    /// <param name="execute">コマンドが実行するメソッド。</param>
    /// <exception cref="ArgumentNullException"><c>execute</c> が null です。</exception>
    public ButtonViewModel(Action execute)
        : this(execute, true, true)
    {
    }

    /// <summary>
    /// <see cref="ButtonViewModel"/> クラスの新しいインスタンスを初期化します。
    /// </summary>
    /// <param name="execute">コマンドが実行するメソッド。</param>
    /// <param name="canExecute">コマンドが実行可能かどうかの値。</param>
    /// <exception cref="ArgumentNullException"><c>execute</c> が null です。</exception>
    public ButtonViewModel(Action execute, bool canExecute)
        : this(execute, canExecute, true)
    {
    }

    /// <summary>
    /// <see cref="ButtonViewModel"/> クラスの新しいインスタンスを初期化します。
    /// </summary>
    /// <param name="execute">コマンドが実行するメソッド。</param>
    /// <param name="canExecute">コマンドが実行可能かどうかの値。</param>
    /// <param name="autoRaiseCanExecuteChanged">コマンドが実行可能かどうかが変化したことを自動通知するかどうかの値。</param>
    /// <exception cref="ArgumentNullException"><c>execute</c> が null です。</exception>
    public ButtonViewModel(Action execute, bool canExecute, bool autoRaiseCanExecuteChanged)
    {
        if (execute == null)
        {
            throw new ArgumentNullException("execute");
        }

        this.execute = execute;
        this.canExecute = canExecute;
        this.autoRaiseCanExecuteChanged = autoRaiseCanExecuteChanged;
    }

    #endregion // Constructors

    #region Properties

    /// <summary>
    /// コンテンツを取得または設定します。
    /// </summary>
    public object Content
    {
        get { return this.content; }
        set
        {
            if (value != this.content)
            {
                this.content = value;
                this.RaisePropertyChanged(() => this.Content);
            }
        }
    }

    /// <summary>
    /// コマンドを取得します。
    /// </summary>
    public ViewModelCommand Command
    {
        get
        {
            return this.command = this.command ??
                new ViewModelCommand(this.execute, () => this.CanExecute);
        }
    }

    /// <summary>
    /// コマンドが実行可能かどうかの値を取得または設定します。
    /// </summary>
    public bool CanExecute
    {
        get { return this.canExecute; }
        set
        {
            if (value != this.canExecute)
            {
                this.canExecute = value;
                this.RaisePropertyChanged(() => this.CanExecute);

                if (this.AutoRaiseCanExecuteChanged)
                {
                    this.RaiseCanExecuteChanged();
                }
            }
        }
    }

    /// <summary>
    /// コマンドが実行可能かどうかが変化したことを自動通知するかどうかの値を取得または設定します。
    /// </summary>
    public bool AutoRaiseCanExecuteChanged
    {
        get { return this.autoRaiseCanExecuteChanged; }
        set
        {
            if (value != this.autoRaiseCanExecuteChanged)
            {
                this.autoRaiseCanExecuteChanged= value;
                this.RaisePropertyChanged(() => this.AutoRaiseCanExecuteChanged);
            }
        }
    }

    #endregion // Properties

    #region Public methods

    /// <summary>
    /// コマンドを実行します。
    /// </summary>
    public void Execute()
    {
        if (this.command != null)
        {
            this.Command.Execute();
        }
    }

    /// <summary>
    /// コマンドが実行可能かどうかが変化したことを通知します。
    /// </summary>
    public void RaiseCanExecuteChanged()
    {
        if (this.command != null)
        {
            this.command.RaiseCanExecuteChanged();
        }
    }

    #endregion // Public methods
}

最低限必要なプロパティを実装しました。
おまけで、RaiseCanExecuteChanged メソッドの実行を制御するプロパティを用意。

使う側の MainWindowViewModel.cs はこんな感じで実装します。

public MainWindowViewModel()
{
    this.CopyButton = new ButtonViewModel(this.CopyAction)
    {
        Content = "コピー",
    };
}

public ButtonViewModel CopyButton { get; private set; }

private void CopyAction()
{
}

最後は、xaml です。

<Button Command="{Binding Path=CopyButton.Command}"
        Width="75"
        Height="24"
        Margin="3"
        HorizontalAlignment="Right"
        Content="{Binding Path=CopyButton.Content" />

バインドする名前が長くなってしまうのが難点だけど、ViewModel がスッキリできました。


頑張りすぎず脱力系でいこうと思います。
以上。

2014年7月3日木曜日

Levet で MVVM の基本

お久しぶりです。
1ヶ月以上の開いてしまいました。

今回は、前回の Livet を使った簡単な MVVM のサンプルを作りたいと思います。

機能は TextBox に入力した文字列を別の TextBox にコピーするだけ。
とても、シンプルです。

画面はこんな感じ。(UI のセンスがありません)



では、はじめます。

Visual Studio Express 2013 を立ち上げたら、「Livet WPF4.5 MVVM アプリケーション」を選んでプロジェクトを作成します。

MainWindowVIewModel.cs を開いてたら、TextBox 用のプロパティを2つ追加します。


private string inputText;

public string InputText
{
    get { return this.inputText; }
    set
    {
        if (value != this.inputText)
        {
            this.inputText = value;
            this.RaisePropertyChanged(() => this.InputText);
        }
    }
}

private string outputText;

public string OutputText
{
    get { return this.outputText; }
    private set
    {
        if (value != this.outputText)
        {
            this.outputText = value;
            this.RaisePropertyChanged(() => this.outputText);
        }
    }
}

次にコピーの処理を追加します。

private void CopyAction()
{
    this.OutputText = this.InputText;
}

最後にボタン用のコマンドを追加します。

private ViewModelCommand copyCommand;

public ViewModelCommand CopyCommand
{
    get
    {
        return this.copyCommand = this.copyCommand ??
            new ViewModelCommand(this.CopyAction);
    }
}

MainWindow.xaml を開いてコントロールを追加します。

<Window x:Class="Kaznagamine.LivetSample.Views.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
        xmlns:ei="http://schemas.microsoft.com/expression/2010/interactions"
        xmlns:l="http://schemas.livet-mvvm.net/2011/wpf"
        xmlns:v="clr-namespace:Kaznagamine.LivetSample.Views"
        xmlns:vm="clr-namespace:Kaznagamine.LivetSample.ViewModels"
        Title="MainWindow" Height="300" Width="400">
    <Window.DataContext>
        <vm:MainWindowViewModel/>
    </Window.DataContext>
    <Grid>
        <StackPanel Orientation="Horizontal">
            <TextBox Text="{Binding Path=InputText}"
                     Width="120"
                     Height="23"
                     Margin="3"
                     TextAlignment="Right" />
            <Button Command="{Binding Path=CopyCommand}"
                    Width="75"
                    Height="24"
                    Margin="3"
                    HorizontalAlignment="Right"
                    Content="コピー" />
            <TextBox Text="{Binding Path=OutputText}"
                     Width="120"
                     Height="23"
                     Margin="3"
                     TextAlignment="Right"
                     IsReadOnly="True"/>
        </StackPanel>
    </Grid>
</Window>

ビルドして実行したら、左の TextBox に文字列を入力してボタンを押します。
右の TextBox に同じ文字列が表示されたら完成です。


頑張りすぎず脱力系でいこうと思います。
以上。