I was recently pointed to a nice list of Selenium/WebDriver blogs. If you are looking for more information about Selenium/WebDriver you should check out http://it-kosmopolit.de/Selenium/blog/selenium-blogs/selenium_blogs.php.
I haven't checked out all the links but there appears to be a good start to the list of Selenium/WebDriver blogs available out there.
Google Analytics
Search
To search for specific articles you can use advanced Google features. Go to www.google.com and enter "site:darrellgrainger.blogspot.com" before your search terms, e.g. site:darrellgrainger.blogspot.com CSS selectors will search for "CSS selectors" but only on my site. |
Tuesday, November 27, 2012
Monday, October 29, 2012
Generating a file of a specific size
Every once in a while someone is looking for a file of a specific size. Occasionally, it must be real data. If you are transmitting the file and the data will be compressed then the type of data will make a difference.
However, if you just need a file to fill some space or there will be no compression then Windows has a neat little utility called FSUTIL.
The FSUTIL file can be used for a number of things but the nicest feature is creating a new file filled with zero bytes. First, you need to know how many bytes. If you want a file which is 38 gigabytes then you need to figure out how many bytes that is. Technically, it is 1024*1024*1024*38. If you want a rough idea you can just use 38,000,000,000 but a 38 gigabyte file is really 40,802,189,312. Next is which file you want to hold the data. Let's say you want to create C:\DELETEME.TXT then the full FSUTIL command is:
However, if you just need a file to fill some space or there will be no compression then Windows has a neat little utility called FSUTIL.
The FSUTIL file can be used for a number of things but the nicest feature is creating a new file filled with zero bytes. First, you need to know how many bytes. If you want a file which is 38 gigabytes then you need to figure out how many bytes that is. Technically, it is 1024*1024*1024*38. If you want a rough idea you can just use 38,000,000,000 but a 38 gigabyte file is really 40,802,189,312. Next is which file you want to hold the data. Let's say you want to create C:\DELETEME.TXT then the full FSUTIL command is:
fsutil file createnew C:\DELETEME.TXT 40802189312
This will create a 38G file is a matter of seconds.
For UNIX, Mac OS X or Linux you can use DD. The DD command is for converting and copying files. If we wanted to create the 38G file with DD the command would be:
dd of=deleteme.txt oseek=79691776
The oseek is the magic. It will seek n*512 bytes. The standard size of a block is 512. So we take 79691776*512, which is 38G. Even easier would be:
dd of=deleteme.txt oseek=38m obs=1024
This will generate a file of 38M * 1024 or 38G. Much easier to figure things on working with values like these. That is, no need for a calculator.
IMPORTANT: after you press enter on the DD command it will take the standard input as its input. So you need to enter CONTROL-D.
The other option for UNIX/Linux/Mac OS X is to copy a file of a set size. The nice thing about this is you can take a file with real data and copy it enough times to make a single file of the correct size. For example, if I have a text file with 512 bytes of real data I can set the if= to that file and make multiple copies of that one file into the output file.
Labels:
Linux,
Quality Assurance,
testing,
tips,
UNIX
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.
- Run regedit.exe
- Go to HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Policies
- Create a new Key called Explorer
- Go to Explorer folder
- Create the DWORD key StartMenuLogoff.
- Set it to 1.
- 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:
To create automatic log in:
- Run regedit.exe
- Go to HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon
- 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.
- 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.
- Set AutoAdminLogon to 1. If the key does not exist add it as REG_SZ.
- 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:
- Run regedit.exe
- Go to HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\RunOnce
- Add a string value
- The Name of the should be something like zzz_Automation
- 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.
Labels:
automation,
Windows
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:
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.
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:Now it has the capability to take a screen shot. To make the call, here are the three different outputs:WebDriver driver = new Augmenter().augment(new RemoteWebDriver(url,dc));
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:
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.
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);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:
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);
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.
Wednesday, June 20, 2012
StaleElementException
Most automation tools depend on the concept of the page has finished loading. With AJAX and Web 2.0 this has become a grey area. META tags can refresh the page and Javascript can update the DOM at regular intervals.
For Selenium this means that StaleElementException can occur. StaleElementException occurs if I find an element, the DOM gets updated then I try to interact with the element.
Actions like:
Generally speaking, if you know the page has Javascript which automatically updates the DOM, you should assume a StaleElementException will occur. It might not occur when you are writing the test or running it on your local machine but it will happen. Often it will happen after you have 5000 test cases and haven't touched this code for over a year. Like most developers, if it worked yesterday and stopped working today you'll look at what you changed recently and never find this bug.
So how do I handle it? I use the following click method:
The method takes as input a locator for the element you want to click. If it is successful it will return true. Otherwise it returns false. If it makes it past the click call, it will return true. All other failures will return false.
Personally, I would argue this should always work. If the developers are refreshing the page too quickly then it will be overloading the browser on the client machine.
For Selenium this means that StaleElementException can occur. StaleElementException occurs if I find an element, the DOM gets updated then I try to interact with the element.
Actions like:
driver.findElement(By.id("foo")).click();
are not atomic. Just because it was all entered on one line, the code generated is no different than:
By fooID = By.id("foo");
WebElement foo = driver.findElement(fooID);
foo.click();
If Javascript updates the page between the findElement call and the click call then I'll get a StaleElementException. It is not uncommon for this to occur on modern web pages. It will not happen consistently however. The timing has to be just right for this bug to occur.Generally speaking, if you know the page has Javascript which automatically updates the DOM, you should assume a StaleElementException will occur. It might not occur when you are writing the test or running it on your local machine but it will happen. Often it will happen after you have 5000 test cases and haven't touched this code for over a year. Like most developers, if it worked yesterday and stopped working today you'll look at what you changed recently and never find this bug.
So how do I handle it? I use the following click method:
public boolean retryingFindClick(By by) {
boolean result = false;
int attempts = 0;
while(attempts < 2) {
try {
driver.findElement(by).click();
result = true;
break;
} catch(StaleElementException e) {
}
attempts++;
}
return result;
}
This will attempt to find and click the element. If the DOM changes between the find and click, it will try again. The idea is that if it failed and I try again immediately the second attempt will succeed. If the DOM changes are very rapid then this will not work. At that point you need to get development to slow down the DOM change so this works or you need to make a custom solution for that particular project.The method takes as input a locator for the element you want to click. If it is successful it will return true. Otherwise it returns false. If it makes it past the click call, it will return true. All other failures will return false.
Personally, I would argue this should always work. If the developers are refreshing the page too quickly then it will be overloading the browser on the client machine.
Subscribe to:
Posts (Atom)