11

Hi I am using selenium webdriver 2.25.0 & faceing the some serious issues,

  1. how to find broken images in a page using Selenium Webdriver
  2. How to find the image is replace by another image having same name (This is also bug) using webdriver.

Thanks in advance for your value-able suggestions.

Chetan
  • 2,360
  • 3
  • 18
  • 33

3 Answers3

14

The accepted answer requires that you use a proxy with an extra call to each image to determine if the images are broken or not.

Fortunately, there is another way you can do this using only javascript (I'm using Ruby, but you can use the same code in any executeScript method across the WebDriver bindings):

images = @driver.find_elements(:tag_name => "img")
broken_images = images.reject do |image|
  @driver.execute_script("return arguments[0].complete && typeof arguments[0].naturalWidth != \"undefined\" && arguments[0].naturalWidth > 0", image)
end
# broken_images now has an array of any images on the page with broken links
# and we want to ensure that it doesn't have any items
assert broken_images.empty?

To your other question, I would recommend just taking a screenshot of the page and having a human manually verify the resulting screenshot has the correct images. Computers can do the automation work, but humans do have to check and verify its results from time to time :)

Johnbo
  • 498
  • 6
  • 16
bbbco
  • 1,508
  • 1
  • 10
  • 25
9

The next lines are not optimized, but they could find broken images:

List<WebElement> imagesList = _driver.findElements(By.tagName("img"));
for (WebElement image : imagesList)
{
    HttpResponse response = new DefaultHttpClient().execute(new HttpGet(image.getAttribute("src");));
    if (response.getStatusLine().getStatusCode() != 200)
        // Do whatever you want with broken images
}

Regarding your second issue, I think I didn't understand it correctly. Could you explain it with more detail?

Johnbo
  • 498
  • 6
  • 16
  • Hi Johnbo, one image having name is "MyImage.jpg", first time i am executing my test script MyImage found. ok after some time developer changes on site & this "MyImage" is replace by other image having same name as "MyImage" (On images folder). Now, we execute test script MyImage found & our test script pass. but actually it is bug because in UI another image gets display. Thanks for your quick reply. – Chetan May 28 '13 at 09:12
  • 2
    As I see it, you need to store the image in the first execution so you can compare it next times, because from the HTML point of view the page could be exactly the same and Selenium wouldn't be able to find the images difference. Or maybe you could use Selenium in conjunction with an image recognizing tool like Sikuli Script. – Johnbo May 28 '13 at 09:59
  • i agree but all the images from web page is store & then compare, its not good according to performance. we can play with image size (i.e. we can store image size & compare image size next time). any idea please suggest. – Chetan May 28 '13 at 12:21
  • 1
    Take a full page screenshot and have a human manually check the results. – bbbco May 29 '13 at 11:56
2

Based on the other answers, the code that eventually worked for me in an angular / protractor / webdriverjs setting is:

it('should find all images', function () {
    var allImgElts = element.all(by.tagName('img'));

    browser.executeAsyncScript(function (callback) {
        var imgs = document.getElementsByTagName('img'),
            loaded = 0;
        for (var i = 0; i < imgs.length; i++) {
            if (imgs[i].naturalWidth > 0) {
                loaded = loaded + 1;
            };
        };
        callback(loaded);
     }).then(function (loadedImagesCount) {
        expect(loadedImagesCount).toBe(allImgElts.count());
    });
});

The webdriver code counts the number of img elements, and the function executed within the browser context counts the number of successfully loaded elements. These numbers should be the same.

avandeursen
  • 8,458
  • 3
  • 41
  • 51
  • The `allImgElts` in protractor-land is doing basically the same thing as the `imgs` inside browser-land, right? (I'm not really confident they are, so mostly I'm asking this.) But, if they were ... the only difference in lengths would be if any `img[i].naturalWidth <= 0`, right? So, it would be simpler and more efficient to skip the `allImgElts`, and have the browser-land script simply return the number of images with invalid natural width, and have protractor land expect that count to be 0? (You'll miss out on the fancy nested `then` which is a neat trick to see, though.) – P.T. Feb 07 '15 at 05:59
  • Yes, you're right. This can be simplified by returning the number of broken images as `imgs.length - loaded`, which you can then expect to be 0. Then the `allImgEtls` is not needed anymore indeed. – avandeursen Feb 07 '15 at 14:01