Running UI tests in Internet Explorer with Jenkins on AWS

In the best conditions it can feel difficult to use Selenium WebDriver to run UI tests on Internet Explorer. Running on the same machine you develop on isn’t realistic as WebDriver for IE requires all of the window focus. So you move it into a virtual machine on your box and then find that your machine can’t give up enough resources to reliably run the UI test suite you’ve built out. Even opening a new application on the host machine can cause the tests running in the virtual machine to fail. All that being said you want to have testing done somewhere else, that you don’t have to see, where it won’t be interrupted and have it all run every time you commit to source control. Our team is starting with Jenkins and automatic provisioning of Elastic Compute Cloud (EC2) servers in Amazon Web Services (AWS).

Asking for help running UI tests on Internet Explorer in this setup seemed to result in short replies of “no”. I won’t tell you about all the wrong paths I took getting to this solution. This tutorial of sorts makes several assumptions about where you are in the setup and what you already know how to do. For example, I had no Jenkins administration experience before doing this, I didn’t sign up for AWS, and I never setup any security credentials before starting this task.

  • I will not go into any specifics of running UI testing against IE because you’ve already got tests passing when run locally.
  • You already have a Jenkins install running and are comfortable enough to break things.
  • This Jenkins install has the EC2 plugin and has been connected to AWS
  • You’ve been given access to an AWS account where you can spawn instances with wild abandon.
  • You’ve got a PEM file for said AWS account to decrypt your instance’s administrator password.
  • You aren’t afraid of a little command line work.
  • You’re ready to do some Windows configuration.
  • And finally, you’re prepared to have patience.

This process involves:

  1. Create a new EC2 instance
  2. Configuring that EC2 instance to automatically login as an administrator
  3. Setting up the EC2 instance to register itself on your Jenkins build server
  4. Creating an AMI of this EC2 instance
  5. Adding or using an existing Jenkins user to use on the slave instances
  6. Configuring the Jenkins EC2 plugin to connect to the AMI we created
  7. Adding our own User Data information to the Jenkins EC2 configuration
  8. Start a build, launching an EC2 instance and starting the local process
  9. See success as this instance launches Internet Explorer from your UI test suite and watch as your tests pass because Selenium WebDriver can interact with IE.

AWS Setup

After signing into AWS and navigating to the EC2 console screen you want to launch a new instance.2015-08-28 16_00_24-EC2 Management Console

This example test machine will be on Microsoft Windows Server 2012. I used an M3.Large instance but you might be able to get away with less machine.2015-08-28 11_50_39-EC2 Management Console

When you get to the step to configure the instance’s security group you’ll want to create a new group or select an existing group that has the RDP protocol open to a machine you’ll be connecting from. 2015-08-28 11_51_40-EC2 Management Console

Back on the EC2 instances console, when the machine state is green and running you’ll want to collect the administrator account password by right clicking on the instance and selecting Get Windows Password. Then after you’ve decrypted and copied the Windows admin password you need to right click on the menu again to connect to this instance. 2015-08-28 11_55_02-EC2 Management Console

Once you’ve gotten into Windows the first thing we’ll do is create another account and add it to the administrator security group. Open up the Control Panel, then User Accounts, then User Accounts again, then click on Manage User Accounts. Here you’ll click on Add a user account. 2015-08-28 12_03_32-ec2-54-161-109-120 - - Remote Desktop

Once you’ve created that account, navigate back to the Manage Accounts screen and select that new User. Then select change account type, and change it to Administrator. 2015-08-28 12_04_21-ec2-54-161-109-120 - - Remote Desktop

Now we need to set that user to automatically login and go to the desktop when Windows starts up. Use the shortcut Windows+R to open the Run dialog and enter the command control userpasswords2. 2015-08-28 12_06_07-ec2-54-161-109-120 - - Remote Desktop

In the User Accounts window that appears you’ll want to uncheck the first option requiring users to enter a password to use the computer. 2015-08-28 12_06_48-ec2-54-161-109-120 - - Remote Desktop

