富文本框和普通的文本框定位有较大的区别,富文本框常见的实现用到Frame标签,并且Frame里面实现了一个完整的HTML网页结构,所以使用普通的定位模式无法直接定位到富文本框对象。
以http://mail.sohu.com为例,介绍两种方法读取富文本框。
方法一:
package cn.om.webdriverapi; import org.testng.annotations.Test; import org.testng.annotations.BeforeMethod; import java.awt.AWTException; import java.awt.Robot; import java.awt.event.KeyEvent; import java.util.concurrent.TimeUnit; import org.openqa.selenium.By; import org.openqa.selenium.JavascriptExecutor; import org.openqa.selenium.WebDriver; import org.openqa.selenium.WebElement; import org.openqa.selenium.firefox.FirefoxDriver; import org.openqa.selenium.support.ui.ExpectedConditions; import org.openqa.selenium.support.ui.WebDriverWait; import org.testng.annotations.AfterMethod; public class TestRichTextBox1 { WebDriver driver; String url; @Test public void testSohuMailWriteEMail() { driver.get(url); //设置获取元素的超时时间为5秒 driver.manage().timeouts().implicitlyWait(5, TimeUnit.SECONDS); WebElement username = driver.findElement(By.xpath(".//*[@id='theme']/form/div[1]/div[1]/input")); WebElement password = driver.findElement(By.xpath(".//*[@id='theme']/form/div[2]/div[1]/input")); WebElement sub = driver.findElement(By.xpath(".//*[@id='theme']/form/div[5]/input")); //输入账号,密码,点击登录。由于有验证码,会跳转到输入验证码的页面 username.sendKeys("fosterwu"); password.sendKeys("1111"); sub.click(); //等待10秒,手工输入验证码 try { Thread.sleep(10000); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } //输入验证码后,再次点击登录。 sub.click(); //手机安全认证,点击【下次再说】按钮 WebElement notdo=driver.findElement(By.xpath(".//*[@id='theme']/div[1]/div[1]/div[4]/span[2]")); notdo.click(); WebDriverWait wait=new WebDriverWait(driver, 15); //显示等待15秒,通过查找【写邮件】按钮,判断是否已经成登录到邮箱中 wait.until(ExpectedConditions.presenceOfElementLocated(By.xpath(".//*[@id='addSkinClass']/div[4]/div/ul/li[1]"))); //定位【写邮件】的按钮,点击后进入写信页面 WebElement writeMailButton=driver.findElement(By.xpath(".//*[@id='addSkinClass']/div[4]/div/ul/li[1]")); writeMailButton.click(); //定位发件人输入框,输入要测试的数据 WebElement recipients=driver.findElement(By.xpath(".//*[@id='mailContent']/div/div[1]/div[1]/div[1]/div[1]/div/span/input")); recipients.sendKeys("[email protected]"); //由于发件人输入进去后,要回车或者点击下才能编辑下一个。因此加上点击回车的操作 Robot robot=null; try { robot=new Robot(); } catch (AWTException e) { // TODO Auto-generated catch block e.printStackTrace(); } robot.keyPress(KeyEvent.VK_ENTER); robot.keyRelease(KeyEvent.VK_ENTER); //定位主题输入框,输入要测试的数据 WebElement topic=driver.findElement(By.xpath(".//*[@id='mailContent']/div/div[1]/div[1]/div[4]/input")); topic.sendKeys("给自己的信"); //通过tabname找到iframe元素,切换到iframe中 WebElement iframe=driver.findElement(By.tagName("iframe")); driver.switchTo().frame(iframe); //声明JavaScriptExecutor对象来执行JavaScript脚本 JavascriptExecutor js=(JavascriptExecutor)driver; //在iframe中,查找到编辑区域对象p,设定html格式的文字内容,即正文内容 js.executeScript("document.getElementsByTagName('p')[0].innerHTML='<b>邮件要发送的内容<b>'"); //切换到默认页面。(主页面) driver.switchTo().defaultContent(); //点击发送 WebElement send=driver.findElement(By.xpath(".//*[@id='mailContent']/div/div[2]/span[1]")); send.click(); } @BeforeMethod public void beforeMethod() { url = "http://mail.sohu.com"; System.setProperty("webdriver.firefox.bin", "D:/Mozilla Firefox/firefox.exe"); driver = new FirefoxDriver(); } @AfterMethod public void afterMethod() { driver.quit(); } }
这种方法的优点是,可以支持HTML格式的文字作为富文本框的文字输入内容。
缺点是,因为不同网页的富文本框的实现机制都不同,定位到富文本框的文本编辑区域对象比较难,需要熟练了解HTML代码含义和frame的进出方法,对于脚本定位实现的能力要求较高。
方法二:
package cn.om.webdriverapi; import org.testng.annotations.Test; import org.testng.annotations.BeforeMethod; import java.awt.AWTException; import java.awt.Robot; import java.awt.Toolkit; import java.awt.datatransfer.StringSelection; import java.awt.event.KeyEvent; import java.util.concurrent.TimeUnit; import org.openqa.selenium.By; import org.openqa.selenium.WebDriver; import org.openqa.selenium.WebElement; import org.openqa.selenium.firefox.FirefoxDriver; import org.openqa.selenium.support.ui.ExpectedConditions; import org.openqa.selenium.support.ui.WebDriverWait; import org.testng.annotations.AfterMethod; public class TestRichTextBox2 { WebDriver driver; String url; @Test public void testRichTextBox2() { driver.get(url); // 设置获取元素的超时时间为5秒 driver.manage().timeouts().implicitlyWait(5, TimeUnit.SECONDS); WebElement username = driver.findElement(By.xpath(".//*[@id='theme']/form/div[1]/div[1]/input")); WebElement password = driver.findElement(By.xpath(".//*[@id='theme']/form/div[2]/div[1]/input")); WebElement sub = driver.findElement(By.xpath(".//*[@id='theme']/form/div[5]/input")); // 输入账号,密码,点击登录。由于有验证码,会跳转到输入验证码的页面 username.sendKeys("fosterwu"); password.sendKeys("1111"); sub.click(); // 等待10秒,手工输入验证码 try { Thread.sleep(10000); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } // 输入验证码后,再次点击登录。 sub.click(); // 手机安全认证,点击【下次再说】按钮 WebElement notdo = driver.findElement(By.xpath(".//*[@id='theme']/div[1]/div[1]/div[4]/span[2]")); notdo.click(); WebDriverWait wait = new WebDriverWait(driver, 15); // 显示等待15秒,通过查找【写邮件】按钮,判断是否已经成登录到邮箱中 wait.until( ExpectedConditions.presenceOfElementLocated(By.xpath(".//*[@id='addSkinClass']/div[4]/div/ul/li[1]"))); // 定位【写邮件】的按钮,点击后进入写信页面 WebElement writeMailButton = driver.findElement(By.xpath(".//*[@id='addSkinClass']/div[4]/div/ul/li[1]")); writeMailButton.click(); // 定位发件人输入框,输入要测试的数据 WebElement recipients = driver .findElement(By.xpath(".//*[@id='mailContent']/div/div[1]/div[1]/div[1]/div[1]/div/span/input")); recipients.sendKeys("[email protected]"); // 由于发件人输入进去后,要回车或者点击下才能编辑下一个。因此加上点击回车的操作 pressEnterKey(); // 定位主题输入框,输入要测试的数据 WebElement topic = driver.findElement(By.xpath(".//*[@id='mailContent']/div/div[1]/div[1]/div[4]/input")); topic.sendKeys("给自己的信"); // 通过tab键切换到富文本框 pressTabKey(); setAndctrlVClipboardData("邮件发送的正文内容"); //点击发送 WebElement send=driver.findElement(By.xpath(".//*[@id='mailContent']/div/div[2]/span[1]")); send.click(); } @BeforeMethod public void beforeMethod() { url = "http://mail.sohu.com"; System.setProperty("webdriver.firefox.bin", "D:/Mozilla Firefox/firefox.exe"); driver = new FirefoxDriver(); } @AfterMethod public void afterMethod() { driver.quit(); } public void pressTabKey() { Robot robot = null; try { robot = new Robot(); } catch (AWTException e) { // TODO Auto-generated catch block e.printStackTrace(); } robot.keyPress(KeyEvent.VK_TAB); robot.keyRelease(KeyEvent.VK_TAB); } public void pressEnterKey() { Robot robot = null; try { robot = new Robot(); } catch (AWTException e) { // TODO Auto-generated catch block e.printStackTrace(); } robot.keyPress(KeyEvent.VK_ENTER); robot.keyRelease(KeyEvent.VK_ENTER); } public void setAndctrlVClipboardData(String s) { // 声明StringSelection对象,并使用函数的string参数来完成实例化 StringSelection stringSelection = new StringSelection(s); // 使用Toolkit对象的setContents方法将字符串放到剪切板上 Toolkit.getDefaultToolkit().getSystemClipboard().setContents(stringSelection, null); // 声明Robot对象 Robot robot = null; try { robot = new Robot(); } catch (AWTException e) { // TODO Auto-generated catch block e.printStackTrace(); } // 调用KeyPress来实现按下Crtl键 robot.keyPress(KeyEvent.VK_CONTROL); // 调用KeyPress来实现按下V键 robot.keyPress(KeyEvent.VK_V); // 调用KeyPress来释放V键 robot.keyRelease(KeyEvent.VK_V); // 调用KeyPress来释放crtl键 robot.keyRelease(KeyEvent.VK_CONTROL); } }
这个方法的优点是,无论什么种类的富文本框,只要找到它的上面紧邻的元素,通过按tab键的方式均可以进入到富文本框的文本编辑区域,可以使用一种方法解决所有类型的富文本框编辑区域的定位问题。
缺点是,不能在富文本框编辑区域中进行HTML格式的文本输入。
两种方法各有各的好处,在实际使用的时候,根据实际情况来进行选择。