質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.38%
C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

ユニットテスト

ユニットテストは、システムのテスト手法の一つで、個々のモジュールを対象としたテストの事を指します。対象のモジュールが要求や性能を満たしているか確認する為に実行します。

WPF

Windows Presentation Foundation (WPF) は、魅力的な外観のユーザー エクスペリエンスを持つ Windows クライアント アプリケーションを作成するための次世代プレゼンテーション システムです

Q&A

解決済

2回答

265閲覧

Codeer Friendlyを使ったC#WPFのユニットテストで、LabelのRaiseEventメソッドを呼び出すことってできますかね?

jiro.kaihatsu

総合スコア16

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

ユニットテスト

ユニットテストは、システムのテスト手法の一つで、個々のモジュールを対象としたテストの事を指します。対象のモジュールが要求や性能を満たしているか確認する為に実行します。

WPF

Windows Presentation Foundation (WPF) は、魅力的な外観のユーザー エクスペリエンスを持つ Windows クライアント アプリケーションを作成するための次世代プレゼンテーション システムです

1グッド

0クリップ

投稿2024/09/11 14:27

実現したいこと

Codeer Friendlyに入門しました。従来FlaUIを使ってユニットテストしていたのですが事情があってFriendlyに乗り換えようか検討中です。素晴らしいライブラリだと思うので乗り換えたいのですが、ある壁にぶつかっており乗り換えの決心がつかない状況です。掲題の課題が実現できるとありがたいのですが、実現できるか否か、実現できるならばどうすればいいか、アドバイスいただける方いらっしゃるでしょうか?

やりたいことは、テスト対象のLabelにMouse.MouseUpEventが投げられたように見せかけることです。

発生している問題・分からないこと

LabelのRaiseEventメソッドを呼び出してみようとしているのですが「'MouseButtonEventArgs' はシリアル化可能として設定されていません。」というエラーになってしまいます。

該当のソースコード

XAML

1<!-- テスト対象プログラム --> 2<Window x:Class="WpfApp1.MainWindow" 3 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 4 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 5 xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 6 xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 7 xmlns:local="clr-namespace:WpfApp1" 8 mc:Ignorable="d" 9 Title="MainWindow" Height="200" Width="300"> 10 <Grid> 11 <Button x:Name="button1" Content="length"> 12 <Button.ContextMenu> 13 <ContextMenu> 14 <Label x:Name="menu1" Content="ft" MouseUp="OnMouseUp"/> 15 <Label Content="m" MouseUp="OnMouseUp"/> 16 </ContextMenu> 17 </Button.ContextMenu> 18 </Button> 19 </Grid> 20</Window> 21

C#

1// テスト対象プログラム 2using System.Diagnostics; 3using System.Windows; 4using System.Windows.Input; 5 6namespace WpfApp1 7{ 8 /// <summary> 9 /// MainWindow.xaml の相互作用ロジック 10 /// </summary> 11 public partial class MainWindow : Window 12 { 13 public MainWindow() 14 { 15 InitializeComponent(); 16 } 17 18 private void OnMouseUp(object sender, MouseButtonEventArgs e) 19 { 20 Debug.WriteLine("OnMouseUp"); 21 } 22 } 23} 24

C#

1// ユニットテストのためのテスト対象プログラムのドライバ 2using System.Windows; 3using System.Windows.Controls.Primitives; 4using Codeer.Friendly.Windows.Grasp; 5using RM.Friendly.WPFStandardControls; 6 7namespace WpfControlLibrary.Tests 8{ 9 internal class WpfApp1Driver 10 { 11 public WindowControl MainWindow { get; private set; } 12 public IWPFDependencyObjectCollection<DependencyObject> LogicalTree { get; } 13 public WPFButtonBase Button1 { get; private set; } 14 15 public WpfApp1Driver(WindowControl w) 16 { 17 MainWindow = w; 18 LogicalTree = w.LogicalTree(); 19 20 var btn = LogicalTree.ByType<ButtonBase>().ByName("button1").Single(); 21 Button1 = new WPFButtonBase(btn); 22 } 23 } 24} 25

C#