When you click OK you’ll want to enter the user name and password for that new administrator account you created. 2015-08-28 12_07_25-ec2-54-161-109-120 - - Remote Desktop

Test Environment Setup

At this point it’s time for you to setup this machine. Go through installing everything you need to build and test your project. Build and test your project, make sure IE UI tests run. You want every thing to be green here. Get it all prepared because we’re going to freeze this as an AMI to be used on demand by Jenkins. After you’ve done all that we need to download a couple of files that I wrote to configure this machine when it launches to connect to Jenkins and register itself as the slave it should be.

You’ll need to install Java, wget and Python 2.7 on the system. I used Chocolatey for my configuration. After that save this file to your users directory, ie: C:\Users\Test, and named it

Then download a batch file we’ll use to run this script and save it to the same directory, ie: C:\Users\Test, and named it slave.bat.

Run both files to make sure they work. They won’t really work right now we have other configuration to do but it will verify they are linked and you have Python installed.

What this Python script does is look at the EC2 User Data values that will be set by Jenkins later. It then connects to Jenkins as a slave, run by this administrator user and in an active session. This is the one weird trick in getting Internet Explorer UI testing to work. It demands an active and interactive session, which is why it was such a pain to run anywhere.

AWS Setup Continued

To finish setting up the instance we need to add a new task to run our startup slave script every time the system starts. If you’re unsure where the Task Scheduler is you can use the Run dialog again and enter the command %SystemRoot%\system32\taskschd.msc /s. When you click Create Task on the right of the Task Scheduler the first thing to do is make sure you’ve got Run with highest privileges checked. 2015-08-28 13_38_04-ec2-54-161-109-120 - - Remote Desktop

Select the Triggers tab and add a trigger to run this task at login.

Now select the Actions tab and create a new Start a program action pointed to our batch file. Be sure to use the format cmd /k “path/to/my/batch/file”2015-08-28 13_38_21-ec2-54-161-109-120 - - Remote Desktop

Go ahead and reboot the instance and then log back in with your custom admin account. You should be presented with a cmd prompt and a unsuccessful script launch. 2015-08-28 14_57_08-ec2-54-161-109-120 - - Remote Desktop

If you’ve gotten this far then go back to the EC2 console, right click on our running instance and select Image, then select Create Image2015-08-28 15_19_58-EC2 Management Console

Now navigate over to the AMIs page on the right navigation and you can see the new AMI pending. Save the AMI ID at this time we’ll need to use it later in Jenkins.

Jenkins Setup

Set aside AWS for a bit and lets take a look at Jenkins. We’re going to be collecting information to populate our instance’s user data property as well as configure a few other connections. If you don’t already have the EC2 Plugin installed do so at this time. After installing it take some time to look around and familiarize yourself with the setup. I’ve assumed you’ve already got this part connected to AWS. We need to collect a few pieces of information along the way to help get the slave system connected properly.

  1. The URL for our build server
  2. A user that has permission to start slave machines
  3. That user’s username
  4. That user’s API token
  5. A prefix by which our Jenkins’ slaves are named which is conventional

As I presumed earlier you already have the Jenkins build server that our instance will be able to access. Save that build server URL now as it completes our first requirement. If you don’t already have a user created or want to create a new user for launching these slaves do so at this time to take care of our second requirement. Now go to that users profile page and click the Show API Token button. 2015-08-28 13_40_31-User ‘Barrett Sonntag’ Configuration [Jenkins]

This User ID and API Token fulfill our third and fourth requirements so hang onto those values. 2015-08-28 13_40_50-User ‘Barrett Sonntag’ Configuration [Jenkins]

