Thursday, July 26, 2012

Removing logout button

When I set up a Selenium Server it only works when someone is logged in. In a previous article I wrote how to make a user automatically log in. For this article I'll write how to prevent that user from logging out.

  1. Run regedit.exe
  2. Go to HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Policies
  3. Create a new Key called Explorer
  4. Go to Explorer folder
  5. Create the DWORD key StartMenuLogoff.
  6. Set it to 1.
  7. Go to the Start Menu and use Shutdown or Reboot (so Logoff is not the last option used).
When you log in as that user now, they will not have a Logoff button available to them. This has been tested on Windows 7.


automatic log in, automatic run

When writing test scripts for testing an installer, on Windows, one of the challenges is when the installer requires a reboot. To handle this I use automatic log in and the run once features of Windows.

To create automatic log in:
  1. Run regedit.exe
  2. Go to HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon
  3. Set DefaultUserName to the name of the person you want to automatically log in. If the key does not exist add it as REG_SZ.
  4. Set DefaultPassword to the user's password. If the key does not exist add it as REG_SZ. Note: anyone who can read the registry can see the user's name and password. Create a local user with no permission on your network.
  5. Set AutoAdminLogon to 1. If the key does not exist add it as REG_SZ.
  6. Set ForceAutoLogon to 1. If the key does not exist add it as REG_SZ.
And that is all you need to have the computer automatically log in after a reboot.

The second part is to create a script which will start up the automation at the right place. What usually happens is the installer will put something in place so that after the reboot it will continue with the install the moment the user logs in. If this is the case for your installer, write a script which continues the automation and add it to the RunOnce key. Assuming you have a batch file which starts part 2 of your automation:
  1. Run regedit.exe
  2. Go to HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\RunOnce
  3. Add a string value
  4. The Name of the should be something like zzz_Automation
  5. The Data value will be the full path to the batch file. It is important to note that the current directory will not be the location of the batch file. Do not assume it will be in your script. Either use full paths for everything in the script or change to the directory you think you should be in then continue with the script.
Enjoy.


Tuesday, July 24, 2012

Generating a screen capture when using RemoteWebDriver

Recently I was asked if all the different implementations of WebDriver allow for screen captures. I had a look at the source code and see that almost all of them "implement TakesScreenshot". If the Java class for the driver implements TakeScreenshot then it allows for screen captures. This means a previous posting (http://darrellgrainger.blogspot.ca/2011/02/generating-screen-capture-on-exception.html) there isn't really any need for using Robot to generate the screen capture.

The nicest thing about using the built-in screen capture is that Robot will capture the visible screen. The built-in screen capture will capture the entire window in the browser, including the parts not visible, i.e. things you have to scroll to see.

Shortly after this someone asked of RemoteWebDriver supported screen capture. This was very important because Robot would not capture even the visible part of a REMOTE screen.

A quick check of RemoteWebDriver.java showed that it did NOT implement TakesScreenshot.

Recently however I found a solution. Assuming you have the code:
DesiredCapabilities dc = DesiredCapabilities.firefox();
URL url = new URL("http://localhost:4444/wd/hub");
WebDriver driver = new RemoteWebDriver(url,dc);
You can change the driver to:
WebDriver driver = new Augmenter().augment(new RemoteWebDriver(url,dc));
Now it has the capability to take a screen shot. To make the call, here are the three different outputs:
File f = ((TakesScreenshot)driver).getScreenshotAs(OutputType.FILE);
String s = ((TakesScreenshot)driver).getScreenshotAs(OutputType.BASE64);
byte[] b = ((TakesScreenshot)driver).getScreenshotAs(OutputType.BYTES);


And that is all there is to taking a screenshot with RemoteWebDriver. I have tried this with Firefox and InternetExplorer. I assume it works with the other browsers but I leave that for you to explore.

Wednesday, July 4, 2012

Creating a screen capture on every action

Someone recently commented on an article I wrote about generating a screen capture when an exception is thrown (see Generating a screen capture on exception thrown with Selenium 2).

Performing an action when an exception is thrown is built into the Selenium framework. You just need to create the action to generate a screen capture and hook it into the framework.

The Selenium framework comes with a WebDriverEventListener interface. In my article above I created an implementation of the WebDriverEventListener interface. To do this properly, you need to implement the following methods:
beforeNavigateTo(String url, WebDriver driver);
afterNavigateTo(String url, WebDriver driver);
beforeNavigateBack(WebDriver driver);
afterNavigateBack(WebDriver driver);
beforeNavigateForward(WebDriver driver);
afterNavigateForward(WebDriver driver);
beforeFindBy(By by, WebElement element, WebDriver driver);
afterFindBy(By by, WebElement element, WebDriver driver);
beforeClickOn(WebElement element, WebDriver driver);
afterClickOn(WebElement element, WebDriver driver);
beforeChangeValueOf(WebElement element, WebDriver driver);
afterChangeValueOf(WebElement element, WebDriver driver);
beforeScript(String script, WebDriver driver);
afterScript(String script, WebDriver driver);
onException(Throwable throwable, WebDriver driver);
In my screen capture when an exception is thrown, I put the necessary code to generate a screen capture in the onException method. You can see from the list above that you can have Selenium perform an action when other events occur. For example, if you wanted to do a screen capture after each click() action, you could write:

public void afterClickOn(WebElement element, WebDriver driver) {
    String filename = generateRandomFilenameFromWebElementAndDriver(element, driver);
    createScreenCaptureJPEG(filename);
}

I'll leave it to the reader to figure out how to create the generateRandomFilenameFromWebElementAndDriver. You might do something like use getCurrentUrl(), convert things like colon, slash, etc. into valid filename characters then append the web element getTagName() to the end of the filename.

Or you could do something tricky like have the beforeClickOn generate the filename and the afterClickOn use that filename to generate the screen capture.

If the event you want to trigger a screen capture is not listed above, there is no easy answer for how you would do it.

Initially, you might considering changing the WebDriverEventListener interface. But this would require a change to how Selenium works. Every time there is a new release of Selenium, you would have to merge your changes back in.

I would recommend submitting the changes as a new feature to the Selenium project to see if they'll incorporate it or wrap the Selenium methods with your own methods. For example, you would call your sendKeys() which could do a driver.sendKeys then do a screen capture.