Google Analytics

Tuesday, January 28, 2014

Forcing a remote computer to restart

Occasionally I find I need to reboot a remote computer. In my current situation the remote computer is Windows XP and accessed via VNC. However the VNC server will occasionally stop responding.

If the machine's IP address was 1.2.3.4 and I try:
shutdown /m 1.2.3.4 /r /t 1
it does not reboot the computer. Assuming there is nothing to save on the computer and I just want it to reboot and restart the services, I am happy to just kill processes until I hit something critical and it reboots.

However, if you hit the RPC process, you will be unable to send the command to kill more processes. So you have to be careful about which process you are killing. What I have found is killing the lsass.exe process will cause the computer to reboot. So issuing:
taskkill /im "lsass.exe" /s 1.2.3.4 /f
Will kill the lsass.exe proccess on the remote machine and force a reboot of that computer. The reboot will not be immediate. A 30 second countdown will happen as the system warns you a critical process was killed. However it will reboot the computer after the countdown is complete.

Friday, November 29, 2013

Browser statistics


A lot of discussion goes into browser statistics. Whenever a company is creating a new web application they need to decide which browsers will be supported and their order of importance.

Years ago it was a given that Internet Explorer was the #1 browser. Just the shear volume of Windows users and lack of serious competition in that area made Internet Explorer the dominant browser.

Then along came Firefox and later Chrome. Additionally, Mac Desktop is becoming a large enough market that Safari is worth considering.

So how do we decide which browsers we should support and what order we should rank them in?

There are many sites which give statistics on browser usage:
W3 SchoolsStatCounterW3 CounterClickyNetMarketShareWikiMedia
and probably a whole lot more to check. If we look at the different sites we can see some radically different numbers. Some claim Chrome is close to 60% of the market. Others have Chrome around 30% of the market.

Why the big difference? Different sites will gather statistics on different people. The W3 Schools site is very popular among programmers and software testers. I tend to like Chrome because it has the built-in Inspect feature and other helpful development tools. Firefox is okay when you install Firebug or other tools but often we want to test with a clean browser and don't have these tools available.

Starting with Internet Explorer 8 it came with development tools. The tools in Internet Explorer 9 are better but nothing as good as the tools in Firefox or Chrome. So Chrome and then Firefox are going to be the browser of choice for programmers and software testers.

Not surprisingly, W3 Schools is the site which claims Chrome is almost 60% of the market. But it will be biased towards power users, programmers and testers. My mother doesn't use a computer. If she did it would be a Windows 7 with Internet Explorer 11 or a Mac with Safari 6.1.

So which statistics site you select depends on your target audience. You don't want to use the statistics from W3 Schools if your target audience is my mom.

What if you have a website and you are going to be updating it or adding another website with the same target audience? Then you have been hopefully gathering statistics on your existing website. Statistics from your existing website will tell you exactly who your users are. If you statistics say that 97% of your users are using Internet Explorer 6 then you need to support Internet Explorer 6. You could make it painless to upgrade your existing user base to a new version of the same browser but odds are it is safer to just support what your users are using.

The only time I would say you might not want to completely follow the statistics on an existing website would be if you are attempting to grow your market and know the new customer base is going to be a different type of user. Let's say that my user base is traditionally Internet Explorer users but I want to start targeting Mac users. I want to make sure that I don't sacrifice existing users for the new user base. So I will continue to value the Internet Explorer users but I want to start looking at statistics for when the operating system is Mac OS X. If I drill down to just Mac OS X users, which is the dominate browser?

In addition to which browser there is also the resolution for the display. This tends to be a little easier to decide if we are talking desktop. You pick the small display which is widely supported. Originally, I would design a website so it looked good on 640x480. Then the average display was 800x600. Later we would start seeing wide displays like 1440x900. I found it easiest to set a minimum size that would be supported. So you don't want so many things on a menu that the menu is longer than say 600 pixels high if you supported 800x600. We can use tools to resize the browser to the different sizes and make sure things still look good. This is easy to do on pretty much any desktop today.

Back in the days of EGA and VGA the number of colours you would support was an issue but today it isn't really something people worry about any more.