The fifth requirement can be found when configuring the EC2 plugin for Jenkins. Go to Manage Jenkins, then Configure System, then on the very bottom click Add a new cloud, then configure that cloud. After that click the Add button under this cloud. Here your Description field is what will set your slave name prefix. I suggest not using spaces, but if you go crazy just make sure to URL encode it and then save this value off to fulfill the fifth requirement. Set the AMI ID to the same ID we collected earlier for our EC2 AMI. Be sure to set the FS root, for my examples I used “c:\jenkins”. Set the remote user as the user you created earlier and the set the AMI Type to windows and enter the user’s password there. Set the boot delay to 180 as recommended. 2015-08-28 15_28_30-Configure System [Jenkins]

Now click Advanced under these options. It’s time to use all the variables you saved to build our User Data values.

  • JENKINS_URL is the build server URL
  • SLAVE_PREFIX is the AMI description
  • USER_NAME is the user’s username you saved
  • USER_TOKEN is the user’s token you saved

2015-08-28 15_30_17-Configure System [Jenkins]

Verify User Data Injection in AWS

At this point you should be able to spawn a new instance with Jenkins by starting a build and see that User Data. Go back to the EC2 console after starting a build and find the new instance that was provisioned. Right click on it and select Instance Settings, then select View/Change User Data.

2015-08-28 15_33_55-EC2 Management Console

The code there should have a USER_DATA value, but the value is base64 encoded so it looks nothing like what we entered before. 2015-08-28 15_35_41-EC2 Management Console

That is okay because the script we setup in the EC2 AMI is already configured to decode that. At this point your build should be working, to check it out you can connect into this instance and login using your custom user credentials we made at the beginning. You can see the command window open up from the scheduled task and start debugging as necessary or celebrate a successful build.

Creating and Taking Ownership of Your Personal Brand

Photo by Jeff Stvan

“Iron Sky” by Jeff Stvan

In the beginning

When I began programming it was a solitary pursuit. I didn’t connect with any other hobbyist or professional programmers for several years until my first real job. At that same time I bought this domain without an idea of what I was going to do with it. I remember the desire to claim a space online, and to create a personal presence. This wasn’t my first domain, and I regret not continuing the pay for my registration of older domains. I remember someone I didn’t know well coming up to me in high school and asking why my site wasn’t live anymore. At that point I realized I could have an effect on someone without ever knowing them; simply by publishing my own presence online. My personal brand uses my own name: Barrett Sonntag.

Our modern development space is an open book

During this time Linux was fighting for enterprise respect while being created by countless programmers from all across the globe for the love of creation. I watched this open source software movement being vilified and fought. Any developer today can look around, look at GitHub, and see just how much benefit open source software has brought to our chosen profession. Everything in GitHub is tracked, and everything has a unique name on it. That unique name links to a page which lists all of their contributions, which languages they use, and which projects they contribute too. With just a little searching you can create a complete picture of a programmers activity online. Even the lack of activity is knowledge that asks questions. I can’t share the code for private projects, but by contributing publicly I can share a bit of my experience and passion. Your accountability in code is easily viewable so think carefully about cursing in your comments.

My turning point to making the Barrett Sonntag brand

In 2007 I made a conscious decision to own my personal brand, that is Barrett Sonntag. Some coworkers and I started searching ourselves online. Those with common names didn’t appear at all, but since I am blessed with a fairly unique name some content came up. Some stuff I forgot about, but was proud of. My good friend Ronald Figueroa bought his own domain not too long after that conversation. At the same time I saw a possible future where someone else would come into the Internet with my name, and I wouldn’t be able to recoup ownership of my name. I had a head start and I took it. I took ownership of the Barrett Sonntag brand, and that extends beyond my personal reach. It is my creation, it is what I have chosen to publish and relate to myself. I have gone to the source where my employers, my clients, and my customers go searching for truth to create my personal brand. Search engine optimization for the self!

The information super highway