1// ユニットテスト 2using Microsoft.VisualStudio.TestTools.UnitTesting; 3 4using Codeer.Friendly.Dynamic; 5using Codeer.Friendly.Windows; 6using Codeer.Friendly.Windows.Grasp; 7using RM.Friendly.WPFStandardControls; 8using System.Diagnostics; 9using System.Windows.Input; 10 11namespace WpfControlLibrary.Tests 12{ 13 [TestClass()] 14 public class WpfApp1Tests 15 { 16 private WindowsAppFriend _app; 17 private WindowControl _win; 18 private WpfApp1Driver _drv; 19 20 [TestInitialize] 21 public void Initialize() 22 { 23 var path = System.IO.Path.GetFullPath(@"..\..\..\WpfApp1\bin\Debug\WpfApp1.exe"); 24 _app = new WindowsAppFriend(Process.Start(path)); 25 _win = _app.IdentifyFromTypeFullName("WpfApp1.MainWindow"); 26 _drv = new WpfApp1Driver(_win); 27 } 28 29 [TestCleanup] 30 public void Cleanup() 31 { 32 _app.Dispose(); 33 34 Process process = Process.GetProcessById(_app.ProcessId); 35 process.CloseMainWindow(); 36 } 37 38 [TestMethod()] 39 public void WpfApp1Test_01() 40 { 41 _drv.Button1.EmulateClick(); 42 43 var contextMenus = _win.VisualTreeWithPopup().ByType("System.Windows.Controls.ContextMenu"); 44 var contextMenu = contextMenus[0]; 45 var labels = contextMenu.LogicalTree().ByType("System.Windows.Controls.Label"); 46 var label = new WPFContentControl(labels[0]); 47 Debug.WriteLine($"label text = {label.Content}"); 48 49 // これでは「MouseButtonEventArgs' はシリアル化可能として設定されていません。」になってしまう。どうすればLabelにMouse.MouseUpEventを通知できるのか? 50 label.Dynamic().RaiseEvent(new MouseButtonEventArgs(Mouse.PrimaryDevice, 0, MouseButton.Right) 51 { 52 RoutedEvent = Mouse.MouseUpEvent, 53 Source = this, 54 }); 55 } 56 } 57} 58

試したこと・調べたこと

  • teratailやGoogle等で検索した
  • ソースコードを自分なりに変更した
  • 知人に聞いた
  • その他
上記の詳細・結果

本家サイトを拝見したり、GoogleでCodeer Friendlyのサンプルプログラムをあさったりしたのですが、該当する例を見つけることができていません。

補足

特になし

TN8001😄を押しています

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

ベストアンサー

作者です。ご利用ありがとうございます。

前の方が書いてくれているように対象プロセスの中にMouseButtonEventArgsを生成する必要があります。Friendlyで対象プロセスのメソッドやプロパティの引数に渡せるものは以下のものです。

  • シリアライズ可能なもの
  • 対象プロセスの中のオブジェクト

MouseButtonEventArgsはシリアライズできないのでテストプロセスからWPFのプロセスへ引き渡すことができません。そのため対象プロセスの中に生成してそれを渡す必要があります。

この辺はややこしいのですが、Friendlyはプロセス越しにAPIを直接呼び出すのでそのオブジェクトがどちらのプロセスに存在するのか、どのように引き渡すのかがポイントになってきます。

それからやりたいことを実現する手段が他にもあるのでそれも書いておきます。
引き続き、ご利用よろしくお願いします。

テスト自動化支援サービスも弊社でやってますのでよろしければそちらもご利用ください。

cs

