During one of the Pluralsight study group nights, we came across a problem when we test angular websites that make Ajax calls to switch templates in a Single page application. To repro the scenario we created a simple website that did nothing more then showing on the main page an button and hocking up that button with an event to switch the page with an second page, using an Ajax call.
The pages look like follows:
After clicking the button you will see
The code looks like this:
Now the CodedUI test we ran looks like follows:
We launch the browser, Search for the button, then click the button. On the new page we search for the HtmlEdit box and read out it’s value.
Now this test works great as long as the Index.js file contains the following line to switch the page:
If we use an Ajax call by using the following code then the second page will not be shown in the browser. So it looks like the click is not executed.
What happens is that codedUI injects java scrip the moment it starts a browser test. This script is used to enable codedUI to wait for Ajax calls to complete and coordinate other timing related things.
Unfortunately this script seems to interfere with the standard way Angular is handling Ajax calls and therefore breaks your site.
Now the big question is how can we solve this?
Fortunately there is a simple solution. You can add an App.config file to your codedUI test project inside this config file you specify a configuration key called WebWaitForReadyLevel and set its value to 3. So your config file must contain the following xml:
Of course this has as side effect that CodedUI will not test the ready level of controls, so in order to ensure you can interact with controls you might need to add some control flow logic to the code to wait for controls to appear like e.g. the WaitforControlEnabled or WaitForControlExists that are available on all the test controls you use.
In my previous post I showed primarily how you can select elements based on the ng-* attributes when using CodedUI. In this post I will complete the scenario on how we can test the sample application created by my colleague MVP Maurice de Beijer, who is an Angular expert.
The scenario we will walk through is the following:
Goto the site http://rawstack.azurewebsites.net/, Click on the Admin link, enter a movie in the filter box, Click on one row and then read out the audience score value and assert on the value.
Below you see the steps including the screenshots so you can follow along the steps how to implement this.
Goto the site and click the Admin link
Enter text in the filter box:
Click the row with the entered text we are searching for:
Now check if the value in the text box is 94
So what are the steps we need to code in CodedUI
.We need to get started with going to the Url and then click in the admin link. this is done with the following steps:
The next step is that we want to find the filter box, as described int he previous post. The challenge we have here is that this box is not available right away. What happens is that the site goes out with an Ajax request to get a list of data and when the data is returned shows the grid with the data and the text box where we can type the filter text.
To show progress the page has an progress indicator that shows an Ajax request is ongoing and this indicator is hidden the moment the Ajax call is done.
We can make use of this to wait for the call to complete. We do this using the WaitForControlNotExisits call on the TestControl. This is done as follows:
So now we have filtered down the list to the number of items we are looking for and next is to find the correct row we want to click
This part is a bit tricky, since only selecting the Span that contains the text item and clicking it, will not yield the right results. If you look at the table structure for the grid you see it has multiple div’s and you need to actually select the row div that contains the click handler to trigger the click that a user would normally trigger. If you look with the F12 tools on any of the browsers you will see the following structure:
So to find the correct row we can simply use the power of CodedUI searches. We only need to add two SearchProperties to find the correct div and then we can click it. We need to search for both the InnerText and the CssClass on the Div and use the PropertyExpressionOperator.Contains. The code for this is as follows:
After clicking the row we now will see the admin page for this row and we can finally search for the audienceScore input. This control has an Id, so the search for that is very simple and robust. Reading out the value and then asserting on that is nothing more then reading the Text property and asserting on that value. The code for that is as follows:
The solution I showed here works cross browser, so by just setting the BrowserWindow.CurrentBrowser = “crome” or “firefox” you can run this test also on chrome or Firefox with the same results.
Last week we hosted the first of a series of Pluralsight Study group meetings at our company Xpirit together with the DotNed user group. The study group focuses on the new training I just got published on pluralsight called “Testing Web Applications with CodedUI”.
In the first few chapters we covered last week we looked at how the CodedUI object model works and as one of the hands on assignments we thought it would be fun to test an Angular sample website created by my fellow MVP Maurice de Beijer that he uses in his training on Angular. (http://rawstack.azurewebsites.net/)
The site we wanted to test with CodedUI is located here and shows a list of movies as an infinite scroll list and it has admin pages where you can filter the list of movies and then click one of the rows to edit the movie details.
The scenario we wanted to test was as follows:
Goto the site, Click on the Admin link, enter a movie in the filter box, Click on one row and then alter the rating.
In my course I always urge people to find unique identifiers to find the controls you want to interact with, but as Maurice showed me with his Angular website, there is no use of the id attribute in any of the pages. This seems to be a common practice and therefore we need to find some other ways to uniquely identify the controls we want to interact with so we can find them on the screen.
With Angular it is very common you use attributes like: ng-model, ng-controller, ng-repeat, ng-submit, etc. So there is a way to uniquely identify these controls we just need another way to find them then using an id attribute.
Basically there are two options you have to achieve to find the controls with CodedUI. the first one is the one that most closely matches the CodedUI object model and the way CodedUI finds controls. We need to specify search properties and additional filter properties to find the control. The problem with this approach is that it is not working when you are using the cross browser plug-in and want to playback on chrome or Firefox. (what happens is that all filterProperties are ignored except taginstance, meaning you will most likely have a match that can contain multiple objects in stead of just one.
Great thing about the ExecuteScript method is that it returns a correctly typed object so you can interact with the control with it’s provided convenience properties that make interaction with the controls more easy.
In my next post I will show you the full steps on testing the full scenario.
If you would like to join me in San Francisco, you can get a discount on the conference fee. Use this link to register and you will get a discount of $400. You can also use the following promo code if you don’t want to click the link: SFSPK07
HI, thanks for all that attended my sessions at VSLive this week in Las Vegas. I hope you enjoyed the sessions and if you have questions left, please reach out to me on twitter (@marcelv) or ask them here below in the comments section.
If you want to have a look at the slides ore want to use the demo’s your self, you can find them here below.
Today I was asked an interesting and challenging question regarding CodedUI. We are working on some code that a colleague of mine wanted to test with Spec flow and CodedUI. The challenge was that in the spec flow test they created an instance of some WFP UI components that are part of the application and they wanted to use CodedUI to validate the behavior. So this means the applciation under test is the test itself, since that is hosting the control.
So Why is this challenging, you might ask? Well there are a couple of things that will bite you when you try this and you need to get them solved first, hence my post to directly show you the solution 🙂
To simplify the scenario and show what you need to do, I created a simple test application that creates a Wpf Window. In this window I created 2 buttons. The first button is the button I will use to activate the CodedUI code (this is the spec flow code in our real life scenario) and one other button that CodedUI code will click after I clicked the “click Hello Automated” button. I called the second button “Hello”.
Here is a screenshot of the applciation:
Now to get started, You need to add quite some references to assemblies to get CodedUI to run within your application. Therese references don’t seem all to obvious, but without them, your code will crash at runtime with Assembly type load exceptions.
You need to reference the following set of assemblies: (I have them in the format, so you can copy and paste them straight into your csproj file, after unloading it in the ide, to save you some time)
Next we need to write some code to click the button.Since we are not part of a classic CodedUI test, we need to initialize the payback engine ourselves first. so therefore we start with a call the Playback.Initialize().
Next we need to find the application under test, and this is our own process. Therefore I used the environment class Process to get the current running process information and that we can pass to the ApplicationUnderTest and attach to it. With this we now have a search scope for all CodedUi controls we want to find. Then you create a WpfButton and pass it the search criteria how to find the button. I have done this by searching on the x:name property of the xaml control. Here is the code:
Now you normally would just call this method from the event handler of our button. But if you do this the code will not run properly. this has to do with the fact that the event handler of the button click that would activate our code, runs on the UI thread. CodedUI will create a “search” control that will then search for the UI control on the screen, but on the same UI thread that needs to receive the input of the mouse click. So we will block the UI thread until we would be done, blocking it from getting the codedUI input.
There is an easy fix for that, and that is to move the code to a background thread, enabling the UI thread to receive input.
You see me click the activation button, then coded UI will click the Hello Button and then the Message box pops up.
All in all not the most complicated code you have ever seen I think, but still there where at least two things that where less obvious I think. First to initialize the playback engine and second the threading issue. (besides finding all the assemblies you need to reference, which is an annoying and time consuming task :-))
For a couple of weeks I have a Mac Book Pro as my main workstation. For my work I need to spend quite some time in Windows and only for my cross platform mobile app development with Xamarin I need the Mac Book, so I can develop iOS applications. The past weeks I have been using Parallels virtualization, but when you use it for Windows phone development, you need to enable nested virtualization and then unfortunately the machine has strange lags and is sometimes extremely slow.
One thing I wanted to try out today was to setup Parallels in a different way, using a boot camp partition. Here you install windows on your bare metal using the Apple provided boot camp options.
I must say, installing with boot camp was overall a smooth install, no strange issues I needed to solve. Just a couple of tweaks that I summarize below:
Change the scroll direction on the boot camp windows machine
Only a few things I got used to the past weeks on the Mac Book I really love where the way the track pad works. One thing is natural scrolling, which I got used to in such a way that I could not work with the reverse scroll anymore on windows.
To fix the scroll directions, there is a simple registry key you can set.
Here is the Power Shell command you can use (in admin mode!)
After rebooting, your windows will scroll in natural scroll mode, just as on Mac OS
Slowing down the scroll speed on the boot camp windows machine
The track pad now works, but the scroll speed is way to fast, at least for me it is. The way to slow down scrolling on the track pad is by changing the mouse settings in the control panel. Go to the control panel, type in the search keyword, mouse and then select “change mouse settings”
Here you select the tab wheel and set the number of lines to a lower value. for me 1 works best as shown in the screenshot:
Enabling Hardware virtualization on your boot camp windows machine
This one is in the category don’t ask how it works, but it works.
If you first boot into your boot camp partition, you can not enable Hyper-V. reason is that the hardware virtualization is disabled and you normally need to enable this in the PC bios. In this case you need to take the following steps:
restart your machine and use the option key at startup to select the OS-X partition and boot into the Mac OS again. there go to the System preferences and then to the Startup disk option. Then you select your boot camp partition and click reboot.
Now windows starts again, and if you look at the processor information, you can now see the hardware virtualization is enabled.
With this fix I was able to enable Hyper-V, and enable Visual studio to install the phone emulator image and start working on Windows Phone projects again
today I got hit by some serious outage on Microsoft Azure, that caused a couple of my virtual machines to be stuck in the starting stage. the problem was that there is just no way to fix this problem by using the simple tools you get in the azure portal. My servers that I use for demo purposes, needed to be up, since I was going to demo a lot of stuff in the afternoon at my Visual Studio Live! talks in Orlando.
My VM dashboard looked like this when I looked this morning:
So the question is, how the heck can you unblock these machines in this starting state, since they have been there for hours, so they are not actually starting.
the only way to fix this, was either delete the VM’s and be carful to keep the disks when deleting, or use PowerShell to stop the VM’s. Interestingly enough you can do a lot more with PowerShell then with the portal and I thought that might be the easiest way to get going again.
But since I most o the time just use the portal, I had not done any PowerShell on my brand new laptop. I think it is nice to go through the step by step process of what I needed to do in order to get things going again.
So first I needed to get the Azure PowerShell environment. The Azure PowerShell command lets are available for download, but I just got the whole package using the Windows Platform installer.
Here I selected the Azure Power tools and after that install I started a fresh command prompt.
Next I wanted to issue the Stop-AzureVM command, but in order for that command to succeed, you need to set up your subscription first.
For that you start with the command:
This command will create an UI prompt to log you on with your Azure credentials and after this succeeds you will see your subscriptions listed associated with your account.
If you have multiple subscriptions, you need to check which subscription was selected as your default. In this case I needed to select the right subscription. For this you use the command:
Select-AzureSubscription and you provide it the subscription name.
Now the default subscription is set for all subsequent azure commands.
Now I could finally issue the Stop-AzureVM command and there you need to provide it a couple of parameters. Fist you need to give it the name of the VM, tha tis easy since it is the name you see in the portal. The second question is the name of the service. The name of the service apparently is the name of the DNS for that machine, without the cloudapp.net part. So for my TFS azure machine that is called FluentbytesTFS, this was fluentbytesdc, as you can see in the picture here below.
After issuing the Stop-AzureVM command, I was able to use the portal again to start the VM’s. This time they started and all was well again.
Hope this helps you when you get your VM’s stuck, I had to search in multiple places to figure out how to make it work again.
TLDR version: install xcode on your Mac, since it is probably not installed.
Today I spend about an hour getting things up and running because I kept running into problems getting visual studio to pair with the build host.
This is one of the things that you need to set up when you want to build iOS applications with Xamarin and Visual Studio, is the build host that runs on a Mac.
I had installed Xamarin studio on my MacBook and windows running in Parallels. Started the build host and then clicked the button to pair, giving me a PIN number to use to pair Visual Studio with the build host.
But the Visual Studio pairing dialog kept telling me the PIN number was incorrect, even after copying and pasting it from the build host control into the connection dialog.
When running Diagnostics I saw it kept failing on connecting to the build host. Connectivity to the mac was ok, but the build host could not be reached. I tried of course many things, turning of the fire wall being e.g. one of the things I tried.
When looking at the details, I kept getting the diagnostics failing with a cryptic message. The message was:
Parameter name: must be between 0 and 65535
Almost ready to pull my hair out I got one moment of enlightenment. What I did is that I started xamarin studio on my MacBook and there tried to build an iOS app. Just to see if I could build an app and run it in the simulator, just to ensure all is good on the Mac side.
Then I tried to build the app and run it in the simulator and I got the message that XCode was not installed. And that was true, it is a brand new MacBook and after installing Xamarin I just went straight through installing the visual studio side of thing.
After installing XCode and checking I could run a simple app in the simulator, I tried reconnecting the Visual Studio environment again and voila, problem solved.
So if you get the message Parameter name: must be between 0 and 65535, chances are you haven’t fully installed everything required to run an app in the iOS simulator.
Setting up such a domain is especially useful when you want to leverage e.g. TFS and the test tools, since these tools work best if you work in a domain joined environment.
After setting this up, all worked great and I have used it for several demos and just some average development work I do.
My network looks more or less as follows:
But all of a sudden last week, I ran into the problem that on any of my development machines (the test clients) could not connect to the internet anymore. Sometimes an address was reachable and all of a sudden a couple of seconds it was not possible to connect. This intermitted problem was really problematic getting any real work done these days especially when you are running tests against websites on the internet
So trying to resolve the problem, I first looked at my network setup and especially DNS. Reason for me to start there is that the IE browser constantly showed the dreaded connection failed and telling me I did not have an internet connection. If you look a bit deeper, you could see it was a name resolution issue, so I started a command line and used nslookup to try to resolve names.
DNS request timed out.
timeout was 2 seconds.
DNS request timed out.
timeout was 2 seconds.
DNS request timed out.
timeout was 2 seconds.
DNS request timed out.
timeout was 2 seconds.
*** Request to UnKnown timed-out
So this confirmed to me I had a DNS problem, question next was how to resolve it. With the custom domain setup, I configured a virtual private network with the address range 10.0.0.x and since I wanted to host my own Active Directory and you can see by the response it did pick up my DNS server. So the problem must be at the DNS server itself.
Then I looked at the DNS configuration and since it was fully functioning before, it must have something to do with a DNS setting that might have gone stale in the Azure network topology.
One of the things that is different to on premise AD is the fact that your AD machine still has an DHCP obtained address. I did pin it to a fixed address using the PowerShell command described, but still you get this address from a DHCP server.
Now looking at the configuration, I discovered that the configured forwarder, that takes care of all requests outside the local domain, was unable to resolve.
This was exactly my issue, so by removing the forwarder, DNS will fall back to the root hints. Now all requests can be resolved straight away and my development machines can happily browse the web again
I Assume this problem is caused by the fact that once I created this AD machine and promoted it to the AD and DNS server, it just added the DHCP server that it got it’s lease from as the default forwarder. Since I might have been moved around the datacenter during maintenance or perhaps even failover, it is very well possible this server does not exist anymore. By just removing it from the list, I have a more sustainable solution, since it will not be affected anymore by such a move in the future.