Thousands of people are intentionally doing the same thing right now. There are personal blogs of developers, designers, project managers, or hire me sites, that are purpose built. These personal brands are extremely valuable, increasing your future potential earnings, discoverability or providing an edge in getting your next job. The Internet is how we discover the world outside our personal network. Even when I get a personal recommendation for something I turn right around and enter that into the search engines of the Internet to get a feel for the general consensus. The idea that I did Internet research on potential clients and employees was novel at the time in my personal network, but is common place today. At the same time over these last few years we’ve had more people join the Internet as consumers. They only created content on social networks, and learned hard lessons about the permanence of the Internet. The pictures you post, the words you say have an unknown lifespan, and that idea is hard to understand. So we have these personal brands being created right now whose value does extend beyond the person who is creating them. The creation of your own personal brand is a way to take control of reality in relation to yourself. You have an opportunity to be selective about the picture of you that someone else builds in their mind when they search for you online. You can highlight your achievements, point out your contributions, and wax poetic about something related to your brand.

The risks of connecting the virtual and physical

The creation of your online presence, your personal brand, or your history on the Internet can also be a security measure. Defamation of character as I understand it is a matter between two entities. Someone has stated false claims on my brand, or another person whose name matches my personal brand does something newsworthy, creates a lot of noise unrelated to what I have created. The more effort placed into my brand the more robust I believe it might be in that event, and no I haven’t had to test that yet. There has also been many instances of unorganized but large amounts of individuals acting aggressively. They will tweet, post to blogging platforms, share on social networks. I don’t know if there is a defense of that to be honest. There is a large amount of risk taken in creating your own personal brand connecting an online presence with your physical presence. The risk is not only to yourself but to those near to you whether you’re in the right or not. A statement can be taken out of context, an opinion you gave, and comments you made in the past can haunt you if it is connected to your personal brand in a negative way. Your personal social media pages that are public or private can be connected to you. Private social networks can be made public in the blink of an eye by accident or on purpose. Those photos you thought were cool or comments you made in college might not reflect who you are now, and can hurt your personal brand.

A personal brand is free to create, but I can only imagine how much PR disaster relief can cost. It doesn’t even have to be done with the intent of creating a formal brand. You can create, with some effort, the picture you want, and the reality you want. Don’t be fooled though, there is not enough potential value to risk lying. I only publish the truth as I know it at that moment, it’s a lot easier to be consistent, I am always able to change my opinion based on new information, and there is no web of lies. Nothing goes away in the information age, there is no secret that can be kept once it gets uploaded, and if you lie it will eventually come back around. Even offline sleuths can uncover public records that are then uploaded and spread. There isn’t a defense strong enough to suppress the truth once it hits the Internet.

Another consideration to keep in mind when you strike out to create a personal brand is hacking. A stale site that isn’t up-to-date is a prime target for hackers. They don’t make any noise when they infect your sites and are very difficult to get rid of. I’ve had more than one time of my own dealing with security vulnerabilities so keep your brand active and the problems if they arise won’t go unnoticed.

A natural progression to personal brand creation

This personal brand, Barrett Sonntag, is something I never imagined when I started programming. I never considered that I would work with other people on enormous code bases that were created by our predecessors. You’re probably already on your way to creating a personal brand of your own. Open source software has won the day, programmers have put themselves out their, and connected themselves with their code. You can trace contributions, bugs, comments, successes, and mistakes back to the person that created them. The connections may be created innocently at first, perhaps as leverage in an interview, but soon build into a map or history of your footprints across the net. To make this personal brand and directly connect it to yourself takes courage. It is to become vulnerable, and is a commendable step for people with less supportive environments. You are spreading your arms wide and saying here I am, this is my mark. I want to show you what I am proud of, what I think makes me valuable, how I act, and how I think. Many people have become social through these personal brands only in the way today’s Internet understands social interaction. It never requires any physical presence to create a brand with a social appearance. The stereotype of a basement dweller can be one of your most prolific sources of information and have an extremely valuable personal brand.

Be the authority on your personal brand

