Поделиться через


WPF SendKeys or mocking the keyboard in WPF

This post will only be interesting for the few of those who test WPF UI in-process (i.e. not through out-of-process UI automation frameworks such as White). When using in-process testing, the test lives in the same AppDomain as the code under test and has direct access to all the APIs such as UIElement.RaiseEvent.

With out-of-process testing, the test lives in a separate process from the application under test. In this case, the test sends the application automation requests (typically using the MSAA or the newer UI Automation library). These requests eventually end up going through the operating system's window messages. The downside of this approach is that since it almost fully emulates the user behavior, the tests are fragile because a sudden Windows Update dialog popup or a random message box from another application can steal the focus from the test application and confuse the test. That's why in-process tests are generally considered more reliable, since they will work even if the application is not focused or even not visible (in case of unit-test).

Those who have written tests using WinForms before are familiar with the helpful SendKeys class in System.Windows.Forms. It works by going through the operating system's SendInput function and provides good approximation of how the actual user's input would be routed through the system. SendKeys can be used for both in-process and out-of-process testing.

Another thing that WinForms has is the RaiseKeyEvent methods on Control with KeyEventArgs that easily allow you to mock keyboard events in-process, at the unit-testing level.

WPF does not provide any alternative to the SendKeys class. It does provide a RaiseEvent method, however the KeyEventArgs class in WPF was explicitly designed in such a way to prevent mocking the modifier keys state. We can see that many people are looking to call RaiseEvent from their tests and provide mock key and modifiers, however it seems that no solution is currently available. See for example this StackOverflow question: https://stackoverflow.com/questions/1263006/wpf-send-keys-redux The official guidance from the WPF team is to go through the operating system and either add a reference to System.Windows.Forms.dll to use SendKeys or directly use the SendInput API to mock the keyboard.

I've created a little project that works around this limitation and allows you to call RaiseEvent on your WPF controls from your unit-tests and fully mock the modifier key states (Ctrl, Alt, Shift). It implements the SendKeys DSL – a little mini-language to encode keystrokes. It does some very dirty reflection magic to workaround WPF's protection against mocking modifier key states, however it works and might be useful to some people. Warning: it is NOT a replacement for the WinForms SendKeys, it's a completely different thing.

While it is not recommended for unit tests, it can do a decent job for integration tests, when you actually show your application's UI. Chances that you need this library are very low, but if you happen to need it, then it's probably handy.

The source is at https://wpfsendkeys.codeplex.com

Comments

  • Anonymous
    August 26, 2011
    Hi Kirill How would sendkeys to a datagrid cell in wpf ? Thanks

  • Anonymous
    April 04, 2013
    I'm not sure why you're talking your project down so much. There are many, many, people who have been looking for something like this for a long time. It's great! Thanks!

  • Anonymous
    November 05, 2015
    michlg.wordpress.com/.../wpf-send-keys