This is how I generally recommend clients decide on which desktop browsers to support. It does not really address the idea of mobile browsers. This is an area which is still in flux. I see a lot of different mobile browsers. My own personal experience has been updating my browser can make it more unstable. So if I have a browser which runs on my device I'll stick with it. However, if I get a new device I tend to find the newer browsers come with it and run better than old browsers. So you should be seeing a wider range of browsers on mobile devices than on desktops. Additionally, mobile devices include smart phones and tablets. There are full size tablets, mini tablets, large smart phones, medium smart phones and small smart phones. The different resolutions can vary much more than desktop devices.

Additionally, I cannot take a large device and resize the browser to small sizes. The idea of a window on a desktop doesn't exist on many mobile devices. So testing on the different resolutions is a major concern. Fortunately, with emulators you can run a software emulated version of a device and check that the website displays properly on it. Or you can use features of our existing browser to pretend to be a specific mobile device. This will change the size and User-Agent information to make your web application display as if it was getting rendered on a mobile device. Again, Chrome Inspect has some built-in features in this area which are quite helpful. They should not replace emulators or even better actual devices when doing system testing.

Ideally, in a test lab I will have all the machine with the largest display we want to support. I will then use a virtual computer player like Virtual PC, Parallels, VMware, etc. to emulate all the other operating systems. A Mac works really well because you can use it to run Mac browsers, a virtual PC like Parallels or Fusion to run Windows, Linux and Solaris x86, XCode to emulate iOS devices and Eclipse or IDEA to emulate Android devices.

If the client runs mostly Microsoft products and Mac isn't a concern then you can use Virtual PC on a Windows 7 device to run Windows XP and Windows 7 virtual machines for free.

For virtualizing all the Windows machines right now you can go to http://www.modern.ie/en-us/virtualization-tools#downloads to download virtual machines for Windows XP, Windows 7 and Windows 8. Everthing from Internet Explorer 6 to Internet Explorer 11.



Thursday, November 28, 2013

Opening two windows for one WebDriver

I'm currently testing a project with two applications. The first is an administrator tool for updating/modifying the customer site and the second is the actual customer site.

There are three ways to test a project like this. The first is creating one instance of WebDriver and access each application one at a time, e.g.

WebDriver driver = new ChromeDriver();
driver.get(adminToolURL);
// do some admin stuff
driver.get(customerSiteURL);
// do some site stuff

The second would be to create two instances of WebDriver. One to access the admin tool and the other to access the customer site, e.g.

WebDriver adminDriver = new ChromeDriver();
adminDriver.get(adminToolURL);
WebDriver driver = new InternetExplorerDriver();
driver.get(customerSiteURL);
// do some admin stuff with adminDriver
// do some site stuff with driver

The nice thing about this scenario is that you might have different browser requirements. The admin tool only has to work with one browser and the customer site has to work with a variety of browsers. So I can hard code the adminDriver to one browser and configure the test framework to change the browser. Run 1, InternetExplorerDriver; run 2, ChromeDriver; run 3, SafariDriver; etc.

The third way is to create one instance of WebDriver and open two windows. If you use the driver.get() method, it will open the site in the current window. To open a second window you'll need to use something in Selenium to force a second window. The trick is to use JavascriptExecutor to run javascript which opens a second window, e.g.

WebDriver driver = new ChromeDriver();
driver.get(adminToolURL);
Set<String> windows = driver.getWindowHandles();
String adminToolHandle = driver.getWindowHandle();
((JavascriptExecutor)driver).executeScript("window.open();");
Set<String> customerWindow = driver.getWindowHandles();
customerWindow.removeAll(windows);
String customerSiteHandle = ((String)customerWindow.toArray()[0]);
driver.switchTo().window(customerSiteHandle);
driver.get(customerSiteURL);
driver.switchTo().window(adminToolHandle);

The first two lines are straight forward and open a window with the admin tool. The next few lines does the following: get a list of the currently open windows, save the window handle for the admin tool window, open a new window using executeScript, get a second list of the currently open window (this will be the same as the first list PLUS the new window). Next remove all the original windows handles from the second list. This should leave the second list (customerWindow) with only one window handle, e.g. the new window. The last three lines show you how to switch between the customer site window and the admin tool window.


Thursday, October 31, 2013

WebDriverWait

In an older article I wrote about a method I created called waitForElement. After looking through some of the WebDriver code I found WebDriverWait. You should read the original article before you read this one.

