How to use Coded UI in Visual Studio to create automated UI tests

To use the Coded UI for automated testing you need to know three things:

  1. You can use the recording function for Visual Studio to do most of the work
  2. You can do it manually but it requires time and patience.
  3. There are some details which you need to be aware of before you can use Coded UI for testing

 

Automated UI test recording

This is rather straight forward.

To be able to record a test the following must be true:

  • You application but not in debug mode while you are recording your UI test
  • You have to have a physical focus in a C# test file inside a test method where the recording will create a test call created by the recording process.
  • Before you can start recording you must have your application running.

codeduip3

Next open the “Coded UI Test Builder”:

codeduip4

It should look like this:

codeduip6.PNG

At this point open your application on the screen. Then press the red recording button to start recording.

After you are done with your application test steps creation you can add assertions to the test. This happens from the circle in the test builder.

When you are done press the blue arrow pointing to the right with lines below it(the last icon in the test builder). This will generate the test code.

After this, you can start your tests from the test explorer.

Manual UI tests creation

Manual testing can be harder and time-consuming but has the advantage of precision. The basic structure goes as:

  • Create a browser object pointing to a web application
  • Start searching for controls based on search and/or filter properties
  • Do something to the control
  • Do an assertion for the test

[TestMethod]
public void CodedUITestMethod2()
{

// To generate code for this test, select "Generate Code for Coded UI Test" from the shortcut menu and select one of the menu items.
BrowserWindow browser = BrowserWindow.Launch("some your to your web application");
browser.Maximized = true;
UITestControl control = new UITestControl(browser);
control.TechnologyName = "Web";
control.SearchProperties.Add(HtmlHyperlink.PropertyNames.TagName, "A", HtmlHyperlink.PropertyNames.InnerText, "some text", HtmlHyperlink.PropertyNames.ControlType, ControlType.Hyperlink.Name);
control.SearchProperties.Add(HtmlHyperlink.PropertyNames.Href, "some partial URL", PropertyExpressionOperator.Contains);
control.WaitForControlReady();

Assert.AreEqual(true, control.Exists);
control.DrawHighlight();

UITestControl control2 = new UITestControl(browser);
control2.TechnologyName = "Web";
control2.SearchProperties.Add(HtmlInputButton.PropertyNames.ControlType, ControlType.Button.Name, HtmlHyperlink.PropertyNames.ValueAttribute, "some text", HtmlHyperlink.PropertyNames.Class, "some css class");
control2.WaitForControlReady();

Assert.AreEqual(true, control2.Exists);
control2.DrawHighlight();

UITestControl control3 = new UITestControl(browser);
control3.TechnologyName = "Web";
control3.SearchProperties.Add(HtmlHyperlink.PropertyNames.TagName, "input", HtmlEdit.PropertyNames.Name, "some name", HtmlHyperlink.PropertyNames.Id, "some ID");
control3.WaitForControlReady();

Assert.AreEqual(true, control3.Exists);
//tunnit.DrawHighlight();
control3.SetFocus();
control3.SetProperty(HtmlEdit.PropertyNames.Text, "some text");
System.Threading.Thread.Sleep(1000);

UITestControl person = new UITestControl(browser);
person.TechnologyName = "Web";
person.SearchProperties.Add(HtmlCell.PropertyNames.TagName, "td");
person.SearchProperties.Add(HtmlCell.PropertyNames.ValueAttribute, "namefield");
person.SearchProperties.Add(HtmlCell.PropertyNames.InnerText, "some text", PropertyExpressionOperator.Contains);

person.WaitForControlReady();
person.SetFocus();
Mouse.Click(person);

}

For more info on the controls and ways of using go here:

https://msdn.microsoft.com/en-us/library/microsoft.visualstudio.testtools.uitesting.htmlcontrols.aspx

Coded UI – Have to know things

Requirements

To use the Coded UI you need some version of Visual Studio that supports Coded UI. Currently as of this blog post only Visual Studio Enterprise supports it: https://www.visualstudio.com/en-us/products/compare-visual-studio-2015-products-vs.aspx

