This isn't a horrible example piece of code but it is missing the output. It does eliminate the idea that the child window is really a div in the same DOM as the parent window. The fact that it 'worked a few times' indicates that a child window does exist but the majority of the time your code is not detecting the child window.
This hints at a timing issue. Whenever I see intermittent behavior I suspect timing is the issue. The easiest way to test this theory is adding large sleep statements. I created two html pages. The first page is called 'index.html' and it contains a link which opens a new window called 'child.html'. The index.html title is 'index' and the child.html title is 'child'. If I use:
driver.get("file:///Users/darrellgrainger/index.html");
driver.findElement(By.cssSelector("#link2")).click();
Set<String> handles = driver.getWindowHandles();
for(String handle : handles) {
driver.switchTo().window(handle);
System.out.print(handle + ": ");
System.out.println(driver.getTitle());
}
It opens index.html, clicks the link then iterates over the window handles. This seems to work well when dealing with static html pages. If your html is using AJAX and is very javascript heavy then it is possible that the title of the page isn't available the moment the page is loaded. This means you need to wait for the title to exist. It could even mean you have to wait for the child window to exist. For example, I click the link which opens the child window. It then runs a LOT of javascript or conducts AJAX calls. Only after the javascript finishes then it opens the child window. If your Selenium code is attempting to find the child window and the web page is still processing javascript then the child window won't exist and your code will fail.
The way to test this is:
driver.get("file:///Users/darrellgrainger/index.html");
driver.findElement(By.cssSelector("#link2")).click();
Thread.sleep(10000);
Set<String> handles = driver.getWindowHandles();
for(String handle : handles) {
driver.switchTo().window(handle);
System.out.print(handle + ": ");
System.out.println(driver.getTitle());
}
In this example I click the link to make the child window appear but then I sleep for 10 seconds before checking for the child window. If this works 100% of the time then the theory is correct. We have to wait for something to complete before the child window appears. If we know a child window will be created then we could do something like:
int n = driver.getWindowHandles().size();
int attempts = 0;
// do the action which causes a child window to appear
while ((driver.getWindowHandles().size() == n) && attempts < 30) {
Thread.sleep(100);
attempts++;
}
If we are waiting 100ms between checks for 30 iterations then this will wait 3 seconds before it gives up. You can play with the numbers to wait longer or shorter as you see fit. However, when this loop finishes if the attempts reach the maximum or Selenium finds the child window. So if attempts == 30 is false we could assume the child window is present and we can switch to it. Now this all assumes that my theory is correct. If it is something else we'll have to come up with another theory and test that theory.