如何使用PhantomJS提交包含多个Web元素的登录表单?
我正尝试使用PhantomJS进行测试,现有一个登录页面,包含username和password两个必填参数。此前在Google页面测试时,仅需操作单个元素并调用element.submit()即可,但在该登录页中需要传递两个元素,该如何实现?
我的代码如下:
import java.io.File; import java.io.IOException; import org.apache.maven.shared.utils.io.FileUtils; import org.openqa.selenium.By; import org.openqa.selenium.OutputType; import org.openqa.selenium.TakesScreenshot; import org.openqa.selenium.WebDriver; import org.openqa.selenium.WebElement; import org.openqa.selenium.phantomjs.PhantomJSDriver; import org.openqa.selenium.remote.DesiredCapabilities; import org.testng.annotations.Test; public class PhantomExample { public PhantomExample() { System.out.println("this is constructor"); } @Test public void verify() { File src = new File("C:\\Users\\Admin\\Downloads\\Compressed\\phantomjs-2.1.1-windows\\bin\\phantomjs.exe"); DesiredCapabilities phantomjsCap = new DesiredCapabilities(); phantomjsCap.setJavascriptEnabled(true); phantomjsCap.setCapability("phantomjs.binary.path", src.getAbsolutePath()); System.out.println("inside the verify method"); System.setProperty("phantomjs.binary.path", src.getAbsolutePath()); WebDriver driver = new PhantomJSDriver(phantomjsCap); driver.get("http://localhost:8080/MyApp/Login"); System.out.println(driver.getPageSource()); WebElement el =driver.findElement(By.name("username")); WebElement elp =driver.findElement(By.name("password")); el.sendKeys("username"); elp.sendKeys("0"); el.submit(); elp.submit(); System.out.println(driver.getTitle()); System.out.println(driver.getCurrentUrl()); System.out.println(driver.getPageSource()); File Ss=((TakesScreenshot)driver).getScreenshotAs(OutputType.FILE); try { FileUtils.copyFile(Ss, new File("d:/sample.jpg")); } catch (IOException e) { System.out.println(e.getMessage()); } driver.quit(); } }
我创建了两个独立的元素并期望得到响应,但在调试模式下,执行完el.submit()后程序就不再继续执行。我确定当前做法有误,请问正确的实现方式是什么?同时如何获取登录后服务器返回的响应对象?
兄弟,你现在的问题核心是连续调用了两次submit()——当你调用el.submit()时,浏览器已经触发了整个表单的提交操作,页面会开始跳转或者刷新,后续的elp.submit()根本没机会执行,而且这种操作逻辑本身就不符合表单提交的规范。下面给你两种正确的实现方式,再聊聊如何获取响应相关信息:
一、正确提交双字段登录表单的两种方式
1. 定位整个登录表单,调用表单的submit()方法
不要单独调用输入框的submit,应该找到包含两个输入框的<form>元素,直接提交整个表单,这样就能同时带上username和password的参数:
// 在输入完账号密码后,找到username输入框所在的表单 WebElement loginForm = el.findElement(By.xpath("./ancestor::form")); loginForm.submit();
如果你的表单有明确的id、name或者class,也可以直接定位,比如driver.findElement(By.id("login-form")).submit();,这样更高效。
2. 模拟点击页面的登录按钮(更推荐)
如果登录页面有专门的提交按钮(比如<button type="submit">登录</button>或者<input type="submit" value="登录">),直接定位按钮并模拟点击,完全贴合真实用户的操作流程,稳定性更高:
// 替换成你页面中登录按钮的实际定位方式,比如按name、id、xpath等 WebElement loginBtn = driver.findElement(By.name("login-btn")); loginBtn.click();
二、关于获取服务器返回的响应对象
PhantomJS(以及整个Selenium WebDriver体系)的定位是模拟浏览器交互,它并不直接提供获取HTTP响应对象的API。不过你可以通过以下几种方式获取相关信息:
- 通过页面状态判断登录结果:登录成功后通常会跳转到指定页面(比如用户首页),你可以用
driver.getCurrentUrl()检查是否跳转到了预期地址,或者解析driver.getPageSource()查看是否有登录成功的标识(比如“欢迎回来”这类文本)。 - 捕获PhantomJS的网络日志:可以配置DesiredCapabilities开启网络日志,捕获请求和响应的详细信息,不过需要自己解析日志内容:
// 在初始化phantomjsCap的时候添加以下配置 phantomjsCap.setCapability("phantomjs.page.onResourceReceived", new PhantomJSDriver.LogEntriesListener() { @Override public void onLogEntry(org.openqa.selenium.logging.LogEntry entry) { // 打印响应日志,你可以在这里解析响应状态、响应体等内容 System.out.println("收到响应: " + entry.getMessage()); } }); - 配合API测试工具:如果需要直接获取HTTP响应的完整内容(比如响应头、响应体),建议用RestAssured这类专门的API测试工具单独发送登录请求,拿到响应对象后,再结合Selenium做页面交互测试,分工更清晰。
修正后的完整代码示例
import java.io.File; import java.io.IOException; import org.apache.maven.shared.utils.io.FileUtils; import org.openqa.selenium.By; import org.openqa.selenium.OutputType; import org.openqa.selenium.TakesScreenshot; import org.openqa.selenium.WebDriver; import org.openqa.selenium.WebElement; import org.openqa.selenium.phantomjs.PhantomJSDriver; import org.openqa.selenium.remote.DesiredCapabilities; import org.testng.annotations.Test; public class PhantomExample { public PhantomExample() { System.out.println("this is constructor"); } @Test public void verify() { File src = new File("C:\\Users\\Admin\\Downloads\\Compressed\\phantomjs-2.1.1-windows\\bin\\phantomjs.exe"); DesiredCapabilities phantomjsCap = new DesiredCapabilities(); phantomjsCap.setJavascriptEnabled(true); phantomjsCap.setCapability("phantomjs.binary.path", src.getAbsolutePath()); System.out.println("inside the verify method"); System.setProperty("phantomjs.binary.path", src.getAbsolutePath()); WebDriver driver = new PhantomJSDriver(phantomjsCap); driver.get("http://localhost:8080/MyApp/Login"); System.out.println(driver.getPageSource()); WebElement el = driver.findElement(By.name("username")); WebElement elp = driver.findElement(By.name("password")); el.sendKeys("username"); elp.sendKeys("0"); // 方式一:提交整个表单(推荐如果没有明显的登录按钮时使用) WebElement loginForm = el.findElement(By.xpath("./ancestor::form")); loginForm.submit(); // 方式二:点击登录按钮(如果页面有登录按钮,注释上面的代码,打开下面的代码) // WebElement loginBtn = driver.findElement(By.name("submit")); // 替换成实际按钮的定位器 // loginBtn.click(); System.out.println(driver.getTitle()); System.out.println(driver.getCurrentUrl()); System.out.println(driver.getPageSource()); File Ss = ((TakesScreenshot) driver).getScreenshotAs(OutputType.FILE); try { FileUtils.copyFile(Ss, new File("d:/sample.jpg")); } catch (IOException e) { System.out.println(e.getMessage()); } driver.quit(); } }
内容的提问来源于stack exchange,提问作者Pavan Divekar