Running tests

You can run tests with or without debug mode for the tests. Notice that Coded UI test debugging is different than debugging your application, meaning that you have to run the debugging for test specifically from the text explorer.

codeduip1

To access the test explorer:

codeduip5

Debugging

You can’t have your application in debug mode when recording automated UI tests (this is true for Web application, not sure for windows applications). What you need to do is to run your application without debugging. For web apps what this does is that normally IIS Express is launched and the app will be running there. If you are running the app on a manual IIS site well then all you need to do is to start the app.

codeduip2

Browsers

Coded UI requires Internet Explorer unless you configure it otherwise.

You can start a browser from your code using the following code:

BrowserWindow browser = BrowserWindow.Launch(“some URL”);
browser.Maximized = true;

UIMap

This is a class inside your test project where the automated recorded tests are saved.

codeduip8

NOTICE: If you have the “Coded UI Test Builder” closed you can double click on the UIMap.uitest to get an overview of your recorded tests.

codeduip9

Dynamic controls or URLs

If you have dynamic controls or URLs then you need to remove the dynamic parts from the recorded code. This means that you have to inside the C# code to remove search properties of filter properties that define dynamic data. Notice that you have to make sure that the remaining properties are enough to find your controls or URLs

You can do this from your Coded UI test class by going to the declaration of the test function in the UIMap class:

codeduip7

Or by opening the UIMap.cs file and under it the UIMap.Designer.cs file.

codeduip8

Basically what you are looking for is something like the code example below. The commented out code is in this case, the dynamic data which changes. The code assumes that the rest of the properties will do the job in finding the control:


public HtmlCheckBox UI__listitem___id_5066CheckBox
{
get
{
if ((this.mUI__listitem___id_5066CheckBox == null))
{
this.mUI__listitem___id_5066CheckBox = new HtmlCheckBox(this);
#region Search Criteria
//this.mUI__listitem___id_5066CheckBox.SearchProperties[HtmlCheckBox.PropertyNames.Id] = "__id_50661";
//this.mUI__listitem___id_5066CheckBox.SearchProperties[HtmlCheckBox.PropertyNames.Name] = "__listitem___id_50660";
this.mUI__listitem___id_5066CheckBox.FilterProperties[HtmlCheckBox.PropertyNames.Value] = "some value";
this.mUI__listitem___id_5066CheckBox.FilterProperties[HtmlCheckBox.PropertyNames.LabeledBy] = null;
this.mUI__listitem___id_5066CheckBox.FilterProperties[HtmlCheckBox.PropertyNames.Title] = null;
this.mUI__listitem___id_5066CheckBox.FilterProperties[HtmlCheckBox.PropertyNames.Class] = "__checkbox";
this.mUI__listitem___id_5066CheckBox.FilterProperties[HtmlCheckBox.PropertyNames.ControlDefinition] = "name=\"__listitem___id_50660\" class=\"__ch";
this.mUI__listitem___id_5066CheckBox.FilterProperties[HtmlCheckBox.PropertyNames.TagInstance] = "27";
this.mUI__listitem___id_5066CheckBox.WindowTitles.Add("Some URL");
#endregion
}
return this.mUI__listitem___id_5066CheckBox;
}
}

Search and Filter properties when searching for controls – What’s the difference?

The difference is that the search properties act as AND operators. While the filter properties act as OR operators.

Advertisements

PnP Partner-Pack Site Provisioning: Weirdness, quirks and guide

If you have been playing around with the Site Provisioning in the PnP Partner Pack you might have run into problems when installing it. While the instructions are rather good there are still some problems which I ran into and are not mentioned in the instruction(or I might have just passed by them).

Notice that the things mentioned here assumes that you have read or understand how to install the site provisioning web app by this instruction:

https://github.com/OfficeDev/PnP-Partner-Pack/blob/master/Documentation/Manual-Setup-Guide.md

Anyway here is what is good to know:

