diff --git a/docs/Advanced Topics/ContinuousIntegration.md b/docs/Advanced Topics/ContinuousIntegration.md new file mode 100644 index 00000000..514bb5c3 --- /dev/null +++ b/docs/Advanced Topics/ContinuousIntegration.md @@ -0,0 +1,24 @@ +--- +layout: layout +title: Continuous Integration +--- + +White drives the mouse and keyboard for it's automation, and only falls back to the automation API's when it can't use the mouse/keyboard. This simulates real world behavior more than using automation directly. +This means that White has to run on an UNLOCKED desktop. + +Here is a list of my setup requirements when I create a UI test agent: + + - The build agent running as a Console agent (both TFS and TeamCity support this) and set it to automatically start on boot + - Automatic logon setup (Use [SysInternals Autologon for Windows](http://technet.microsoft.com/en-us/sysinternals/bb963905.aspx) as it encrypts your password in the registry) + - Screensaver disabled + - Disable Windows Error Reporting. View on Gist: [DisableWER.reg](https://gist.github.com/JakeGinnivan/5131363) + - VNC installed and connect via VNC, *not remote desktop* + - When you connect using Remote desktop, then disconnect, the desktop will be locked, and UI Automation will fail + - Personally I use [Tight VNC](http://www.tightvnc.com/) with the [DFMirage driver](http://www.tightvnc.com/download.php) + - I also put a shortcut (cmd) which restarts the PC on the desktop `shutdown -r -t 0`. Useful for when you connect via Remote Desktop, you can then reboot, and auto login will make sure your test agent is good to go when it comes back up! + +Make sure that, while running these tests you would need to make sure that there aren't applications which would show windows while test is running. e.g. new chat message window coming up in restored or maximum mode. (I am not going into this here but there are ways to do this, like get the Yahoo Messenger new message window can be made to show as minimized). + +You might have issues running it in CI, if the server runs as windows service. Allowing the service to "interact with the desktop" might help. (This can be set from the service properties log-on tab) + +Please choose user version of windows instead of server versions. i.e. XP/Windows7 over Windows2003/Windows2008. The automation support for UIA is generally poor in server editions of windows. \ No newline at end of file diff --git a/docs/Advanced Topics/CustomUIItems.md b/docs/Advanced Topics/CustomUIItems.md new file mode 100644 index 00000000..2f0ff36b --- /dev/null +++ b/docs/Advanced Topics/CustomUIItems.md @@ -0,0 +1,54 @@ +--- +layout: layout +title: Custom UI Items +--- +Fundamentally all UIItems are either elementary (Label, e.g. having no other item in it) or composed of other UI Items. In white there is in-built support for standard UIItems. These are called standard mainly because of their prevalent use and ready availability in development environments. +When we use "third party controls", this might not be enough. Even though these UI Items are still made up of elementary items and can be automated by finding them individually. But we might miss some abstraction while doing this. Also we need build a lot of things in these items ourselves which are already done in white for other items. This is where Custom UI Item would be useful. + +Sample code of a Date control which consists of three text boxes for day, month and year. (See the inline comments) + + //Specify the ControlType which corresponds to the top level of Custom UI Item. + //White needs this when finding this item inside the window. + [ControlTypeMapping(CustomUIItemType.Pane)] + public class MyDateUIItem : CustomUIItem + { + // Implement these two constructors. The order of parameters should be same. + public MyDateUIItem(AutomationElement automationElement, ActionListener actionListener) + : base(automationElement, actionListener) + { + } + + //Empty constructor is mandatory with protected or public access modifier. + protected MyDateUIItem() {} + + //Sample method + public virtual void EnterDate(DateTime dateTime) + { + //Base class, i.e. CustomUIItem has property called Container. Use this find the items within this. + //Can also use SearchCriteria for find items + Container.Get("day").Text = dateTime.Day.ToString(); + Container.Get("month").Text = dateTime.Month.ToString(); + Container.Get("year").Text = dateTime.Year.ToString(); + } + } + +This is how it can be used. + MyDateUIItem myDateUIItem = window.Get("dateOfBirth"); + Assert.AreNotEqual(null, myDateUIItem); + myDateUIItem.EnterDate(DateTime.Today); + +If you have downloaded the source code you can find all of this in CustomItemTest.cs + +### What do I need to do when the CustomUIItem type is not specified is not defined in the source code already? +These are the places where you need to make the change. +1. Add your type in CustomUIItemType +1. Add the mapping to UIAutomation ControlType + + mappings[CustomUIItemType.Table] = System.Windows.Automation.ControlType.Table; + +### What happens to the extended controls? e.g. I extend TextBox in the code and use MyTextBox. +In such a case the it would remain as TextBox for white. + +## Subclassing CustomUIItems + - Since the object has to be constructed by white. You need to define the same constructors in the subclass. + - The CustomUIItem type attribute should be redefined in the subclass. \ No newline at end of file diff --git a/docs/Advanced Topics/Localisation.md b/docs/Advanced Topics/Localisation.md new file mode 100644 index 00000000..78ee2a96 --- /dev/null +++ b/docs/Advanced Topics/Localisation.md @@ -0,0 +1,32 @@ +--- +layout: layout +title: Localisation +--- +White uses text internally to find UIItems. These string differ based on locale. e.g. in Table(DataGrid) the header, row header etc, or scroll bars, are identified by some names given to them. These don't work in locales which are not english based. While doesn't provide all the locale values but allows you to configure these text. +In the app.config define sections as: + + + .... +
+ + + ... + + + + + +Like other configuration these can be set programmatically as well. + + UIItemIdAppXmlConfiguration.Instance. TableVerticalScrollBar = "Vertical Scroll Bar"; + +Configurable values are: + + TableVerticalScrollBar=Vertical Scroll Bar + TableHorizontalScrollBar=Horizontal Scroll Bar + TableColumn=Row + TableTopLeftHeaderCell=Top Left Header Cell + TableCellNullValue=(null) + TableHeader=Top Row + HorizontalScrollBar=Horizontal ScrollBar + VerticalScrollBar=Vertical ScrollBar \ No newline at end of file diff --git a/docs/Advanced Topics/MouseAndKeyboard.md b/docs/Advanced Topics/MouseAndKeyboard.md new file mode 100644 index 00000000..05c514fd --- /dev/null +++ b/docs/Advanced Topics/MouseAndKeyboard.md @@ -0,0 +1,16 @@ +--- +layout: layout +title: Mouse and Keyboard +--- + +## Using keyboard/mouse directly +Ideally you don't need to use these directly but if you do want to use. If you do want to use it then please use window.Keyboard and window.Mouse instead on instantiating a new window. The different between these two is that the use of Keyboard.Instance gives you raw keyboard and any operation performed on it would not wait till the window is busy. You can call window.WaitForInputIdle as well. + +Moving the mouse to a particular location + var point = new Point(100, 100); + mouse.Location = point; + +Moving the mouse to a particular UI Item + mouse.Location = uiItem.Bounds.Center(); //Please see the class RectX to see options of different locations to which a mouse can be moved. + +Sometimes you do not want to use mouse to be used for click and directly use the pattern provided by the UI Automation framework. You can use RaiseClickEvent event method on any UI Item as long as it supports InvokePattern. If it doesn't support the pattern then this would result in no-op. \ No newline at end of file diff --git a/docs/Advanced Topics/PositionBasedSearch.md b/docs/Advanced Topics/PositionBasedSearch.md new file mode 100644 index 00000000..d97114cb --- /dev/null +++ b/docs/Advanced Topics/PositionBasedSearch.md @@ -0,0 +1,29 @@ +--- +layout: layout +title: Position Based Search +--- + +### Speed up performance by Position based search + +Performance of finding UIItems (based on search criteria) is proportional to the number of items on a window. A UIItem is found by enumerating over all the controls in a window (at windows messages level, everything is a window, try spy++ to understand this better). Smaller the scope of faster would be search. Position based search is based on this idea. + +When finding a window from an application or another window you need to specify the identification of the window. This identification has to be unique as this is the identification for the cache. This cache is stored in the xml file. Duplicate identification would not cause any failures but you would not get benefit of position based search in such cases. This is how to do this. + + Window window = application.GetWindow("Customer - Foo", InitializeOption.NoCache.AndIdentifiedBy("Customer")); + +The identification is tied to the type of window and not instance of window. So even if I was doing this somewhere else in the code where my customer name is "Bar" I would do this. + + Window window = application.GetWindow("Customer - Bar", InitializeOption.NoCache.AndIdentifiedBy("Customer")); + +Similarly for modal windows same applies: + + Window modalWindow = window.ModalWindow("Address - Home", InitializeOption.NoCache.AndIdentifiedBy("Address")); + +You also need to do + + application.ApplicationSession.Save(); + +at the end of the test (or after killing the application). + +White remembers the position of UIItems on a window when you run your program for the first time and stores it on the file system as an xml file (see Configuration for setting the directory). In the next run it finds the UIItems based on the position of UIItem which is very fast because there is only one item at the point. If the item is not found at the position it would perform the normal search. +The position which is saved in xml file is relative to the window, hence change in position of window doesn’t affect position based find. Changes in layout of items in a window are taken care of by overwriting the position when it changes. You need to delete these files when you switch to new version of white. After first run they would be cached again. \ No newline at end of file diff --git a/docs/Advanced Topics/SearchDepth.md b/docs/Advanced Topics/SearchDepth.md new file mode 100644 index 00000000..d45913d8 --- /dev/null +++ b/docs/Advanced Topics/SearchDepth.md @@ -0,0 +1,16 @@ +--- +layout: layout +title: Controlling Search Depth +--- + + - UI Automation provides two approach for querying the UIAutomation tree of an automation element. + - Search on automation element tree: In this search the API user specifies the criteria and scope of the search. The scope is of two levels children or descendant. This is simpler API as the user doesn't need to match against every element. + +Search during automation element tree navigation: In this search the user is provided with tree navigation calls which the she can use to search the elements among other things. This provides complete freedom to the user at the cost of simplicity of API. +White until release 0.19 used only the first approach. With 0.20 one can configure search based on tree navigation using the RawElementBasedSearch property in Configuration file. This property is used along with MaxElementSearchDepth property which indicates the depth of navigation, white should perform when using this mode. Hence, if you have a very deep tree but you hope to find your UI Items within 4 levels then you can set RawElementBasedSearch=true and MaxElementSearchDepth=4, and this would perform much better than when RawElementBasedSearch=false. Like most other configuration this can be set programmatically using CoreAppXmlConfiguration.Instance. + + CoreAppXmlConfiguration.Instance.RawElementBasedSearch = true; + CoreAppXmlConfiguration.Instance.MaxElementSearchDepth = 2; + var listView = window.Get("listView"); + // or any of other execution in white would use search depth of 2 + CoreAppXmlConfiguration.Instance.RawElementBasedSearch = false; // white starts using regular search \ No newline at end of file diff --git a/docs/Advanced Topics/ThirdPartyControls.md b/docs/Advanced Topics/ThirdPartyControls.md new file mode 100644 index 00000000..a25aca8a --- /dev/null +++ b/docs/Advanced Topics/ThirdPartyControls.md @@ -0,0 +1,17 @@ +--- +layout: layout +title: Third Party Controls +--- + +White provides support for all the controls which comes with standard .NET libraries. This support is partially just abstraction over UIAutomation and window messages. So, in case of third party controls like DevExpress, PureComponents etc, there are no standard UIItem implementation in white which you can use out of the box. The reason being the automation element structure beneath is unique to each of them. These Custom UI Item can be plugged in to white. +While implementing these you might face issues. Some known issues and possible resolution is provided below. Soon we would have a sample for each of them available here: + +## Do not rely on UISpy +UISpy comes along with .NET SDK. Please do not trust UISpy, it doesn't tell everything even for standard controls. You can use LogStructure() method to see what is present inside the control. This method is available on all the UIItems including window. It prints out the entire UIA tree which is helpful, if you are having problem finding UIItems. The structure would be logged in log file (and console if configured) as configured in log4net Configuration. +A lot of people on the white forums have been successful with http://www.codeplex.com/UIAutomationVerify for the same. + +## Silverlight +Some of the controls http://msdn.microsoft.com/en-us/library/cc645045(VS.95).aspx?ppud=4 which come with silverlight do not have built-in support for UIAutomation. Hence white cannot recognize them. + +## Focusing the UIItem +...using Focus method, sometimes activates the UIAutomation to fetch the internal elements. \ No newline at end of file diff --git a/docs/Advanced Topics/UIAv3.md b/docs/Advanced Topics/UIAv3.md new file mode 100644 index 00000000..cd415941 --- /dev/null +++ b/docs/Advanced Topics/UIAv3.md @@ -0,0 +1,25 @@ +--- +layout: layout +title: UIA v3/COM Api +--- +White will soon be running against the [UIA COM Wrapper](https://github.com/JakeGinnivan/UIAComWrapper) which means that White can support and will expose UI patterns for Virtualisation, and also add support for WinRT applications. + +# Breaking Changes +Unfortunately, this will not be a perfectly clean upgrade. There are many small behavior differences, and some more fundamental changes. + +For example, SWA would return a control type of `document` for a multi-line textbox in Windows forms, in the COM UIA Api the control type that is exposed is `edit`. But WPF will still have a control type of This means that with the UIA Com wrapper, a multi-line textbox in WPF you would use the MultiLineTextBox control in White, but in WinForms you would just use TextBox. +There are a number of different controls which have changed slightly, and I will do my best to document changes below. + +## Behavior changes + - Combo-box items no longer are visible to UIA while closed + +## Control changes +A few controls will change, for these changes, White will throw meaningful exceptions along the lines of + + The MultiLineTextBox control is no longer supported in Winforms due to a change in UIA 3.0, please use the TextBox or WinFormTextBox instead. + +### Conversion list + +Windows Forms: + - MultiLineTextBox -> TextBox + - ListView -> ListBox \ No newline at end of file diff --git a/docs/Advanced Topics/Waiting.md b/docs/Advanced Topics/Waiting.md new file mode 100644 index 00000000..b63442be --- /dev/null +++ b/docs/Advanced Topics/Waiting.md @@ -0,0 +1,98 @@ +--- +layout: layout +title: Handling waiting in White +--- + +White strives to eliminate any need whatsoever for doing Thread.Sleep and retry in your test programs. So if you find yourself doing these things in your program, please use any one applicable options below. If you don't find it, please raise an issue. + +1. When any action is performed white automatically waits till the window can respond again to next action. One of the thing white does during this is to call windowPattern.WaitForInputIdle on the parent window of the UI item on which the action is performed. In cases where the window would be closed as a result of the action performed, this call would throw exception internally, depending on timing of the call. The caller doesn't have to worry about this as this exception is trapped. +All of this happens by default, without having to configure anything. + +2. Wait based on presence of hour glass. This can be configured by using WaitBasedOnHourGlass property (default value true). This ensures that the test would wait till the cursor remains in hour-glass or default-and-hour-glass. When configured it would happen for each and every action. It is very common in applications to not use hour glass to provide feedback to the user when the application is busy. It is highly recommended to do this, as WaitWhileBusy call on the process object in .NET is not reliable at all. + +3. There are cases where the above two strategy aren’t enough and hence white provides its own wait mechanism. In this test program waits until the certain condition matches. As soon as the condition matches it would return. There is maximum wait duration. This duration can be configured by setting BusyTimeout property. + +There are other places where you need to set the timeout (all in milli seconds set to some defaults). + + Property Description + PopupTimeout Timeout period for finding a popup + TooltipWaitTime Maximum duration in within which tooltip would appear (see Tool tip problem) + SuggestionListTimeout Timeout period for finding a suggestion list on a textbox + UIAutomationZeroWindowBugTimeout Timeout till any window is found for an application. There is a bug in UIAutomation because of which it sometimes doesn’t find windows for a process + +For configuring above have a look at the Configuration section +Timeout means the upper time limit of search. White keeps trying till this time, after every 100 ms. +Custom wait hook + +In addition to wait provided by default by white, as mentioned above. From release 0.20 onwards you can also hook in custom wait mechanism. This hook gets called every time after the above wait checks are performed. In this hook you can wait for your conditions to finish. This is useful if your wait scenarios are quite pervasive and you have put in this check at lot of places in your test. + +Steps to hook you custom wait: +Implement the interface White.Core.Configuration.IWaitHook. +Implement the WaitFor method in it to wait for as long as your test requires. White passed in the UIItemContainer (most of the time this is just the window) object to provide the context of call. e.g. you can wait till you can find a UI Item in this container. +Set the wait hook by setting CoreAppXmlConfiguration.Instance.AdditionalWaitHook value + +A note on the custom wait hook: + +For the hook to work CoreAppXmlConfiguration.Instance.AdditionalWaitHook has to be set to the object implementing the IWaitHook interface, e.g: + + public class CustomWait : IWaitHook + { + public CustomWait() + { + CoreAppXmlConfiguration.Instance.AdditionalWaitHook = this; + } + + // Implementation of the IWaitHook interface + public void WaitFor(UIItemContainer uiItemContainer) + { + ... + } + } + +**Note:** IWaitHook is quite heavy handed, it checks after every action (which for a single logical action, there may be multiple internal actions). This can make it rather slow. See the next section for some other techniques + +## Handling asynchronous/background work (WPF) +I tend to use the UI automation HelpText to tell White that my application is busy, this approach is not supported by White out of the box, so you will have to put it in yourself. These code samples are for WPF, but the technique can be used in other UI Frameworks + +First, you want to create an attached property: + + public static class BusyAutomationBehaviour + { + public static readonly DependencyProperty IsApplicationBusyProperty = + DependencyProperty.RegisterAttached("IsApplicationBusy", typeof (bool), typeof (BusyAutomationBehaviour), new PropertyMetadata(OnChanged)); + + private static void OnChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + AutomationProperties.SetHelpText(d, GetIsApplicationBusy(d) ? "Busy" : string.Empty); + } + + public static void SetIsApplicationBusy(DependencyObject element, bool value) + { + element.SetValue(IsApplicationBusyProperty, value); + } + + public static bool GetIsApplicationBusy(DependencyObject element) + { + return (bool) element.GetValue(IsApplicationBusyProperty); + } + } + +You can attach this on your main Window, then bind it to a property which is true when your application is busy. Now this requires your application to know when it is busy, so I hope you have made this a cross cutting concern in your app. + + + +Then in your [Screen](wiki\ScreenPattern) you can have a `WaitWhileBusy` helper. + + public void WaitWhileBusy() + { + Retry.For(ShellIsBusy, isBusy => isBusy, TimeSpan.FromSeconds(30)); + } + + bool ShellIsBusy() + { + var currentPropertyValue = WhiteWindow.AutomationElement.GetCurrentPropertyValue(AutomationElement.HelpTextProperty); + return currentPropertyValue != null && ((string)currentPropertyValue).Contains("Busy"); + } + +I hope to expand this article later. \ No newline at end of file diff --git a/docs/Advanced Topics/index.md b/docs/Advanced Topics/index.md new file mode 100644 index 00000000..6025c2e2 --- /dev/null +++ b/docs/Advanced Topics/index.md @@ -0,0 +1,6 @@ +--- +layout: layout +title: Advanced Topics +--- + +If you would like to know more about how White works, or set it up on a build server this is the place for you \ No newline at end of file diff --git a/docs/ChangeLog.md b/docs/ChangeLog.md new file mode 100644 index 00000000..9b87c19b --- /dev/null +++ b/docs/ChangeLog.md @@ -0,0 +1,77 @@ +--- +layout: layout +title: Change Log +order: 9 +--- + +## Version 0.11.0 +### Namespace Change +White Namespace changed from White.Core to TestStack.White + +Run `Fix-WhiteNamespaces` in the nuget powershell console to automatically fix up namespace errors + +### Documentation Site +Documentation available at [http://teststack.azurewebsites.net/](http://teststack.azurewebsites.net/) + + - **Enhancement**: x64 Support added. You can now compile your project as AnyCPU! + - **Enhancement**: Improved API of Slider + - **Enhancement**: Better Custom controls support for WPF + - **Fixed**: Cannot find multiline textbox in Win32 apps + - **Fixed**: Unable to Find Win32 modal window + - **Fixed**: Drag/Drop sometimes pausing until the mouse is moved + - **Fixed**: Better expanding/collapsing of Win32TreeView + - **Fixed**: Expandable lists now restore their previous expansion (after the items have been retrieved), if `ComboBoxItemsPopulatedWithoutDropDownOpen` is set to false + - **Fixed**: Automating GridView for non-English locals + - **Fixed**: Heaps of other little bugs fixed around selection/scrolling fixed + - **Fixed**: Unable to click one Menu items twice + - **BREAKING**: ModalWindow now throws when the window cannot be found + - **BREAKING**/Enhancement: **MultiLineTextBox no longer exists**, simply use TextBox + - **TestStack.White.ScreenObjects** released on NuGet + +Thanks to all the contributors who helped make v0.11.0. + +## Version 0.10.3 + - Some small updates to WPF Get extension methods + - Further tooltip fixes + +## Version 0.10.2 + - Made ListItem selection more reliable + +## Version 0.10.1 + - Fix: Tooltips can now be found as expected + - Retry.ForDefault method now reads it's default timeout from White's configuration + - New Configuration value 'FindWindowTimeout' which is defaulted to 30 seconds + - Added ability to take screenshots of the desktop: + - `Desktop.CaptureScreenshot()` returns a Bitmap + - `Desktop.TakeScreenshot(string filename, ImageFormat imageFormat)` saves the screenshot to file + +## Version 0.10.0 + - BREAKING: Removed Log4net, now using Castle's logging abstractions. See https://github.com/TestStack/White/wiki/log4net-Removal + - BREAKING: SearchCriteria.ByControlType now takes WindowsFramework rather than string + - BREAKING: WindowsFramework members renamed to Is[Framework] from [Framework] + - Fix: Lots of combobox updates/fixes + - Fix: AsContainer() could throw a NullReferenceException + - Fix: Checkbox fixes + - Fix: Added support for WPF DatePicker + - All exceptions are now serialisable + +Version 0.10.0 removed the log4net dependency in TestStack.White, we now rely on [Castle.Core's Logging abstractions](http://old.castleproject.org/services/logging/index.html). + +By default White uses the `ConsoleFactory` which will cause all logging to be directed to the console, which most unit test frameworks and build servers will pick up. + +To set your own simply override the logger factory in White's configuration. + + CoreAppXmlConfiguration.Instance.LoggerFactory = new Log4netFactory(); + +By removing this hard dependency you can use whatever logging framework you would like with White. + +## Version 0.9.3 + - **BREAKING**: White is now compiled as x86 (fixes issues when run in x64 process) + - **BREAKING**: White will no longer throw TargetInvocationExceptions in some cases, instead it will throw the real, unwrapped exception + - Added support for swapping mouse buttons (for left handed users/system setup) - Accessible via configuration + +## Version 0.9.2 + - **BREAKING**: UIItem.Get now throws an AutomationException when the UI Element is not found + - **Change**: UIItem.Get now auto retries to fetch the item + - **FIX**: Added small delay when fetching menu items (to compensate for menu animation in newer versions of windows) + - **FIX**: AttachOrLaunch method now can accept a full Path. \ No newline at end of file diff --git a/docs/Configuration.md b/docs/Configuration.md new file mode 100644 index 00000000..a8fdd2f2 --- /dev/null +++ b/docs/Configuration.md @@ -0,0 +1,65 @@ +--- +layout: layout +title: Configuration +order: 5 +--- + +##NOTE: This section needs revisiting and is likely out of date + +Configuration +White configuration is done in App.config file. You need to setup configSections, sectionGroup and section. Here is an example of how to do this, with the default values for them. In case any property value is not specified these values would be used. + + + +
+
+ + +
+ + + + + + + + + + + + + + + + +### WorkSessionLocation +Location where the WindowItemsMap is stored as xml. WindowItemsMap is create to Speed up performance by Position based search. + +### PopupTimeout, TooltipWaitTime, SuggestionListTimeout, BusyTimeout, WaitBasedOnHourGlass, UIAutomationZeroWindowBugTimeout, TooltipWaitTime +Checkout, [Wait handling](/White/Advanced%20Topics/Waiting.html) + +### ComboBoxItemsPopulatedWithoutDropDownOpen +In certain situations the combo box item properties are not reflected in the Automation Elements unless the combo box Drop down is opened once. This poses problem for white to do actions which require white to search for items by text. In order to get around this situation white always opens and closes the Drop down when a combo box item is constructed. This can have slight performance over head and can be annoying. This configuration property can be used to avoid doing this. As in most cases such problems don't exist, the default value for this configuration is true. + +### RawElementBasedSearch +Read [Search depth](/White/Advanced%20Topics/SearchDepth.html). + +### MaxElementSearchDepth +Read [Search depth](/White/Advanced%20Topics/SearchDepth.html). Applicable only when RawElementBasedSearch=true. + +### MoveMouseToGetStatusOfHourGlass +In order to check whether application is busy (processing the last action or not) white moves the mouse to top-left-corner of screen. This doesn't work in few cases, when application is not maximized and top left corner takes the mouse outside the application window, when the application under test controls the mouse pointer appearance based on its position. In such cases this property can set to false. + +### DragStepCount +When using drag and drop this specifies the number of steps in which drag should be performed. Default value is one step, which means that mouse location is changed from source to destination in one go. + +### DoubleClickInterval +White doesn't have any sleep for between two clicks of a mouse. But such waits can be introduced using this property. White also uses this property to ensure that the drag and drop operations do not result in double click. The value is in milliseconds. + +All of these properties can be configured via program as well. Sample code which in order to read/update these values. The configured values are logged when you run white programs. + + Console.WriteLine(CoreAppXmlConfiguration.Instance.PopupTimeout); + CoreAppXmlConfiguration.Instance.TooltipWaitTime = 100; + +WorkSessionLocation specifies the location for storing UIItem position file +For description of other properties look at the Wait Handling section \ No newline at end of file diff --git a/docs/FAQ.md b/docs/FAQ.md new file mode 100644 index 00000000..c39ca6d4 --- /dev/null +++ b/docs/FAQ.md @@ -0,0 +1,57 @@ +--- +layout: layout +title: FAQ +order: 10 +--- + +1. **Would there be support for Web Application testing?** +Because there are already a lot of good tools which do this, developing it is not under consideration at this point of time. Look at Selenium, Sahi, Watir, Watin and Watij for testing web applications. + +1. **Silverlight is more like rich client why should white not support it?** +White Supports Silverlight, but currently there are no tests confirming it's stability. The Silverlight support definitely needs work (and tests), but is not a priority at the moment. + +1. **I am not able to find any items inside ToolStrip and MenuStrip (or DataGrid)** +If you running NUnitConsole without /nothread option then you should try that out. [http://www.codeplex.com/white/WorkItem/View.aspx?WorkItemId=3603](http://www.codeplex.com/white/WorkItem/View.aspx?WorkItemId=3603) +Else, +There is a known issue with UIAutomation and ToolStrip/MenuStrip support. Please search for "UIAutomation menustrip" in google for more on this. +Try changing the ApartmentState to STA and see if that helps. In order to change this you would need to edit the app.config file for the test. See the Configuration page. + +1. **I am unable to find window, primary UIItem or secondary UIItem, what might be wrong?** +Please perform `LogStructure()` on the parent UIItem (i.e. Desktop, Window and PrimaryUIItem) to find out the descendant automation elements. Warning: while doing this at the desktop level please make sure you do not have too many un-necessary windows open as it might take a long time to log everything. + +1. **I have multiple UIItems of the same type which has same id and text. How can I retrieve them?** +In such cases generally the mechanism of indexing is preferable as that is how the user relates to them. It is explained here: (Getting Started)[/White/GettingStarted,html] + +1. **I am using WPF and I have nested controls inside my control. Since this is not a standard control structure how do I automate this best with white.** +Please have a look at the WPF Items section on UI Items page. + +1.** I have to put sleeps and wait-for-conditions in my tests. What is the way to get around it?** +Please read the Wait Handling to understand how white works. There are a lot of applications which are built without using wait cursor (hour glass) to provide user feedback when the application is busy. This is true in the initial stages of the project, where wait notification to use is done as an after thought. If wait feedback is provided right in the application under test then white would handle it as well. This should be done in the application not for automation but the user in first place. White currently doesn't handle custom wait cursors, this would be implemented in coming releases. + +1. **Can white test run in the same process as the application?** +No. White is not designed to work in this mode as this can cause threading issues. All in principle it is not a good idea to couple test code with application under test code as they would evolve independent from each other. + +1. **My control (e.g. Button) is embedded inside a panel/group box. Do I need to first get hold of the containing control first and then get the button from it?** +No you do not need to do that. You can directly get the button. This applies to all primary controls. See ControlTypeToUIItemMapping for list of primary UIItems. + +1. **White support for office or any windows application.** +White is based on UIAutomation for finding controls in a window. So the strength of automation support provided by white is equal to UIAutomation. This can be checked easily by using UISpy. The UIAutomation support is best on Windows 7, so you should use that when checking with UISpy. (e.g. ribbon controls are supported by UIAutomation). There is another route to automation if you intend to run a plugin inside the application. Since the plugin is .NET based you can leverage the power of Custom Commands to drive automation. + +1. **If you are windows 7 and facing some issues automating menus** +Then have a a look at following link: [http://www.microsoft.com/download/en/details.aspx?displaylang=en&id=13821](http://www.microsoft.com/download/en/details.aspx?displaylang=en&id=13821) + +1. **When the process I am testing crashes, I expect White to fail. How can I do this?** +First off, you need to disable Windows Error Reporting, view [this GIST](https://gist.github.com/JakeGinnivan/5131363) for details +Then if you handle the process exited event, you can check the error code and throw an exception to fail your test. + +1. I** have asynchronous or background processes running in my app, how can I wait without using Thread.Sleep()** +This is a complex subject with many scenarios and many solutions. +Head to the [Waiting](/White/Advanced%20Topics/Waiting.html) page for some help. + +1. **What is the difference between System.Windows.Automation and the COM UIA Api?** +White was written against the .net managed automation API (Refered to as SWA from now on) which is under the System.Windows.Automation namespace. This managed wrapper has custom behaviours over the COM Api, but does not support many new automation patterns added in Windows 7 & 8. +Read more [here](/White/Advanced%20Topics/UIAv3.html) + +1. **I use my mouse left handed and have my mouse buttons swapped in Windows** +Simply add the below code to your test setup +`CoreAppXmlConfiguration.Instance.InvertMouseButtons = !System.Windows.Forms.SystemInformation.MouseButtonsSwapped;` \ No newline at end of file diff --git a/docs/GettingStarted.md b/docs/GettingStarted.md new file mode 100644 index 00000000..09da671e --- /dev/null +++ b/docs/GettingStarted.md @@ -0,0 +1,97 @@ +--- +layout: layout +title: Getting started with White +order: 1 +--- + +### Pre-requisites +.NET 4.0 framework + +## Getting Started +1. Install via NuGet +`> install-package TestStack.White` +1. Have a look at the [WPF](https://github.com/TestStack/White/tree/master/src/Sample%20App/Wpf) or [WinForms](https://github.com/TestStack/White/tree/master/src/Sample%20App/WinForms) sample projects +1. Have a look at Whites UI Tests, White has automated tests for most controls to prevent regressions in the codebase. These serve as a great example of how to automate different controls. See [White's UI Tests](https://github.com/TestStack/White/tree/master/src/TestStack.White.UITests/ControlTests) +1. Download [http://uiautomationverify.codeplex.com/](http://uiautomationverify.codeplex.com/) which is an ESSENTIAL tool when doing UI Automation work. +1. Start writing tests, first off you require a unit testing framework like xUnit or nUnit. See below for a basic walkthrough +1. Join the mailing list at [https://groups.google.com/forum/#!forum/teststack_white](https://groups.google.com/forum/#!forum/teststack_white) +1. Report issues at [https://github.com/TestStack/White/issues?state=open](https://github.com/TestStack/White/issues?state=open) +1. If you would like to contribute back, read [Contributing](/Contributing.html) to learn how to get started contributing back! + +## Writing your first test + +### Start off with an empty test stub + +In *MSTest*: + + [TestClass] + public class MyTests + { + [TestMethod] + public void MyFirstUITest() + { + } + } + +In *NUnit*: + + [TestFixture] + public class MyTests + { + [Test] + public void MyFirstUITest() + { + } + } + +In *xUnit*: + + public class MyTests + { + [Fact] + public void MyFirstUITest() + { + } + } + +### Get hold of a window +First you need to determine the correct path of the application you want to test. + +In *MSTest*: + + var applicationDirectory = TestContext.TestDeploymentDir + +In *NUnit*: + + var applicationDirectory = TestContext.CurrentContext.TestDirectory; + +Then you create a new instance of your application + + var applicationPath = Path.Combine(applicationPath, "foo.exe"); + Application application = Application.Launch(applicationPath); + Window window = application.GetWindow("bar", InitializeOption.NoCache); + +White uses the UI Automation API (UIA) to find controls on a window. UIA communicates to a displayed window via window messages. This find is performed by iterating through all the controls in a window. + +### Finding a UI Item and performing action + + Button button = window.Get