1[Test] 2[Apartment(ApartmentState.STA)] 3public void TestMethod1() 4{ 5 var app = new WindowsAppFriend(Process.GetProcessesByName("WpfApp1").First()); 6 var window = new WindowControl(app.Type<Application>().Current.MainWindow); 7 8 //右クリックはCodeer.Friendly.Windows.KeyMouseでエミュレート 9 var button1 = new WPFButtonBase(window.Dynamic().button1); 10 button1.Click(MouseButtonType.Right); 11 12 var contextMenus = window.VisualTreeWithPopup().ByType("System.Windows.Controls.ContextMenu"); 13 var contextMenu = contextMenus[0]; 14 var labels = contextMenu.LogicalTree().ByType("System.Windows.Controls.Label"); 15 var label = new WPFContentControl(labels[0]); 16 17 //①これがおそらく書きたかったもの 18 var primaryDevice = app.Type(typeof(Mouse)).PrimaryDevice; 19 var e = app.Type<MouseButtonEventArgs>()(primaryDevice, 0, MouseButton.Right); 20 e.RoutedEvent = app.Type(typeof(Mouse)).MouseUpEvent; 21 e.Source = label; 22 label.Dynamic().RaiseEvent(e); 23 24 //②Codeer.Friendly.Windows.KeyMouseでエミュレートしてもOK 25 label.Click(); 26 27 //③-1 直接呼ぶこともできます 28 window.Dynamic().OnMouseUp(label, e); 29 30 //③-2 特に引数つかってなかったらズルしてもいい 31 window.Dynamic().OnMouseUp(null, null); 32}

投稿2024/09/13 15:05

codeer-ishikawa

総合スコア28

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

jiro.kaihatsu

2024/09/13 20:46

ずばりの回答ありがとうございました。 やりたかったことがバッチリできました。感動です。 これでFlaUIから乗り換えられそうです。
codeer-ishikawa

2024/09/14 00:43

よかったっす。引き続きご利用よろしくお願います!
guest

0

LabelのRaiseEventメソッドを呼び出してみようとしているのですが「'MouseButtonEventArgs' はシリアル化可能として設定されていません。」というエラーになってしまいます。

この辺にさらっと書いてありますが、MouseButtonEventArgs(やパラメータ)を相手側で作ればいいようです(めんどくさw
Friendly/README 対象プロセス内でのインスタンス生成(Any OK)
Friendly/README static操作の呼び出し(Any OK)

やりたいことは、テスト対象のLabelにMouse.MouseUpEventが投げられたように見せかけることです。

そんなまどろっこしいことをするより、直接クリックすればいいのでは?
NuGet Gallery | Codeer.Friendly.Windows.KeyMouse
Codeer-Software/Friendly.Windows.KeyMouse: Emulate key and mouse operation.


xml:WpfApp1.MainWindow.xaml

1<Window 2 x:Class="WpfApp1.MainWindow" 3 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 4 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 5 Width="300" 6 Height="200"> 7 <Grid> 8 <Button x:Name="button1" Click="Button1_Click" Content="length"> 9 <Button.ContextMenu> 10 <ContextMenu> 11 <Label x:Name="menu1" Content="ft" MouseUp="OnMouseUp" /> 12 <Label Content="m" MouseUp="OnMouseUp" /> 13 </ContextMenu> 14 </Button.ContextMenu> 15 </Button> 16 </Grid> 17</Window>

cs:WpfApp1.MainWindow.xaml.cs

1using System.Windows; 2using System.Windows.Input; 3 4namespace WpfApp1 5{ 6 public partial class MainWindow : Window 7 { 8 public MainWindow() => InitializeComponent(); 9 10 private void OnMouseUp(object sender, MouseButtonEventArgs e) 11 => button1.Content = e.Source.ToString(); 12 13 private void Button1_Click(object sender, RoutedEventArgs e) 14 => button1.Content = "Button1_Click"; 15 } 16}

cs:WpfControlLibrary1.WpfApp1Driver.cs

1using Codeer.Friendly.Dynamic; 2using Codeer.Friendly.Windows; 3using Codeer.Friendly.Windows.Grasp; 4using RM.Friendly.WPFStandardControls; 5 6namespace WpfControlLibrary1 7{ 8 public class WpfApp1Driver 9 { 10 public WindowControl MainWindow { get; } 11 public WPFButtonBase Button1 => MainWindow.Dynamic().button1; 12 public WPFContentControl Menu1 => MainWindow.Dynamic().menu1; 13 14 public WpfApp1Driver(WindowControl w) => MainWindow = w; 15 } 16 17 public static class WpfApp1DriverExtensions 18 { 19 public static WpfApp1Driver AttachMainWindow(this WindowsAppFriend app) 20 => new WpfApp1Driver(app.WaitForIdentifyFromTypeFullName("WpfApp1.MainWindow")); 21 } 22}

cs:UnitTestProject1.WpfApp1Tests.cs

1using System.Diagnostics; 2using System.IO; 3using System.Windows.Input; 4using Codeer.Friendly.Dynamic; 5using Codeer.Friendly.Windows; 6using Codeer.Friendly.Windows.KeyMouse; 7using Microsoft.VisualStudio.TestTools.UnitTesting; 8using WpfControlLibrary1; 9 10namespace UnitTestProject1 11{ 12 [TestClass] 13 public class WpfApp1Tests 14 { 15 private WindowsAppFriend _app; 16 private WpfApp1Driver _drv; 17 18 [TestInitialize] 19 public void Initialize() 20 { 21 var path = Path.GetFullPath(@"..\..\..\WpfApp1\bin\Debug\WpfApp1.exe"); 22 _app = new WindowsAppFriend(Process.Start(path)); 23 _drv = _app.AttachMainWindow(); 24 } 25 [TestCleanup] public void Cleanup() => Process.GetProcessById(_app.ProcessId).CloseMainWindow(); 26 27 28 [TestMethod] 29 public void WpfApp1Test_01() 30 { 31 _drv.Button1.EmulateClick(); 32 Assert.AreEqual("Button1_Click", (string)_drv.Button1.Dynamic().Content); 33 34 var primaryDevice = _app.Type(typeof(Mouse)).PrimaryDevice; 35 var mouseUpEvent = _app.Type(typeof(Mouse)).MouseUpEvent; 36 var args = _app.Type<MouseButtonEventArgs>()(primaryDevice, 0, MouseButton.Right); 37 args.RoutedEvent = mouseUpEvent; 38 args.Source = _drv.Menu1; 39 _drv.Menu1.Dynamic().RaiseEvent(args); 40 41 Assert.AreEqual("System.Windows.Controls.Label: ft", (string)_drv.Button1.Dynamic().Content); 42 } 43 44 [TestMethod] 45 public void WpfApp1Test_02() 46 { 47 _drv.Button1.EmulateClick(); 48 Assert.AreEqual("Button1_Click", (string)_drv.Button1.Dynamic().Content); 49 50 _drv.Button1.Click(MouseButtonType.Right, 50, 50); 51 _drv.Menu1.Click(MouseButtonType.Left, 10, 10); 52 Assert.AreEqual("System.Windows.Controls.Label: ft", (string)_drv.Button1.Dynamic().Content); 53 } 54 } 55}

投稿2024/09/11 21:41

TN8001

総合スコア9727

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

TN8001

2024/09/11 21:41

ContextMenuには通常MenuItemを入れますが、Labelなのは何か理由があるのでしょうか?
jiro.kaihatsu

2024/09/12 14:14

テスト対象はソースを変更できないものなんです。理由は分かりませんが、MenuItemを使っていませんでした。MenuItemだとRM.Friendly.WPFStandardControls でEmulateClick()できるので楽なんですが。
TN8001

2024/09/12 14:38

> テスト対象はソースを変更できないものなんです。 なるほど触れないんですね^^; > MenuItemだとRM.Friendly.WPFStandardControls でEmulateClick()できるので楽なんですが。 わたしもそう思っていましたw KeyMouseはLabelだろうがクリックできて簡単でしたよ^^
jiro.kaihatsu

2024/09/13 20:49

迅速アドバイスありがとうございました。 アドバイスに基づき試していたのですが、使い方?文法が理解できていなくてもたもたしていたのですが、作者さんからずばり回答をいただきやりたかったことができるようになりました。 助かりました! (追伸) var primaryDevice = app.Type(typeof(Mouse)).PrimaryDevice; ができていませんでした。
TN8001

2024/09/13 21:52

> アドバイスに基づき試していたのですが、使い方?文法が理解できていなくてもたもたしていた 回答に対する疑問はすぐにコメントいただいて結構ですよ。 こっちも「回答のコメントだけ見て回答内容見てないのかな??」とやきもきしますのでw > 作者さんからずばり回答をいただきやりたかったことができるようになりました。 わたしも同じこと書いてますけどね^^; いやjiro.kaihatsuさんやcodeer-ishikawaさんに不満を垂れているわけではないですw 作者直々に回答があるならこの先も心強いですね^^ > (追伸) > var primaryDevice = app.Type(typeof(Mouse)).PrimaryDevice; > ができていませんでした。 これは「回答との差分が分かりずらくその行を飛ばしてしまった」という意味ですか?? 単刀直入な短い回答とエビデンスのある完動コードに分けるべきでしたかorz
jiro.kaihatsu

2024/09/15 09:07

恥ずかしながら、C#の文法を誤解していることに気付かず的外れな場所を調べてました。答えが分かった時は自分にガッカリしました
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.38%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問