Sign-ON URL format:

When you are defining your Sign-On URL in the Configure section for your application, there is a very weird and annoying error that the site provisioning web application might throw. This is due that you are missing one single character from the end of your URL which is: /

Example:

URL which does not work: https://pnpprovisioning82.azurewebsites.net

URL which does work: https://pnpprovisioning82.azurewebsites.net/

Do you see the difference :)? Small but enough to make you wonder. The error message is not necessarily very informative and unfortunately I do not have that error message anymore, can paste it here. Just check this thing in case of errors.

The webjobs…:

Installation

The web jobs are good and working BUT the installation is a bit misleading. I had to figure out for myself and gather the info from different locations. My problem was that the script which was supposed to install the jobs automatically did not work. Some error which did no make sense and I did not want to spend time figuring out. If it works for you then that is great. If not you might have to do this manually.

You have different way on how to do this manually:

  1. Through Azure portal management
  2. Through visual studio

 

Azure portal management

  1. Build a release version of the webjob
  2. Just zip the entire release folder and rename your zip package
  3. Go to your web application web jobs section
  4. Click add a new job and upload your ZIP file and define how you want your job to run

 

Visual Studio

On the web job project which you want to upload to Azure press the second button and chose  “Publish as Azure Webjob” and follow the instructions.

You might want to take advantage of the Azure management UI by downloading a publishing profile from your web application dashboard. You can use this publishing profile in Visual Studio.

The webjobs what they do

OfficeDevPnP.PartnerPack.ContinousJob

This is the one which will be reading the PnPProvisioningJobs list and create jobs to be processed by the other webjobs. You have to have this on to get anything done, mostly related to site provisioning. I might be wrong on some of the details here but having this on is essential.

OfficeDevPnP.PartnerPack.ScheduledJob

My understanding is that his job is what is provisioning the sites and creating templates of sites.

 

Guide – What is where or how things work

The web application overall UI functionality

As is mentioned in this documentation there are several views(pages) which are used with the site provisioning. Notice that not all of them are available through the web application UI and this in my opinion is confusing.

Some of the functionalities are only available in a actual site:

  1. Creating a new sub site
    1. This is only available when you go to a site, from “site settings” select “site contents”. The PnP Partner Pack overrides the default “New subsite” link. I kind of understand this but was not the first place where I expected it to be.
  2. Saving a site template
    1. This can be found under your site “site settings” in the category “site actions”. There is a JS file which is attached to your PnP sites which add a new link here named as “Save site as Provisioning Template”.

The JS file is located in the infrastructure site in the Library: PnPProvisioningTemplates under the folder: Overrides. Through the XML file in this location the JS file is loaded and the two above mentioned things are performed.

Infrastructural Site Collection

What is mean by this is that this is a “dummy” site collection created by you and then you apply the steps(script) https://github.com/OfficeDev/PnP-Partner-Pack/blob/master/scripts/Provision-InfrastructureSiteArtifacts.ps1 on the site collection. This will be the central hub from where all things are operated from regarding site provisioning.

Good to know libraries

PnPProvisioningTemplates

This is where your site provisioning templates are located(right in the root of the library) and all other PnP site provisioning related configuration data.

PnPProvisioningJobs

This is all of the actions(jobs, requests) for sub site, site collection, site templates etc are stored. Based on these the web jobs will start to operate.

 

How to set O365 PageLayout Associated Content Type field

Here is a code snippet to set your page layouts associated content type. This one was a bit weird when I first tried to set it.

 private static void SetPageLayoutMetadata(Web web, File uploadFile, string title, string publishingAssociatedContentType)
{
// Speficy that the page layout is a page layout and not a master page
var parentContentTypeId = ""0x01010007FF3E057FA8AB4AA42FCB67B453FFC100E214EEE741181F4E9F7ACC43278EE811""; //Page Layout
var gallery = web.GetCatalog(116);
web.Context.Load(gallery, g => g.ContentTypes);
web.Context.ExecuteQuery();

var contentTypeId = gallery.ContentTypes.FirstOrDefault(ct => ct.StringId.StartsWith(parentContentTypeId)).StringId;
var item = uploadFile.ListItemAllFields;
web.Context.Load(item);

item["ContentTypeId"] = contentTypeId;
item["Title"] = title;
item["PublishingAssociatedContentType"] = publishingAssociatedContentType;

item.Update();
web.Context.ExecuteQuery();
} 

