《手把手教你》系列技巧篇(四十二)-java+ selenium自動化測試 – 處理iframe -下篇(詳解教程)

1.簡介

  經過宏哥長時間的查找,終於找到了一個含有iframe的網頁。所以今天這一篇的主要內容就是用這個網頁的iframe,宏哥給小夥伴或者童鞋們演示一下,在處理過程中遇到的問題以及宏哥是如何解決的。

2.iframe是什麼

  iframe就是我們常用的iframe標籤:<iframe>。iframe標籤是框架的一種形式,也比較常用到,iframe一般用來包含別的頁面,例如我們可以在我們自己的網站頁面加載別人網站或者本站其他頁面的內容。iframe標籤的最大作用就是讓頁面變得美觀。iframe標籤的用法有很多,主要區別在於對iframe標籤定義的形式不同,例如定義iframe的長寬高。簡單的一句話概括就是:iframe 就是HTML 中,用於網頁嵌套網頁的。 一個網頁可以嵌套到另一個網頁中,可以嵌套很多層。和俄羅斯套娃差不多吧。

3.selenium處理iframe的方法

selenium提供了switch_to.frame(reference)方法來切換frame。reference是傳入的參數,用來定位frame,可以傳入id、name、index以及selenium的WebElement對象。

// 進入 id 叫frameA 的 iframe
dr.switchTo().frame("frameA");

// 回到主窗口
dr.switchTo().defaultContent();

4.項目實戰

 網上找了半天也沒有找到這樣的例子,以前12306的日曆是這種。最近升級了,已經不是這種了。完了就沒有找了,偶然發現QQ郵箱的登錄還是iframe這種方式的,所以宏哥就利用這個網頁給大家實戰演示一下。

4.1被測網址

1.被測網址的地址://mail.qq.com/

2.網頁如下圖(F12可以看到iframe標籤):

3.假設宏哥想要在qq郵箱輸入框輸入內容,輸入框的html代碼如下:

4.此時宏哥在QQ郵箱輸入框輸入內容的代碼如下:

package lessons;

import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;

/**
 * @author 北京-宏哥
 *
 *《手把手教你》系列技巧篇(四十一)-java+ selenium自動化測試 - 處理iframe-下篇(詳解教程)
 *
 * 2021年11月9日
 */
public class TestQQMail {
    
    public static void main(String[] args) throws InterruptedException {
        
        System.setProperty("webdriver.gecko.driver", ".\\Tools\\chromedriver.exe");
            
        WebDriver driver = new ChromeDriver();  
         
        driver.manage().window().maximize();  
              
        driver.get("//mail.qq.com/");
        
        Thread.sleep(5000);
        
        //By id 定位
        WebElement QQMailName = driver.findElement(By.id( "u" ));
        QQMailName.sendKeys("[email protected]");
        
    }

}

5.但是運行代碼 後報錯,如下圖所示:

Exception in thread “main” org.openqa.selenium.NoSuchElementException: no such element: Unable to locate element: {“method”:”id”,”selector”:”u”}

6.此時小夥伴或者童鞋們是不是比較鬱悶?這個輸入框明顯是有id屬性的啊,並且屬性值確實是u啊。。。那麼問題在哪呢?其實就是iframe的原因,我們再仔細分析下html代碼會發現沿着定位元素讓上找會找到罪魁禍首iframe。如下圖所示:

7.換句話說也就是我們要定位的元素時在這個 iframe中的,所以需要先切到iframe裡邊後才可操作。好了原因知道了,按照上一篇宏哥講解的知識點,很輕鬆就可以定位到解決問題。

4.2代碼設計

1.如果我們要切入的iframe有id或者name屬性的話,我們可以直接通過driver.switch_to.frame並且傳入要切換的iframe對應的id或者name對應屬性值就可以切換到iframe,切換完後便可對我們要操作的元素進行操作。

2.如果要定位的iframe沒有id或者那麼的話,此時可以通過xpath、css等其他方式定位到iframe然後再進行切入。

3.使用index來區分iframe,index從0開始的。宏哥一直以為只有一個iframe,因此開始代碼里寫的是0結果是死活定位不到元素,後來查了一遍HTML發現是兩個iframe,改成1後,立馬定位元素成功!

4.3參考代碼

1.傳id參數

package lessons;

import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;

/**
 * @author 北京-宏哥
 *
 *《手把手教你》系列技巧篇(四十一)-java+ selenium自動化測試 - 處理iframe-下篇(詳解教程)
 *
 * 2021年11月9日
 */
public class TestQQMail {
    