The WebDriverWait class extends FluentWait<WebDriver> which is a special version of FluentWait which has WebDriver instances.

In the article for waitForElement I was talking about how Selenium cannot detect that Javascript has finished altering the DOM. So if you try to interact with an element with Selenium and Javascript is still altering it, you will have undefined results. The waitForElement method would wait for the element to be full rendered, i.e. for the Javascript to be finished. The WebDriverWait serves the same purpose.

To define a WebDriverWait would be the following:
WebDriverWait wdw = new WebDriverWait(driver, timeoutInSeconds, pollingTimeInMs);
The first parameter is an already existing WebDriver element. The second parameter is how long we want to wait for the element to be present. If we set it to say 30 it will wait for 30 seconds before it throws an error. The third parameter is how often you want to check for the element. If you set it really low, e.g. 10, it will check every 10 milliseconds. However this could put a load on the test machine. If you know it typically takes 55 milliseconds then maybe waiting for 60 would be best. You would not want to wait for 1000 milliseconds as it would make your test too slow.

This just creates the WebDriverWait object. It doesn't actually do the waiting. Let's say you click the ACCEPT checkbox. This causes Javascript to make the Next button visible. If you just click the ACCEPT checkbox then click the Next button it might fail because the Next button isn't visible as quickly as you can click it. So you need to click the ACCEPT checkbox, wait for the Next button to be visible then click the Next button. Here is some example code:
long timeoutInSeconds = 30;
long pollingTimeInMs = 250;
WebDriverWait wdw = new WebDriverWait(driver, timeoutInSeconds, pollingTimeInMs);
wdw.until(visibilityOfElementLocated(By.id("next"))).click();
This will check every 250 milliseconds to see if the element located by id='next' is visible. If the element does not become visible in 30 seconds it will fail the step and throw an error.

The list of conditions you can wait for are:
presenceOfElementLocated(by);
visibilityOf(driver.findElement(by));
alertIsPresent();
elementSelectionStateToBe(by, true);
elementSelectionStateToBe(we, true);
elementToBeClickable(by);
elementToBeSelected(by);
frameToBeAvailableAndSwitchToIt(frameLocator);
invisibilityOfElementLocated(by);
invisibilityOfElementWithText(by,text);
presenceOfAllElementsLocatedBy(by);
textToBePresentInElement(by, text);
textToBePresentInElementValue(by, text);
titleContains(title);
titleIs(title);
visibilityOf(we);
visibilityOfElementLocated(by);
The WebDriverWait also lets you alter the polling time, timeout, message displayed when it times out and exceptions it should ignore while waiting:
wdw.pollingEvery(delayBetweenPolling, TimeUnit.MILLISECONDS)
.ignoring(NoSuchElementException.class)
.withTimeout(timeoutInSeconds, TimeUnit.SECONDS)
.withMessage(message)
.until(visibilityOfElementLocated(By.id("next"))).click();
Because you can set the unit of measure for polling time and timeout, you can refine these after you instantiate the WebDriverWait object.

.

Saturday, October 26, 2013

Windows Server and WebDriver

From time to time I see people trying to use Windows Server (2003 or 2008 R2) to run WebDriver scripts on Internet Explorer. They are posting to the WebDriver Google Group because it is not working and they are looking for answers on how to make it work.

The problem is they are asking the wrong question. They should not be asking, "How do I use WebDriver tests on Windows Server?" They should be asking, "Why don't my tests, which run on Windows XP or Windows 7, run on Windows Server 2008 R2?"

The answer is that Windows Server is not meant for people to use for surfing the web. They provide Internet Explorer if you need to access a local web application. You can explicitly add in trusted sites. But you cannot use it the way you would Internet Explorer on a Windows Workstation (like Windows XP, Windows 7 or Windows 8).

For more on this read the posting in Microsoft Developer Network: Enhanced Security Configuration for Windows Internet Explorer. The most important thing to note from this posting is the first two sentences:

As a best security practice, a server administrator should not browse Internet Web sites from the server. The administrator should only browse the Internet from a limited user account on a client work station to reduce the possibility of an attack on the server by a malicious Web site.

If you are really bent on using Windows Server there are ways to alter things but you will have to read the documentation on each version of Internet Explorer to understand how to do it.

