1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

FriendlyでE2Eテストを書いてみて、子メニューが取れずに苦戦

Last updated at Posted at 2020-11-27

Windowsデスクトップアプリ(WPF)のE2Eテストを書きたくて、Friendlyに出会った。これが個人的に最も直感的だった。

詰まった点としては、Friendlyというより、WPFのLogicalTreeとVisualTreeの挙動というところにあると思われるので、同じこと悩んでる人がいたらいいなと思って、書きます。

メニューを動的に組んでいるケースでハマった

ログイン者に応じて、メニューを動的に切り替える仕組みを採用していて、そのXAMLがこんな感じです。

MainWindow.xaml

    <Grid Background="#FFF2F0DF">
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto" />
            <RowDefinition Height="*" />
        </Grid.RowDefinitions>
        <Menu ItemsSource="{Binding GlobalMenu}">
            <Menu.ItemContainerStyle>
                <Style TargetType="{x:Type MenuItem}">
                    <Setter Property="Command" Value="{Binding DataContext.NavigateCommand, 
                        RelativeSource={RelativeSource FindAncestor,
                            AncestorType={x:Type view:MainWindow}}}"/>
                    <Setter Property="CommandParameter" Value="{Binding Value}"/>
                </Style>
            </Menu.ItemContainerStyle>
            <Menu.ItemTemplate>
                <HierarchicalDataTemplate DataType="{x:Type local:MainMenuModel}" ItemsSource="{Binding Path=Children}">
                    <TextBlock Text="{Binding Text}"/>
                </HierarchicalDataTemplate>
            </Menu.ItemTemplate>
        </Menu>
        <ContentControl prism:RegionManager.RegionName="ContentPage" Grid.Row="1" />
    </Grid>

システムを起動した直後は、GlobalMenunullなので、LogicalTreeには何も無い。Bindingによって、GlobalMenuに値がセットされると、階層構造に従ったメニューが構成されます。HierarchicalDataTemplateがそれで、値をバインドすればこういうメニューが作られます。

├── メニューA
   ├── メニューA1
   ├── メニューA2
   ├── メニューA3
├── メニューB
   ├── メニューB1
   ├── メニューB2
   ├── メニューB3
├── メニューC
   ├── メニューC1
   ├── メニューC2
   ├── メニューC3

この「メニューA1」等をクリックしたくて、試行錯誤したコードがこれ。

    [TestClass]
    public class MenuTest
    {
        private WindowsAppFriend _app;
        private WindowControl w;

        [TestInitialize]
        public void TestInitialize()
        {
            var path = System.IO.Path.GetFullPath("hoge.exe");
            _app = new WindowsAppFriend(Process.Start(path));
            w = _app.FromZTop();
        }
        [TestMethod]
        public void Testメニュー開け()
        {
            AppVar main = _app.Type<Application>().Current.MainWindow;
            var globalmenu = main.VisualTree().ByType<MenuItem>(); //Countすると3
            new WPFMenuItem(globalmenu[0]).EmulateClick(); //メニューAがクリックされる
            var uuum = globalmenu[0].visualTree().ByType<MenuItem>().Count; //これが0になるのが辛い
        }
    }
}

親のメニュー(メニューA,メニューB,メニューC)は、VisualTreeを辿ったら取れるのに、子供のMenuが取れないのはなんでなんだろう。

とりあえずなんですけど、VMから直接コマンド飛ばして逃げたが、良くないねこれは。

var hoge = main.Dynamic().DataContext; //MainViewModelのVM
hoge.NavigateCommand.Execute("Page1");

キーイベント関係をどうしよう

ボタンを押すサンプルが転がっているが、キーイベント関連があまりなかった。
このコードで出来たんだけど、いいのかな。何か間違ってないよね。

System.Windows.Forms.SendKeys.SendWait("{ENTER}");
  • テキストボックスのReturnキー押下
  • モーダルで上げたWindowのボタン押下
  • DataGridのセル内キーイベント押下と右クリック
  • DataGridにチェックを付ける

コードでUIが操作できると楽しいので、がんばる。

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?