    public static void main(String[] args) throws InterruptedException {
        
        System.setProperty("webdriver.gecko.driver", ".\\Tools\\chromedriver.exe");
            
        WebDriver driver = new ChromeDriver();  
         
        driver.manage().window().maximize();  
              
        driver.get("//mail.qq.com/");
        
        Thread.sleep(2000);
        
        //WebElement frame = driver.findElement(By.tagName("iframe"));
        driver.switchTo().frame("login_frame");
        
        //By id 定位
        driver.findElement(By.id( "switcher_plogin" )).click();
        Thread.sleep(1000);
        WebElement QQMailName = driver.findElement(By.id( "u" ));
        QQMailName.sendKeys("[email protected]");
        System.out.println(" 嘿嘿!宏哥,你已經成功定位iframe內的元素啦!");
    }
}

2.傳selenium的WebElement對象

package lessons;

import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;

/**
 * @author 北京-宏哥
 *
 *《手把手教你》系列技巧篇(四十一)-java+ selenium自動化測試 - 處理iframe-下篇(詳解教程)
 *
 * 2021年11月9日
 */
public class TestQQMail {
    
    public static void main(String[] args) throws InterruptedException {
        
        System.setProperty("webdriver.gecko.driver", ".\\Tools\\chromedriver.exe");
            
        WebDriver driver = new ChromeDriver();  
         
        driver.manage().window().maximize();  
              
        driver.get("//mail.qq.com/");
        
        Thread.sleep(2000);
        
        WebElement frame = driver.findElement(By.cssSelector("#qqLoginCard>iframe"));
        driver.switchTo().frame(frame);
        
        //By id 定位
        driver.findElement(By.id( "switcher_plogin" )).click();
        Thread.sleep(1000);
        WebElement QQMailName = driver.findElement(By.id( "u" ));
        QQMailName.sendKeys("[email protected]");
        System.out.println(" 嘿嘿!宏哥,你已經成功定位iframe內的元素啦!");
    }
}

3.傳index參數

package lessons;

import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;

/**
 * @author 北京-宏哥
 *
 *《手把手教你》系列技巧篇(四十一)-java+ selenium自動化測試 - 處理iframe-下篇(詳解教程)
 *
 * 2021年11月9日
 */
public class TestQQMail {
    
    public static void main(String[] args) throws InterruptedException {
        
        System.setProperty("webdriver.gecko.driver", ".\\Tools\\chromedriver.exe");
            
        WebDriver driver = new ChromeDriver();  
         
        driver.manage().window().maximize();  
              
        driver.get("//mail.qq.com/");
        
        Thread.sleep(2000);
        
        //WebElement frame = driver.findElement(By.tagName("iframe"));
        driver.switchTo().frame(1);
        
        //By id 定位
        driver.findElement(By.id( "switcher_plogin" )).click();
        Thread.sleep(1000);
        WebElement QQMailName = driver.findElement(By.id( "u" ));
        QQMailName.sendKeys("[email protected]");
        System.out.println(" 嘿嘿!宏哥,你已經成功定位iframe內的元素啦!");
    }
}

4.4運行代碼

1.運行代碼,右鍵Run AS->Java Appliance,控制台輸出,如下圖所示:

2.運行代碼後電腦端的瀏覽器的動作,如下小視頻所示:

 

5.小結

1.在Web UI自動化的測試中,如果一個元素定位不到,那麼最大的可能定位的元素屬性是在 iframe 框架中,iframe 是 html 中的框架,在 html 中,所謂框架就是可以在同一個瀏覽器窗口中顯示不止一個頁面,對不同頁面進行嵌套。順着定位元素往上找,查看是否有<iframe>標籤,找到說明要定位此元素,需先切換到此表單,在定位元素。

2.frame標籤有frameset、frame、iframe三種,frameset跟其他普通標籤沒有區別,不會影響到正常的定位,而frame與iframe對selenium定位而言是一樣的,selenium有一組方法對frame進行操作。

3.通常採用id和name就能夠解決絕大多數問題。但有時候frame並無這兩項屬性,則可以用index和WebElement來定位:

  index從0開始,傳入整型參數即判定為用index定位,傳入str參數則判定為用id/name定位
  WebElement對象,即用find_element系列方法所取得的對象,我們可以用tag_name、xpath等來定位frame對象

4.如果你的電腦登錄QQ後,要注意將這一行代碼注釋去掉,如果沒有登錄QQ,需要將這一行代碼注釋掉。因為QQ已經登錄,然後登錄郵箱默認快捷登錄,就會看不到賬號密碼登錄的元素,出現找不到元素的報錯。

//driver.findElement(By.id( "switcher_plogin" )).click();//定位帳號密碼登錄並點擊