Two important things:

  • parentContentTypeId: This is the ID that tells O365 that this page layout is actually page layout, this is a static id which is defined in the code
  • publishingAssociatedContentType: This is your actual content type to which you want to associate your page layout to: Example of the format:;#my content type name;#0x010100C568DB52D9D0A14D9B2FDCC96666E9F2007948130EC3DB064584E219954237AF3900242457EFB8B24247815D688C526CD44D00A3428808D7DE6A4RABF83921AFB25424;#
    • So the format should be in the following way:

public static String BuildPublishingAssociativeContentTypeId(ContentType contentType)
{
String contentTypeAssociativeID = null;
if(contentType != null)
{
contentTypeAssociativeID = String.Format(";#{0};#{1};#", contentType.Name, contentType.StringId);
}

return contentTypeAssociativeID;
}

Mobile Device Testing and Debugging with VirtualBox, Android Studio, Visual Studio and IIS

This post is from the perspective of a person who has a Microsoft technologies based web solution that needs to connect with a mobile device. This might work for other types of technologies and virtual machines with some or alot of tuning. Basic principles should be more or less the same.

I will give firstly an introduction on the solution used in my scenario:

I have a Android mobile device with an app in it that needs to connect to a webapi service to retrieve data and post data to it. The thing which this post is concerned about, is debugging the app with Android studio using the app from the Android device against a webapi which is also under debug mode in Visual Studio. This way I can see what is happening both on the client and on the server side.

Basically how this works is that you will have to connect with your mobile device to a local network where your physical machine exists. Because you are using a mobile device the logical way is over WiFi and no having your device plugged in to your physical machine by USB does not work. You can not directly connect to a localhost that way. Well atleast I could not make it to work. Notice that you can connect to a localhost from Android Studio while debugging your Android app but this is only possible is your a emulating the app locally. Even then though you might have problems and have to configure your solution in such a way that your app will pick it up.

This post assumes that you have a ready build for your server side solution at a location in your development machine. Here are the steps:

1. Create IIS site

– Add a new application to IIS which points to your solution build location.
mobile1

mobile2

– Next make sure that the application pool account has enough privileges to the location. I do this by creating a new account to AD or I create a local machine account on my development machine.

This is to configure the Application Pool account:
mobile8

These steps are for the file system level:
mobile3

mobile4

– If you are using a database in your application make sure that the application pool account has the proper privileges. This depends of course on how you have built your solution.
– Assign a port to your web application

mobile6

mobile5

2. Config ports and firewall settings
– Next you need to allow inbound and outbound connections to you web application through the port which was earlier configured for the web application. This needs to be done for both the virtual machine and your actual physical machine.

For virtualBox:
mobile9

For WMWare:
mobile10
mobile11

3. Attach to process

The next steps is to attach your developer tools to your server solution and your mobile application to whatever developer tools your are using, something like Android Studio or XCode.

Config VirtualBox

How to Forward Ports to a Virtual Machine and Use It as a Server

 

SharePoint – Setting users or groups for a membership webpart through code

This is a rather simple thing… well once you have cracked it :).

 

There are two properties which need to be set:

And that is it. To find the “main” associated groups to your site you could use these properties:

https://msdn.microsoft.com/EN-US/library/microsoft.sharepoint.spweb.associatedownergroup.aspx

https://msdn.microsoft.com/EN-US/library/microsoft.sharepoint.spweb.associatedmembergroup.aspx

https://msdn.microsoft.com/EN-US/library/microsoft.sharepoint.spweb.associatedvisitorgroup.aspx

