我是Selenium的新手。
要了解有关硒的更多信息,我开始自动化网站的飞行搜索流程" https://www.findmyfare.com/"在Java中使用Selenium Web驱动程序。
我能够执行搜索按钮点击。但它会指向错误页面,而不是为我的搜索条件生成结果。
当我手动执行搜索时,它工作正常。
有人可以帮我解决这个问题吗?
N.B。此搜索按钮不是"提交"的类型。所以,我使用了click()方法。 (我也尝试过submit(),也没有区别)。
以下是触发搜索的代码段。
import java.util.List;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.testng.annotations.Test;
public class FlightSearchWD
{
public WebDriver driver = null;
public String baseUrl;
@Test
public void testFlightSearchWD()
{
driver = new FirefoxDriver();
driver.get("https://www.findmyfare.com/");
driver.findElement(By.id("from_1")).click();
WebElement cleartext = driver.findElement(By.id("from_1"));
cleartext.clear();
WebElement FromCity = driver.findElement(By.id("from_1"));
FromCity.sendKeys("Auckland, New Zealand (AKL)");
driver.findElement(By.id("to_1")).click();
WebElement cleartext1 = driver.findElement(By.id("to_1"));
cleartext1.clear();
WebElement ToCity = driver.findElement(By.id("to_1"));
ToCity.sendKeys("Colombo, Sri Lanka (CMB)");
WebElement FromDate = driver.findElement(By.id("date_1"));
FromDate.click();
WebElement datepicker = driver.findElement(By.id("ui-datepicker-div"));
List<WebElement> rows = datepicker.findElements(By.tagName("tr"));
List<WebElement> columns = datepicker.findElements(By.tagName("td"));
for (WebElement cell : columns)
{
// Select 20th Date
if (cell.getText().equals("20"))
{
cell.findElement(By.linkText("20")).click();
break;
}
}
// select to date
WebElement ToDate = driver.findElement(By.id("date_2"));
ToDate.click();
WebElement datepicker2 = driver.findElement(By.id("ui-datepicker-div"));
List<WebElement> rows1 = datepicker2.findElements(By.tagName("tr"));
List<WebElement> columns1 = datepicker2.findElements(By.tagName("td"));
for (WebElement cell1 : columns1)
{
// Select 20th Date
if (cell1.getText().equals("25"))
{
cell1.findElement(By.linkText("25")).click();
break;
}
}
WebElement ClickTravellers = driver.findElement(By.id("PopS"));
ClickTravellers.click();
addAdults();
addChildren();
addInfant();
WebElement clickSearch = driver.findElement(By.id("search_flight_submit"));
clickSearch.click();
}
private void addAdults()
{
while (true)
{
WebElement popOverBtnGrp = driver
.findElement(By.xpath("//div[@class='btn-group col-xs-12 col-md-12 col-sm-12']"));
if (popOverBtnGrp.isDisplayed())
{
try
{
WebElement NoOfTravellers = driver.findElement(By.xpath(
"//button[@class='btn add_people ripple-effect btn-default btn-sm col-xs-2 col-md-4 col-sm-4']"));
for (int i = 0; i < 1; i++)
{
NoOfTravellers.click();
}
break;
} catch (Exception e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
private void addChildren()
{
while (true)
{
WebElement popOverBtnGrp = driver
.findElement(By.xpath("//div[@class='btn-group col-xs-12 col-md-12 col-sm-12']"));
if (popOverBtnGrp.isDisplayed())
{
try
{
WebElement NoOfTravellers = driver.findElement(By.xpath("//button[@class=' add_people btn btn-default btn-sm ripple-effect col-xs-2 col-md-4 col-sm-4' and @data-id='childrens']"));
for (int i = 0; i < 1; i++)
{
NoOfTravellers.click();
}
break;
} catch (Exception e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
private void addInfant()
{
while (true)
{
WebElement popOverBtnGrp = driver
.findElement(By.xpath("//div[@class='btn-group col-xs-12 col-md-12 col-sm-12']"));
if (popOverBtnGrp.isDisplayed())
{
try
{
WebElement NoOfTravellers = driver.findElement(By.xpath("//button[@class='add_people btn btn-default btn-sm ripple-effect col-xs-2 col-md-4 col-sm-4' and @data-id='infants']"));
for (int i = 0; i < 1; i++)
{
NoOfTravellers.click();
}
break;
} catch (Exception e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
}
答案 0 :(得分:0)
Selenium非常适合在浏览器中模拟用户交互。但是,默认情况下,命令遵循简单的顺序。您在驱动程序中加载页面。一旦页面“完成”加载,它将立即执行您告诉它的操作。如果你说找到一个元素,它会通过DOM尝试找到By定位器的匹配元素。如果它找到一个它返回它。如果找不到,则抛出异常。虽然这对于selenium项目或非常静态的网站来说是很好的,但现在更常见的是网站是动态的。该页面将被视为“已加载”,但大多数内容都是通过异步调用获取的。这是因为它通过允许与“首屏”部分或关键内容进行交互而不让他们等待他们可能不关心的部分,从而让用户感觉页面是“活泼的”。不幸的是,这使得现代网站的自动化更加困难。通常,最好在非静态Web站点上使用Selenium来包装与WebDriverWait的所有交互,以确保元素在尝试单击之前处于您期望的状态。等待以下条件的简单例子。
import org.junit.jupiter.api.Test;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;
public class FooTest {
@Test
public void foo() {
WebDriver driver = new FirefoxDriver();
driver.get("https://www.findmyfare.com/");
new WebDriverWait(driver, 10).until(ExpectedConditions.elementToBeClickable(By.id("from_1")))
.click();
// ... etc
driver.quit();
}
}
请注意,上面等待Web驱动程序的构造函数中的数字“10”是以秒为单位的超时。如果在10秒内没有找到具有匹配id的元素,则会抛出异常。
答案 1 :(得分:0)
其他人说你的元素调用应该有等待是正确的。你已经设法以某种方式通过执行while循环来解决它,但等待几乎总是更好。我下载了你的代码并运行它,你遇到的问题实际上并不是与selenium直接相关的问题。
所以,你提到它不会进入结果页面,而是转到错误页面,我认为这是从网站的角度来看的预期行为。我最好的猜测是,他们检测到导航他们网站的'用户'是否是'僵尸',如果是'僵尸',则转到不同的页面而不是常规搜索结果页面。尝试使用其他网站来测试你的selenium脚本,我很确定它是有效的。
无论如何,我已经为初学者创建了一个硒框架,可以帮助您避免这里提到的问题。一旦测试完成,它甚至会为您自动关闭浏览器。以下是使用easytest框架对上面代码的翻译。
@Test
public void testFindMyFare() throws Exception {
try(EasyTest easy = new EasyTest(DriverType.CHROME)) {
// start
easy.start("https://www.findmyfare.com/");
// homepage
easy.newPage(page -> {
page.typeText("#from_1", "Auckland, New Zealand (AKL)");
page.typeText("#to_1", "Colombo, Sri Lanka (CMB)");
// click from date slector and select 20th
page.click("#date_1");
page.executeIn("#ui-datepicker-div", container -> {
container.click(":20");
});
// click to date slector and select 25th
page.click("#date_2");
page.executeIn("#ui-datepicker-div", container -> {
container.click(":25");
});
// click travellers
page.click("#PopS");
// add people
page.executeIn(".popover", container -> {
container.click("button[data-id='adults'].add_people");
container.click("button[data-id='childrens'].add_people");
container.click("button[data-id='infants'].add_people");
});
// click find flight button
page.clickButton("#search_flight_submit");
});
}
}
如果您发现上面的测试更容易阅读和遵循,您可以在https://github.com/codezombies/easytest下载easytest框架。如果我能帮助你学习硒,请告诉我。
答案 2 :(得分:0)
谢谢@Asha,我也是selenium webdriver的新手,从这个查询中学到了很多东西,最后找到了解决方案。
import java.util.List;
import org.testng.annotations.Test;
import org.openqa.selenium.By;
import org.openqa.selenium.Keys;
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;
public class FlightSearchWD {
public WebDriver driver = null;
public String baseUrl;
@Test
public void testFlightSearchWD() throws InterruptedException {
driver = new FirefoxDriver();
driver.get("https://www.findmyfare.com/");
WebDriverWait wait = new WebDriverWait(driver, 10);
WebElement from1 = wait.until(ExpectedConditions
.presenceOfElementLocated(By.id("from_1")));
from1.click();
from1.clear();
from1.sendKeys("AKL");
from1.sendKeys(Keys.ENTER);
driver.findElement(By.id("to_1")).click();
WebElement cleartext1 = driver.findElement(By.id("to_1"));
cleartext1.clear();
WebElement ToCity = driver.findElement(By.id("to_1"));
ToCity.sendKeys("CMB");
ToCity.sendKeys(Keys.ENTER);
Thread.sleep(3000);
driver.findElement(By.xpath(".//*[@id='trip_types']")).click();
driver.findElement(By.id("date_1")).click();
List<WebElement> total_date = driver
.findElements(By
.xpath("//div[@class='panel-body']/div[@class='pull-left col-md-6 pull-left-first']/table[1]//td"));
int total_date_size = total_date.size();
for (int i = 0; i < total_date_size; i++) {
String date = total_date.get(i).getText();
if (date.equalsIgnoreCase("20")) {
total_date.get(i).click();
break;
}
}
driver.findElement(By.id("date_2")).click();
List<WebElement> total_date1 = driver
.findElements(By
.xpath("//div[@class='panel-body']/div[@class='pull-left col-md-6 pull-left-first']/table[1]//td"));
int total_date_size1 = total_date1.size();
for (int i = 0; i < total_date_size1; i++) {
String date1 = total_date1.get(i).getText();
if (date1.equalsIgnoreCase("25")) {
total_date1.get(i).click();
break;
}
}
WebElement ClickTravellers = driver.findElement(By.id("PopS"));
ClickTravellers.click();
addAdults();
addChildren();
addInfant();
WebElement clickSearch = driver.findElement(By
.id("search_flight_submit"));
clickSearch.click();
}
private void addAdults() {
while (true) {
WebElement popOverBtnGrp = driver
.findElement(By
.xpath("//div[@class='btn-group col-xs-12 col-md-12 col-sm-12']"));
if (popOverBtnGrp.isDisplayed()) {
try {
WebElement NoOfTravellers = driver
.findElement(By
.xpath("//button[@class='btn add_people ripple-effect btn-default btn-sm col-xs-2 col-md-4 col-sm-4']"));
for (int i = 0; i < 1; i++) {
NoOfTravellers.click();
}
break;
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
private void addChildren() {
while (true) {
WebElement popOverBtnGrp = driver
.findElement(By
.xpath("//div[@class='btn-group col-xs-12 col-md-12 col-sm-12']"));
if (popOverBtnGrp.isDisplayed()) {
try {
WebElement NoOfTravellers = driver
.findElement(By
.xpath("//button[@class=' add_people btn btn-default btn-sm ripple-effect col-xs-2 col-md-4 col-sm-4' and @data-id='childrens']"));
for (int i = 0; i < 1; i++) {
NoOfTravellers.click();
}
break;
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
private void addInfant() {
while (true) {
WebElement popOverBtnGrp = driver
.findElement(By
.xpath("//div[@class='btn-group col-xs-12 col-md-12 col-sm-12']"));
if (popOverBtnGrp.isDisplayed()) {
try {
WebElement NoOfTravellers = driver
.findElement(By
.xpath("//button[@class='add_people btn btn-default btn-sm ripple-effect col-xs-2 col-md-4 col-sm-4' and @data-id='infants']"));
for (int i = 0; i < 1; i++) {
NoOfTravellers.click();
}
break;
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
}
如果您对此有任何疑问,请与我们联系。