Why do we take the risk in curating a personal brand? Because there is no other option to create opportunity besides a true network of people who know you. That true strongly linked network will have a short reach, and has the chicken and the egg problem. You can create a larger weaker linked network that has a long reach in your spare time. These personal brands persist beyond social networks that rise and fall, and so long as you maintain them they will be the single source of information on you and your curated personal brand. Your guest posts to other blogging platforms could vanish overnight, or the platform might decide that they want to kill a feature that you’ve invested time in. The longer you own your personal brand’s domain name the more value it has. So take a look at your own footprints across the sites you use, and objectively see if you’re creating a brand you’d be proud of. Then take ownership of your personal brand and stake your claim for your online presence.

IE9 crashes when dragging, scrolling, and updating styles

Internet Explorer 9 was released 4 years ago in 2011 which sounds like a short time, but it really is an eternity in the world of web development. IE has had 3 releases since then and the 4th is on the horizon, but the upgrade cycle of many companies doesn’t reflect that fast pace. So we must continue to support IE9, and in doing so we will uncover more obscure bugs that will never see fixes.

This was the case recently when working on a grid view in JavaScript. A customer reported IE9 would crash, as in close the browser window down, when dragging a column to reorder them. They could drag the column in either direction and repeat the crash reliably. No error message, no where to clue where to start other that the drag action.

Since there were no error messages to go off of I used WinDbg after reading a MSDN blog post on debugging Internet Explorer. I had a virtual machine downloaded from After getting WinDbg hooked up to IE I set off to replicate the crash and had no trouble in doing so. The error message stack trace ended inside mshtml.dll, which is also known as Trident, the IE rendering engine.

Internet Explorer architecture

Internet Explorer architecture

WinDbg delivered the crash stack:

6D6DD5BB 81 3F D0 AD A3 6D cmp dword ptr [edi],6DA3ADD0h

mshtml.dll!CDispScroller::SetScrollOffsetInternal()	Unknown
mshtml.dll!CDispScroller::SetScrollOffset(class CSize const &,int,bool,enum tagCOORDINATE_SYSTEM)	Unknown
mshtml.dll!CDragDropManager::DragOver(unsigned long,struct _POINTL,class CSize const &,unsigned long *)	Unknown
mshtml.dll!CDoc::DragOver(unsigned long,struct _POINTL,class CSize const &,unsigned long *)	Unknown
mshtml.dll!CDoc::DragOver(unsigned long,struct _POINTL,unsigned long *)	Unknown
mshtml.dll!CDropTarget::DragOver(unsigned long,struct _POINTL,unsigned long *)	Unknown

Looking at the ScrollOffsetInternal function I suspected it might be in the CSS positioning of the grid area. It was able to scroll left and right as the user dragged for a wider-than-browser grid. I removed all positioning from the element and was still able to get the crash. I lost the crash log that had the right clue, which is the one I got when I removed the positioning classes. The log mentioned CSS colors, paint, and I remembered that there was a hover on the columns as you dragged over them to indicate which one was active. I removed the class, and couldn’t crash the browser! However I lost that visual cue, and though I discovered the issue I wanted to keep the existing functionality in place.

The problem was in the timing. When we hit the drag enter event we would check to see if the element is a valid target, then add the class which changed the look. The crash happened when dragging an element, scrolling the element container, and updating the drag enter target’s parent class when it was outside the container. That update caused an attempt at a paint, which ultimately took down the browser on a null exception. WinDbg even let me walk through the assembly instructions to see Trident was trying to perform a math operation at the time. The solution was easy, just update the CSS on the next event and not in the same one. So now we drag and scroll, then update the style using setTimeout pushing that action off to the JavaScript event stack.

The older technology gets and the more you continue to have to use it necessitates learning new tools to take the investigation into your own hands. Don’t be afraid of debugging tools like WinDbg. It didn’t give me the answer outright, and Trident is closed source but the stack trace gave me some logic to follow. It gave me the clues I needed to deduce the problem and come up with a solution that not only works, but one that I understand why I had to add that setTimeout.