The instructions for making Internet Explorer 7 on Windows Server 2003 work with Selenium will be different from getting Internet Explorer 8 on Windows Server 2008 R2 working with Selenium. Even getting Internet Explorer 9 on Windows Server 2008 R2 will be different as well. Microsoft is always changing what things are locked down and how you unlock them.

You should also realize that no respectable system administrator is going to use Windows Server to access a web application. They will use Virtual PC or a real Windows Workstation to access web applications. Therefore testing the application works okay with Internet Explorer on a Windows Server is not a configuration which should be supported. It does not test that the application runs on a real supported configuration, i.e. Internet Explorer on a Windows Workstation.

Monday, September 23, 2013

Dealing with HTTP Basic Authentication

If you go to a website and it has HTTP Basic Authentication turned on it will pop up a dialog asking you for username and password.

You can pass this information in the URL so the dialog does not pop up. This will allow you to go to these websites with automation tools like Selenium.

For example, if you go to httpwatch and click on the Display Image button it will pop open a dialog asking you for a username and password. For this site you can enter httpwatch for the username and any string for the password. So if I go to:

http://httpwatch:password@www.httpwatch.com/httpgallery/authentication/

then click the Display Image button, it will not pop open a dialog. This is because I have already been authenticated on the website.

HOWEVER, this will not work with current web browsers.

The reason for this is because web browser manufacturers recognized the fact that people can use this URL format to create fake websites. For example, I could have a website at 10.23.56.234, turn on basic authentication and make the username www.microsoft.com. I then send out an email with the URL:

http://www.microsoft.com:80@10.23.56.234/survey.html

This URL will go to my fake website with the username:password of www.microsoft.com:80. Some people might be tricked into thinking they are going to www.microsoft.com.

Fortunately, you can turn this feature back on.

For Internet Explorer you can make it accept the above URLs. It does open you up to someone spoofing you. So do this to a test machine, used only for automation, is okay. Using this on the computer you use to surf the web is a back idea.

If you go to http://support.microsoft.com/kb/834489/EN-US it will explain all the above. At the bottom it will talk about how to enable using username:password in the URL. In a nutshell, do the following:

  • Open regedit.exe
  • Find the key HKEY_LOCAL_MACHINE\Software\Microsoft\Internet Explorer\Main\FeatureControl\FEATURE_HTTP_USERNAME_PASSWORD_DISABLE
  • Create the DWORD iexplore.exe=0
By setting iexplore.exe to 0 you are disabling the disabling of username:password, i.e. double negative.

If you are running 32-bit Windows this works as stated. If you are running 64-bit Internet Explorer on 64-bit Windows this works as stated. However, if you are running 32-bit Internet Explorer on 64-bit Windows this does not work. By default, 64-bit Windows 7 will run 32-bit Internet Explorer.

When you look in the registry, all the settings for 32-bit programs on a 64-bit computer will be in the WOW6432Node. So rather than HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft you want to go to HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Microsoft.

For Chrome & Firefox, they should support basic authentication through the URL.

For Safari, go into the Preferences, go to the Security tab and disable Warn when visiting a fraudulent website.

In summary, if I have the Selenium Java code:


    driver.get("http://www.httpwatch.com/httpgallery/authentication/");
    driver.findElement(By.cssSelector("#displayImage")).click();
    WebElement img = driver.findElement(By.cssSelector("#downloadImg"));

It will never make it to the third line because the .click() will bring up an HTTP basic authentication dialog which will block Selenium. Instead, I would use:

    driver.get("http://httpwatch:password@www.httpwatch.com/httpgallery/authentication/");
    driver.findElement(By.cssSelector("#displayImage")).click();
    WebElement img = driver.findElement(By.cssSelector("#downloadImg"));

.

Thursday, August 29, 2013

Little discussed Java classes in WebDriver

Sleeper

Recently I have been exposed to classes in WebDriver that I did not know existed. I started with Selenium when it was beta and found myself inventing methods to do things for Selenium and later for WebDriver. So I never really looked at the extra capabilities for WebDriver. Even before Selenium I often needed to write code that slept for a few seconds. The proper way to use the Thread.sleep method would be:

    public void sleep(long ms) {
        try {
            Thread.sleep(ms);
        } catch(InterruptedException ie) {
            throw new RuntimeException(ie);
        }
    }