https://msdn.microsoft.com/EN-US/library/microsoft.sharepoint.spweb.associatedgroups.aspx


using (SPSite site = new SPSite(wsSite.ID))
{
using (SPWeb web2 = site.OpenWeb(wsSite.RootWeb.ID))
{
var pubWeb = PublishingWeb.GetPublishingWeb(web2);

using (var wpm = pubWeb.DefaultPage.GetLimitedWebPartManager(PersonalizationScope.Shared))
{
// Search for the right webpart(you could use LINQ instead of a foreach)
int memberShipWebPartsCount = 0;
for (int x = wpm.WebParts.Count - 1; x >= 0; x--)
{
var membersWebPart = wpm.WebParts[x] as Microsoft.SharePoint.WebPartPages.MembersWebPart;
if (membersWebPart != null)
{

// There are only two members webparts which are needed to be processed, at the moment
if (memberShipWebPartsCount < 2)
{
if (memberShipWebPartsCount == 0)
membersWebPart.MembershipGroupId = wsSite.RootWeb.AssociatedOwnerGroup.ID;
else if (memberShipWebPartsCount == 1)
membersWebPart.MembershipGroupId = wsSite.RootWeb.AssociatedMemberGroup.ID;

membersWebPart.DisplayType = Microsoft.SharePoint.WebPartPages.MembersWebPartDisplayType.GroupMembership;
wpm.SaveChanges(membersWebPart);

pubWeb.DefaultPage.Update();
if (pubWeb.DefaultPage.CheckOutType != SPFile.SPCheckOutType.None)
pubWeb.DefaultPage.CheckIn("");

if (pubWeb.DefaultPage.ParentFolder.DocumentLibrary.EnableVersioning && pubWeb.DefaultPage.ParentFolder.DocumentLibrary.EnableMinorVersions)
pubWeb.DefaultPage.Publish("");
}
memberShipWebPartsCount++;
}
}

}
}
}

SharePoint 2013 Search and Search Index Problems

If you find yourself in a situation where your search does not work you have some options:

  1. Do a full crawl
  2. Reset the search index and Do a full crawl
  3. Maybe along the way restart the SharePoint search service and/or the SharePoint timer service
  4. And if none of the above then you have to get creative

In the third option usually you get errors on your search webpart or search results. These errors do not go away and nothing seem to help, like the option one and two above.

One of the last things which you can do before going crazy 🙂 would be to manually empty the configuration cache. You do this in the following way:

  1. Find the the folder named with a GUID which has cache.ini file under the C:\ProgramData\Microsoft\SharePoint\Config
  2. Stop SharePoint Server Search 15 and SharePoint Timer Services
  3. Backup the cache.ini file
  4. Delete all files except the cache.ini file
  5. Edit the cache.ini and make sure it has only 1
  6. Save and Close the file.
  7. Start SharePoint Server Search 15 and SharePoint Timer Services
  8. Start Index Reset from SharePoint Central Administration\Application Management\Manage Service Applications\SearchServiceApplication\Index Reset
  9. You will see your  C:\ProgramData\Microsoft\SharePoint\Config\YourGUID folder will be filled up new .xml files and your cache.ini file will be modified.
  10. Next I run a full search crawl to get some search results.

NOTICE: Do not do this if you are tight on time. Depending on the amount of data in your target environment running a full crawl will take a looon long time. All depends on the server resources and the amount of data in your target environment.

There is also a script from this at codeplex:

https://spcachecleaner.codeplex.com/

Hope this helps someone. I know I have spent enough time with this problem and it is anoying.

 

Error when trying to access Source Control with Team Explorer

The problem is as described in the title. This was in my case due to corrupted Visual Studio version control cached data.

I fixed it like this:

Run this in Visual Studio Comman Prompt:

devenv.exe /resetuserdata

Then navigate to your TFS data on HD, it should be around here:

c:\users\developer\appdata\local\microsoft\team foundation

There delete without mercy under the cache subfolder everything. Just be sure to backup the folder data before you do this, just in case.