Today I decided to scan through the WebDriver APIs. While I was doing this I found the Sleeper class. It has two APIs which are nice to use. Rather than using the method above you can use:
    sleepTight(2000);        // sleep for 2000 milliseconds
    sleepTightInSeconds(2);  // sleep for 2 seconds
SystemClock

Another helpful class I found was the SystemClock class. It implements the Clock interface and has three functions:

    SystemClock sc = new SystemClock();

    long current = sc.now();
    long early = sc.laterBy(-60000);
    long later = sc.laterBy(60000)
    System.out.println(sc.isNowBefore(later));  // true
    System.out.println(sc.isNowBefore(early));  // false
    System.out.println(sc.isNowBefore(now));    // false
The value of 'current' will be the timestamp of now. It is similar to using System.currentTimeMillis() and the API docs actually refer to System.currentTimeMillis(). Obviously, the command immediately after sc.now() will be greater than 'current' just because the call to sc.now() will take some time. The class also has the laterBy method. It talks about passing it a positive long but you can actually pass a negative number. In this case I passed in -60000. The value is in milliseconds. So this would be -60 seconds from 'now'. The third line sets later to 60 seconds later. A few milliseconds will have passed so if the time was 1377825553203 when I called sc.now() then sc.isNowBefore() get called and set 'now' to a few milliseconds later. Maybe 'now' will be 1377825554713. So sc.isNowBefore(later) will be true because later will be around 1377825553203 + 60000 and therefore later than 'now'. Where as sc.isNowBefore(early) will be false because 'now' will be after 1377825553203 - 60000. The odd one is sc.isNowBefore(current). This is because 'current' was now when it was set but a few lines later and 'now' will be after 'current', i.e. now > current, and sc.isNowBefore(current) will be false.

ThreadGuard

This class is more for people writing multi-threaded tests. It is rare for me to write multi-threaded tests. Hopefully you will never have to go there but if you do it is important to know that the implementations of WebDriver (ChromeDriver, FirefoxDriver, InternetExplorerDriver, etc.) are not guaranteed to be thread safe. To make them thread safe you can use the ThreadGuard class. It is actually pretty simple to use. If you have:

    WebDriver driver = new FirefoxDriver();
You can make it thread safe by changing it to:
    WebDriver driver - ThreadGuard.protect(new FirefoxDriver());
It is that simple. I won't get into why you are using multi-threaded tests. If you don't know if you are using multi-threading then you are probably not using multi-threading.

UrlChecker

UrlChecker is also a helpful class. It checks to see if a URL is returning an HTTP response of 200 OK. You could use it to check for a URL existing before you navigate to it or do a if URL does not exist then go to a different URL. For example,

    try {
        UrlChecker uc = new UrlChecker();
        String testURL = "http://localhost:8080/testapp/index.html";
        uc.waitUntilAvailable(5, TimeUnit.SECONDS, new URL(testURL));
        driver.get(testURL)
    } catch(UrlChecker.TimeoutException te) {
        // if the testURL does not become available in 5 seconds
        // this code will be run
    } catch(MalformedURLException mue) {
        // needed by URL class
        // if you think the testURL might be malformed handle it here
    }

Urls

This class has two helpful static methods:

    String testURL = "http://localhost:8080/~darrell/tests/#/";
    System.out.println(Urls.toProtocolHostAndPort(testURL));
    System.out.println(Urls.urlEncode(testURL));
The first println will print "http://localhost:8080". As URLs go, the /~darrell/tests/#/ is the context root. If you try going to "http://localhost:8080" it must have a context root. It will just assume you meant "/" for the context root. The second println will print "http%3A%2F%2Flocalhost%3A8080%2F%7Edarrell%2Ftests%2F%23%2F". All the symbols are converted to their ASCII hexidecimal value prefixed with a percent symbol. So for example, %3A is a :, %2F is a /, %7E is a ~ and %23 is the #. There are other interesting classes in WebDriver but these are the less used/discussed classes. Other classes like WindowsUtils have enough happening that they really need their own article. I will say that the following are some interesting classes which require more investigation:
  • FluentWait
  • Platform
  • ProcessUtils
  • Select
  • Wait
  • WindowsUtils