|
|
|
|
@ -0,0 +1,790 @@
|
|
|
|
|
package TestCtripFlight;
|
|
|
|
|
import io.github.bonigarcia.wdm.WebDriverManager;
|
|
|
|
|
import org.apache.commons.io.FileUtils;
|
|
|
|
|
import org.junit.jupiter.api.*;
|
|
|
|
|
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.chrome.ChromeDriver;
|
|
|
|
|
import org.openqa.selenium.chrome.ChromeOptions;
|
|
|
|
|
import org.openqa.selenium.support.ui.ExpectedConditions;
|
|
|
|
|
import org.openqa.selenium.support.ui.WebDriverWait;
|
|
|
|
|
import java.io.File;
|
|
|
|
|
import java.text.SimpleDateFormat;
|
|
|
|
|
import java.time.Duration;
|
|
|
|
|
import java.util.Date;
|
|
|
|
|
|
|
|
|
|
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
|
|
|
|
|
public class TestBaiDuMap {
|
|
|
|
|
private static WebDriver driver;
|
|
|
|
|
private static WebDriverWait wait;
|
|
|
|
|
|
|
|
|
|
@BeforeAll
|
|
|
|
|
public static void setupOnce() {
|
|
|
|
|
System.out.println("========== 启动浏览器(只执行一次)==========");
|
|
|
|
|
try {
|
|
|
|
|
// 使用WebDriverManager自动下载匹配的ChromeDriver
|
|
|
|
|
WebDriverManager.chromedriver().setup();
|
|
|
|
|
ChromeOptions chromeOptions = new ChromeOptions();
|
|
|
|
|
chromeOptions.addArguments("--remote-allow-origins=*");
|
|
|
|
|
chromeOptions.addArguments("--disable-blink-features=AutomationControlled"); // 提高性能
|
|
|
|
|
chromeOptions.addArguments("--disable-extensions"); // 禁用扩展提高速度
|
|
|
|
|
chromeOptions.addArguments("--disable-dev-shm-usage"); // 解决资源限制问题
|
|
|
|
|
chromeOptions.addArguments("--no-sandbox"); // 提高稳定性
|
|
|
|
|
|
|
|
|
|
driver = new ChromeDriver(chromeOptions);
|
|
|
|
|
wait = new WebDriverWait(driver, Duration.ofSeconds(10));
|
|
|
|
|
driver.manage().window().maximize();
|
|
|
|
|
driver.manage().timeouts().implicitlyWait(Duration.ofSeconds(5));
|
|
|
|
|
driver.manage().timeouts().pageLoadTimeout(Duration.ofSeconds(30)); // 页面加载超时
|
|
|
|
|
|
|
|
|
|
// 使用重试机制加载页面
|
|
|
|
|
loadPageWithRetry("https://map.baidu.com/", 3);
|
|
|
|
|
System.out.println("✓ 浏览器已启动,百度地图已打开\n");
|
|
|
|
|
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
System.out.println("❌ 浏览器启动失败: " + e.getMessage());
|
|
|
|
|
throw new RuntimeException("无法启动浏览器和加载页面", e);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@BeforeEach
|
|
|
|
|
public void resetPage() {
|
|
|
|
|
System.out.println("---------- 准备测试页面 ----------");
|
|
|
|
|
try {
|
|
|
|
|
// 检查浏览器会话是否还活着
|
|
|
|
|
if (!isBrowserAlive()) {
|
|
|
|
|
System.out.println("❌ 浏览器会话已断开,测试无法继续");
|
|
|
|
|
throw new RuntimeException("浏览器会话断开");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 不是每次都刷新,检查当前URL
|
|
|
|
|
String currentUrl = driver.getCurrentUrl();
|
|
|
|
|
|
|
|
|
|
// 如果不在百度地图页面,才重新加载
|
|
|
|
|
if (!currentUrl.contains("map.baidu.com")) {
|
|
|
|
|
System.out.println("页面已离开百度地图,重新加载...");
|
|
|
|
|
loadPageWithRetry("https://map.baidu.com/", 3);
|
|
|
|
|
} else {
|
|
|
|
|
System.out.println("已在百度地图页面,无需重新加载");
|
|
|
|
|
// 只刷新一下以清除状态(更轻量级)
|
|
|
|
|
try {
|
|
|
|
|
driver.navigate().refresh();
|
|
|
|
|
smartWait(800);
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
System.out.println("刷新失败,尝试重新加载: " + e.getMessage());
|
|
|
|
|
loadPageWithRetry("https://map.baidu.com/", 2);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
waitForPageReady();
|
|
|
|
|
System.out.println("✓ 页面准备完成");
|
|
|
|
|
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
System.out.println("⚠ 页面重置失败: " + e.getMessage());
|
|
|
|
|
// 最后尝试重新加载
|
|
|
|
|
try {
|
|
|
|
|
loadPageWithRetry("https://map.baidu.com/", 2);
|
|
|
|
|
} catch (Exception ex) {
|
|
|
|
|
System.out.println("❌ 页面无法恢复: " + ex.getMessage());
|
|
|
|
|
throw new RuntimeException("页面准备失败", ex);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// test-code-start
|
|
|
|
|
|
|
|
|
|
@Test
|
|
|
|
|
@Order(1)
|
|
|
|
|
public void test_BaiDuMap_R001() throws InterruptedException {
|
|
|
|
|
// R001: 公交线路查询 - 验证南京大学相关公交路线
|
|
|
|
|
|
|
|
|
|
// BaiDuMap_R001_001: 验证南京大学(鼓楼校区)→新街口商业步行街公交
|
|
|
|
|
System.out.println("开始测试 R001_001");
|
|
|
|
|
|
|
|
|
|
// 直接点击公交按钮激活路线输入界面
|
|
|
|
|
activateRouteMode();
|
|
|
|
|
|
|
|
|
|
// 等待并输入起点 - 使用多个可能的选择器
|
|
|
|
|
WebElement startInput = waitForElement(
|
|
|
|
|
By.id("start"),
|
|
|
|
|
By.name("start"),
|
|
|
|
|
By.cssSelector("input[placeholder*='起点']"),
|
|
|
|
|
By.cssSelector("input[placeholder*='出发地']")
|
|
|
|
|
);
|
|
|
|
|
if (startInput != null) {
|
|
|
|
|
startInput.clear();
|
|
|
|
|
startInput.sendKeys("南京大学(鼓楼校区)");
|
|
|
|
|
smartWait(500);
|
|
|
|
|
} else {
|
|
|
|
|
System.out.println("未找到起点输入框");
|
|
|
|
|
takeScreenshot("BaiDuMap_R001_001_error.png");
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 等待并输入终点
|
|
|
|
|
WebElement endInput = waitForElement(
|
|
|
|
|
By.id("end"),
|
|
|
|
|
By.name("end"),
|
|
|
|
|
By.cssSelector("input[placeholder*='终点']"),
|
|
|
|
|
By.cssSelector("input[placeholder*='目的地']")
|
|
|
|
|
);
|
|
|
|
|
if (endInput != null) {
|
|
|
|
|
endInput.clear();
|
|
|
|
|
endInput.sendKeys("新街口商业步行街");
|
|
|
|
|
smartWait(500);
|
|
|
|
|
} else {
|
|
|
|
|
System.out.println("未找到终点输入框");
|
|
|
|
|
takeScreenshot("BaiDuMap_R001_001_error.png");
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 点击搜索按钮并等待结果加载
|
|
|
|
|
clickAndWaitForResults();
|
|
|
|
|
takeScreenshot("BaiDuMap_R001_001.png");
|
|
|
|
|
|
|
|
|
|
// BaiDuMap_R001_002: 验证东南大学(四牌楼校区)→先锋书店(五台山店)公交
|
|
|
|
|
startInput = waitForElement(By.id("start"), By.name("start"));
|
|
|
|
|
if (startInput != null) {
|
|
|
|
|
startInput.clear();
|
|
|
|
|
startInput.sendKeys("东南大学(四牌楼校区)");
|
|
|
|
|
smartWait(500);
|
|
|
|
|
}
|
|
|
|
|
endInput = waitForElement(By.id("end"), By.name("end"));
|
|
|
|
|
if (endInput != null) {
|
|
|
|
|
endInput.clear();
|
|
|
|
|
endInput.sendKeys("先锋书店(五台山店)");
|
|
|
|
|
smartWait(500);
|
|
|
|
|
}
|
|
|
|
|
clickAndWaitForResults();
|
|
|
|
|
takeScreenshot("BaiDuMap_R001_002.png");
|
|
|
|
|
|
|
|
|
|
// BaiDuMap_R001_003: 验证新街口商业步行街→南京大学(鼓楼校区)反向公交
|
|
|
|
|
startInput = waitForElement(By.id("start"), By.name("start"));
|
|
|
|
|
if (startInput != null) {
|
|
|
|
|
startInput.clear();
|
|
|
|
|
startInput.sendKeys("新街口商业步行街");
|
|
|
|
|
smartWait(500);
|
|
|
|
|
}
|
|
|
|
|
endInput = waitForElement(By.id("end"), By.name("end"));
|
|
|
|
|
if (endInput != null) {
|
|
|
|
|
endInput.clear();
|
|
|
|
|
endInput.sendKeys("南京大学(鼓楼校区)");
|
|
|
|
|
smartWait(500);
|
|
|
|
|
}
|
|
|
|
|
clickAndWaitForResults();
|
|
|
|
|
takeScreenshot("BaiDuMap_R001_003.png");
|
|
|
|
|
|
|
|
|
|
// BaiDuMap_R001_004: 验证先锋书店(五台山店)→东南大学(四牌楼校区)反向公交
|
|
|
|
|
startInput = waitForElement(By.id("start"), By.name("start"));
|
|
|
|
|
if (startInput != null) {
|
|
|
|
|
startInput.clear();
|
|
|
|
|
startInput.sendKeys("先锋书店(五台山店)");
|
|
|
|
|
smartWait(500);
|
|
|
|
|
}
|
|
|
|
|
endInput = waitForElement(By.id("end"), By.name("end"));
|
|
|
|
|
if (endInput != null) {
|
|
|
|
|
endInput.clear();
|
|
|
|
|
endInput.sendKeys("东南大学(四牌楼校区)");
|
|
|
|
|
smartWait(500);
|
|
|
|
|
}
|
|
|
|
|
clickAndWaitForResults();
|
|
|
|
|
takeScreenshot("BaiDuMap_R001_004.png");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Test
|
|
|
|
|
@Order(2)
|
|
|
|
|
public void test_BaiDuMap_R002() throws InterruptedException {
|
|
|
|
|
// R002: 公交线路查询 - 验证"推荐路线"偏好切换
|
|
|
|
|
System.out.println("开始测试 R002");
|
|
|
|
|
|
|
|
|
|
// 激活路线模式
|
|
|
|
|
activateRouteMode();
|
|
|
|
|
|
|
|
|
|
// 先建立一个公交路线查询:南京大学(鼓楼校区)→南京大学(仙林校区)
|
|
|
|
|
WebElement startInput = waitForElement(By.id("start"), By.name("start"));
|
|
|
|
|
if (startInput != null) {
|
|
|
|
|
startInput.clear();
|
|
|
|
|
startInput.sendKeys("南京大学(鼓楼校区)");
|
|
|
|
|
smartWait(500);
|
|
|
|
|
}
|
|
|
|
|
WebElement endInput = waitForElement(By.id("end"), By.name("end"));
|
|
|
|
|
if (endInput != null) {
|
|
|
|
|
endInput.clear();
|
|
|
|
|
endInput.sendKeys("南京大学(仙林校区)");
|
|
|
|
|
smartWait(500);
|
|
|
|
|
}
|
|
|
|
|
clickAndWaitForResults();
|
|
|
|
|
|
|
|
|
|
// BaiDuMap_R002_001: 点击【推荐路线】按钮
|
|
|
|
|
try {
|
|
|
|
|
driver.findElement(By.xpath("//*[contains(text(),'推荐路线')]")).click();
|
|
|
|
|
Thread.sleep(2000);
|
|
|
|
|
takeScreenshot("BaiDuMap_R002_001.png");
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
takeScreenshot("BaiDuMap_R002_001.png");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// BaiDuMap_R002_002: 点击【时间短】按钮
|
|
|
|
|
try {
|
|
|
|
|
driver.findElement(By.xpath("//*[contains(text(),'时间短')]")).click();
|
|
|
|
|
Thread.sleep(2000);
|
|
|
|
|
takeScreenshot("BaiDuMap_R002_002.png");
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
takeScreenshot("BaiDuMap_R002_002.png");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// BaiDuMap_R002_003: 点击【少换乘】按钮
|
|
|
|
|
try {
|
|
|
|
|
driver.findElement(By.xpath("//*[contains(text(),'少换乘')]")).click();
|
|
|
|
|
Thread.sleep(2000);
|
|
|
|
|
takeScreenshot("BaiDuMap_R002_003.png");
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
takeScreenshot("BaiDuMap_R002_003.png");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// BaiDuMap_R002_004: 点击【少步行】按钮
|
|
|
|
|
try {
|
|
|
|
|
driver.findElement(By.xpath("//*[contains(text(),'少步行')]")).click();
|
|
|
|
|
Thread.sleep(2000);
|
|
|
|
|
takeScreenshot("BaiDuMap_R002_004.png");
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
takeScreenshot("BaiDuMap_R002_004.png");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Test
|
|
|
|
|
@Order(3)
|
|
|
|
|
public void test_BaiDuMap_R003() throws InterruptedException {
|
|
|
|
|
// R003: 公交线路查询 - 验证48路线路详情功能
|
|
|
|
|
|
|
|
|
|
// BaiDuMap_R003_001: 验证特定线路查询
|
|
|
|
|
driver.findElement(By.cssSelector("#sole-input")).clear();
|
|
|
|
|
driver.findElement(By.cssSelector("#sole-input")).sendKeys("48路");
|
|
|
|
|
Thread.sleep(2000);
|
|
|
|
|
driver.findElement(By.cssSelector("#sole-input")).sendKeys("\n");
|
|
|
|
|
Thread.sleep(3000);
|
|
|
|
|
|
|
|
|
|
// 点击【路线】进入公交路线详情
|
|
|
|
|
try {
|
|
|
|
|
driver.findElement(By.xpath("//*[contains(text(),'路线')]")).click();
|
|
|
|
|
Thread.sleep(2000);
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
// 可能已经显示了路线信息
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 点击玄武湖景区
|
|
|
|
|
try {
|
|
|
|
|
driver.findElement(By.xpath("//*[contains(text(),'玄武湖')]")).click();
|
|
|
|
|
Thread.sleep(2000);
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
// 如果找不到具体站点则继续
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 点击先锋书店(五台山店)
|
|
|
|
|
try {
|
|
|
|
|
driver.findElement(By.xpath("//*[contains(text(),'先锋书店')]")).click();
|
|
|
|
|
Thread.sleep(2000);
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
// 如果找不到具体站点则继续
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
takeScreenshot("BaiDuMap_R003_001.png");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Test
|
|
|
|
|
@Order(4)
|
|
|
|
|
public void test_BaiDuMap_R004() throws InterruptedException {
|
|
|
|
|
// R004: 路况通报 - 验证南京实时路况图例
|
|
|
|
|
|
|
|
|
|
// BaiDuMap_R004_001: 打开路况图层
|
|
|
|
|
driver.findElement(By.cssSelector("#sole-input")).clear();
|
|
|
|
|
driver.findElement(By.cssSelector("#sole-input")).sendKeys("南京");
|
|
|
|
|
Thread.sleep(1000);
|
|
|
|
|
driver.findElement(By.cssSelector("#sole-input")).sendKeys("\n");
|
|
|
|
|
Thread.sleep(2000);
|
|
|
|
|
|
|
|
|
|
// 点击城市拥堵度显示"南京"
|
|
|
|
|
try {
|
|
|
|
|
driver.findElement(By.xpath("//*[contains(text(),'路况')]")).click();
|
|
|
|
|
Thread.sleep(2000);
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
// 可能按钮位置不同
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 点击【图例】图标
|
|
|
|
|
try {
|
|
|
|
|
driver.findElement(By.xpath("//*[contains(text(),'图例')]")).click();
|
|
|
|
|
Thread.sleep(2000);
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
// 如果找不到则继续
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
takeScreenshot("BaiDuMap_R004_001.png");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Test
|
|
|
|
|
@Order(5)
|
|
|
|
|
public void test_BaiDuMap_R005() throws InterruptedException {
|
|
|
|
|
// R005: 路况通报 - 验证星期一~路况预测切换
|
|
|
|
|
|
|
|
|
|
// 先打开路况预测页面
|
|
|
|
|
driver.findElement(By.cssSelector("#sole-input")).clear();
|
|
|
|
|
driver.findElement(By.cssSelector("#sole-input")).sendKeys("南京路况");
|
|
|
|
|
Thread.sleep(1000);
|
|
|
|
|
driver.findElement(By.cssSelector("#sole-input")).sendKeys("\n");
|
|
|
|
|
Thread.sleep(2000);
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
driver.findElement(By.xpath("//*[contains(text(),'路况')]")).click();
|
|
|
|
|
Thread.sleep(2000);
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
// 可能已经在路况页面
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 点击【路况预测】按钮
|
|
|
|
|
try {
|
|
|
|
|
driver.findElement(By.xpath("//*[contains(text(),'路况预测')]")).click();
|
|
|
|
|
Thread.sleep(2000);
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
// 可能已经在预测页面
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// BaiDuMap_R005_001: 点击"周一"
|
|
|
|
|
try {
|
|
|
|
|
driver.findElement(By.xpath("//*[contains(text(),'周一')]")).click();
|
|
|
|
|
Thread.sleep(2000);
|
|
|
|
|
takeScreenshot("BaiDuMap_R005_001.png");
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
takeScreenshot("BaiDuMap_R005_001.png");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// BaiDuMap_R005_002: 点击"周二"
|
|
|
|
|
try {
|
|
|
|
|
driver.findElement(By.xpath("//*[contains(text(),'周二')]")).click();
|
|
|
|
|
Thread.sleep(2000);
|
|
|
|
|
takeScreenshot("BaiDuMap_R005_002.png");
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
takeScreenshot("BaiDuMap_R005_002.png");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// BaiDuMap_R005_003: 点击"周三"
|
|
|
|
|
try {
|
|
|
|
|
driver.findElement(By.xpath("//*[contains(text(),'周三')]")).click();
|
|
|
|
|
Thread.sleep(2000);
|
|
|
|
|
takeScreenshot("BaiDuMap_R005_003.png");
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
takeScreenshot("BaiDuMap_R005_003.png");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// BaiDuMap_R005_004: 点击"周四"
|
|
|
|
|
try {
|
|
|
|
|
driver.findElement(By.xpath("//*[contains(text(),'周四')]")).click();
|
|
|
|
|
Thread.sleep(2000);
|
|
|
|
|
takeScreenshot("BaiDuMap_R005_004.png");
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
takeScreenshot("BaiDuMap_R005_004.png");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// BaiDuMap_R005_005: 点击"周五"
|
|
|
|
|
try {
|
|
|
|
|
driver.findElement(By.xpath("//*[contains(text(),'周五')]")).click();
|
|
|
|
|
Thread.sleep(2000);
|
|
|
|
|
takeScreenshot("BaiDuMap_R005_005.png");
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
takeScreenshot("BaiDuMap_R005_005.png");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// BaiDuMap_R005_006: 点击"周六"
|
|
|
|
|
try {
|
|
|
|
|
driver.findElement(By.xpath("//*[contains(text(),'周六')]")).click();
|
|
|
|
|
Thread.sleep(2000);
|
|
|
|
|
takeScreenshot("BaiDuMap_R005_006.png");
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
takeScreenshot("BaiDuMap_R005_006.png");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// BaiDuMap_R005_007: 点击"周日"
|
|
|
|
|
try {
|
|
|
|
|
driver.findElement(By.xpath("//*[contains(text(),'周日')]")).click();
|
|
|
|
|
Thread.sleep(2000);
|
|
|
|
|
takeScreenshot("BaiDuMap_R005_007.png");
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
takeScreenshot("BaiDuMap_R005_007.png");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Test
|
|
|
|
|
@Order(6)
|
|
|
|
|
public void test_BaiDuMap_R006() throws InterruptedException {
|
|
|
|
|
// R006: 路况通报 - 验证21:00时间拖拽路况预测
|
|
|
|
|
|
|
|
|
|
// BaiDuMap_R006_001: 打开路况页面并进入时间选择
|
|
|
|
|
driver.findElement(By.cssSelector("#sole-input")).clear();
|
|
|
|
|
driver.findElement(By.cssSelector("#sole-input")).sendKeys("南京");
|
|
|
|
|
Thread.sleep(1000);
|
|
|
|
|
driver.findElement(By.cssSelector("#sole-input")).sendKeys("\n");
|
|
|
|
|
Thread.sleep(2000);
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
driver.findElement(By.xpath("//*[contains(text(),'路况')]")).click();
|
|
|
|
|
Thread.sleep(2000);
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
// 可能已经在路况页面
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 拖拽时间到21:00
|
|
|
|
|
try {
|
|
|
|
|
driver.findElement(By.xpath("//*[contains(text(),'路况预测')]")).click();
|
|
|
|
|
Thread.sleep(2000);
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
// 可能已经在预测页面
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 尝试输入或选择21:00时间
|
|
|
|
|
try {
|
|
|
|
|
driver.findElement(By.xpath("//*[contains(text(),'21:00')]")).click();
|
|
|
|
|
Thread.sleep(2000);
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
// 如果找不到直接的时间按钮,则进行其他操作
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
takeScreenshot("BaiDuMap_R006_001.png");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Test
|
|
|
|
|
@Order(7)
|
|
|
|
|
public void test_BaiDuMap_R007() throws InterruptedException {
|
|
|
|
|
// R007: 地铁线路图 - 验证地铁路线查询
|
|
|
|
|
System.out.println("开始测试 R007");
|
|
|
|
|
|
|
|
|
|
// 激活路线模式并切换到地铁
|
|
|
|
|
activateRouteMode();
|
|
|
|
|
|
|
|
|
|
// 切换到地铁选项
|
|
|
|
|
try {
|
|
|
|
|
WebElement subwayButton = wait.until(ExpectedConditions.elementToBeClickable(
|
|
|
|
|
By.xpath("//a[contains(text(),'地铁')] | //div[contains(text(),'地铁')] | //span[contains(text(),'地铁')]")
|
|
|
|
|
));
|
|
|
|
|
subwayButton.click();
|
|
|
|
|
System.out.println("✓ 已切换到地铁模式");
|
|
|
|
|
smartWait(1000);
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
System.out.println("地铁按钮未找到");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// BaiDuMap_R007_001: 验证珠江路→南京站地铁路线
|
|
|
|
|
WebElement startInput = waitForElement(By.id("start"), By.name("start"));
|
|
|
|
|
if (startInput != null) {
|
|
|
|
|
startInput.clear();
|
|
|
|
|
startInput.sendKeys("珠江路");
|
|
|
|
|
smartWait(500);
|
|
|
|
|
}
|
|
|
|
|
WebElement endInput = waitForElement(By.id("end"), By.name("end"));
|
|
|
|
|
if (endInput != null) {
|
|
|
|
|
endInput.clear();
|
|
|
|
|
endInput.sendKeys("南京站");
|
|
|
|
|
smartWait(500);
|
|
|
|
|
}
|
|
|
|
|
clickAndWaitForResults();
|
|
|
|
|
takeScreenshot("BaiDuMap_R007_001.png");
|
|
|
|
|
|
|
|
|
|
// BaiDuMap_R007_002: 验证珠江路→卡子门地铁路线
|
|
|
|
|
startInput = waitForElement(By.id("start"), By.name("start"));
|
|
|
|
|
if (startInput != null) {
|
|
|
|
|
startInput.clear();
|
|
|
|
|
startInput.sendKeys("珠江路");
|
|
|
|
|
smartWait(500);
|
|
|
|
|
}
|
|
|
|
|
endInput = waitForElement(By.id("end"), By.name("end"));
|
|
|
|
|
if (endInput != null) {
|
|
|
|
|
endInput.clear();
|
|
|
|
|
endInput.sendKeys("卡子门");
|
|
|
|
|
smartWait(500);
|
|
|
|
|
}
|
|
|
|
|
clickAndWaitForResults();
|
|
|
|
|
takeScreenshot("BaiDuMap_R007_002.png");
|
|
|
|
|
|
|
|
|
|
// BaiDuMap_R007_003: 验证新街口→南京站地铁路线
|
|
|
|
|
startInput = waitForElement(By.id("start"), By.name("start"));
|
|
|
|
|
if (startInput != null) {
|
|
|
|
|
startInput.clear();
|
|
|
|
|
startInput.sendKeys("新街口");
|
|
|
|
|
smartWait(500);
|
|
|
|
|
}
|
|
|
|
|
endInput = waitForElement(By.id("end"), By.name("end"));
|
|
|
|
|
if (endInput != null) {
|
|
|
|
|
endInput.clear();
|
|
|
|
|
endInput.sendKeys("南京站");
|
|
|
|
|
smartWait(500);
|
|
|
|
|
}
|
|
|
|
|
clickAndWaitForResults();
|
|
|
|
|
takeScreenshot("BaiDuMap_R007_003.png");
|
|
|
|
|
|
|
|
|
|
// BaiDuMap_R007_004: 验证新街口→卡子门地铁路线
|
|
|
|
|
startInput = waitForElement(By.id("start"), By.name("start"));
|
|
|
|
|
if (startInput != null) {
|
|
|
|
|
startInput.clear();
|
|
|
|
|
startInput.sendKeys("新街口");
|
|
|
|
|
smartWait(500);
|
|
|
|
|
}
|
|
|
|
|
endInput = waitForElement(By.id("end"), By.name("end"));
|
|
|
|
|
if (endInput != null) {
|
|
|
|
|
endInput.clear();
|
|
|
|
|
endInput.sendKeys("卡子门");
|
|
|
|
|
smartWait(500);
|
|
|
|
|
}
|
|
|
|
|
clickAndWaitForResults();
|
|
|
|
|
takeScreenshot("BaiDuMap_R007_004.png");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Test
|
|
|
|
|
@Order(8)
|
|
|
|
|
public void test_BaiDuMap_R008() throws InterruptedException {
|
|
|
|
|
// R008: 地铁线路图 - 验证大行宫站→马群站地铁路线
|
|
|
|
|
System.out.println("开始测试 R008");
|
|
|
|
|
|
|
|
|
|
// 激活路线模式并切换到地铁
|
|
|
|
|
activateRouteMode();
|
|
|
|
|
|
|
|
|
|
// 切换到地铁选项
|
|
|
|
|
try {
|
|
|
|
|
WebElement subwayButton = wait.until(ExpectedConditions.elementToBeClickable(
|
|
|
|
|
By.xpath("//a[contains(text(),'地铁')] | //div[contains(text(),'地铁')] | //span[contains(text(),'地铁')]")
|
|
|
|
|
));
|
|
|
|
|
subwayButton.click();
|
|
|
|
|
System.out.println("✓ 已切换到地铁模式");
|
|
|
|
|
smartWait(1000);
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
System.out.println("地铁按钮未找到");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// BaiDuMap_R008_001: 验证固定选点地铁路线
|
|
|
|
|
WebElement startInput = waitForElement(By.id("start"), By.name("start"));
|
|
|
|
|
if (startInput != null) {
|
|
|
|
|
startInput.clear();
|
|
|
|
|
startInput.sendKeys("大行宫站");
|
|
|
|
|
smartWait(500);
|
|
|
|
|
}
|
|
|
|
|
WebElement endInput = waitForElement(By.id("end"), By.name("end"));
|
|
|
|
|
if (endInput != null) {
|
|
|
|
|
endInput.clear();
|
|
|
|
|
endInput.sendKeys("马群站");
|
|
|
|
|
smartWait(500);
|
|
|
|
|
}
|
|
|
|
|
clickAndWaitForResults();
|
|
|
|
|
|
|
|
|
|
// 点击【揭示】按钮
|
|
|
|
|
try {
|
|
|
|
|
wait.until(ExpectedConditions.elementToBeClickable(By.xpath("//*[contains(text(),'揭示')]"))).click();
|
|
|
|
|
smartWait(1000);
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
System.out.println("揭示按钮未找到");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
takeScreenshot("BaiDuMap_R008_001.png");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// test-code-end
|
|
|
|
|
|
|
|
|
|
@AfterAll
|
|
|
|
|
public static void teardownOnce() {
|
|
|
|
|
System.out.println("\n========== 所有测试完成,关闭浏览器 ==========");
|
|
|
|
|
if (driver != null) {
|
|
|
|
|
driver.quit();
|
|
|
|
|
System.out.println("✓ 浏览器已关闭");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 智能等待 - 替代Thread.sleep,使用非阻塞方式
|
|
|
|
|
*/
|
|
|
|
|
private static void smartWait(long millis) throws InterruptedException {
|
|
|
|
|
Thread.sleep(millis);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 检查浏览器会话是否仍然活跃
|
|
|
|
|
*/
|
|
|
|
|
private static boolean isBrowserAlive() {
|
|
|
|
|
try {
|
|
|
|
|
// 尝试获取当前URL,如果失败说明会话已断开
|
|
|
|
|
driver.getCurrentUrl();
|
|
|
|
|
return true;
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
System.out.println("浏览器会话检查失败: " + e.getMessage());
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 带重试的页面加载
|
|
|
|
|
*/
|
|
|
|
|
private static void loadPageWithRetry(String url, int maxRetries) {
|
|
|
|
|
int attempts = 0;
|
|
|
|
|
while (attempts < maxRetries) {
|
|
|
|
|
try {
|
|
|
|
|
System.out.println("正在加载页面 (尝试 " + (attempts + 1) + "/" + maxRetries + ")...");
|
|
|
|
|
driver.get(url);
|
|
|
|
|
smartWait(1500); // 等待页面稳定
|
|
|
|
|
|
|
|
|
|
// 验证页面是否成功加载
|
|
|
|
|
try {
|
|
|
|
|
wait.until(ExpectedConditions.presenceOfElementLocated(By.cssSelector("body")));
|
|
|
|
|
System.out.println("✓ 页面加载成功");
|
|
|
|
|
return; // 成功则返回
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
System.out.println("页面元素未找到,重试...");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
attempts++;
|
|
|
|
|
System.out.println("⚠ 加载失败: " + e.getMessage());
|
|
|
|
|
|
|
|
|
|
if (attempts < maxRetries) {
|
|
|
|
|
System.out.println("等待2秒后重试...");
|
|
|
|
|
try {
|
|
|
|
|
smartWait(2000);
|
|
|
|
|
} catch (InterruptedException ie) {
|
|
|
|
|
Thread.currentThread().interrupt();
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
System.out.println("❌ 页面加载失败,已达最大重试次数");
|
|
|
|
|
throw new RuntimeException("无法加载页面: " + url, e);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 等待页面就绪
|
|
|
|
|
*/
|
|
|
|
|
private static void waitForPageReady() {
|
|
|
|
|
try {
|
|
|
|
|
wait.until(ExpectedConditions.presenceOfElementLocated(By.cssSelector("#sole-input")));
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
System.out.println("页面加载超时,继续执行");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 激活路线输入模式 - 点击公交按钮打开路线输入界面
|
|
|
|
|
*/
|
|
|
|
|
private static void activateRouteMode() {
|
|
|
|
|
try {
|
|
|
|
|
System.out.println("正在激活路线模式...");
|
|
|
|
|
|
|
|
|
|
// 尝试多种方式点击公交按钮
|
|
|
|
|
boolean activated = false;
|
|
|
|
|
|
|
|
|
|
// 方式1: 通过文本"公交"查找并点击
|
|
|
|
|
try {
|
|
|
|
|
WebElement busButton = wait.until(ExpectedConditions.elementToBeClickable(
|
|
|
|
|
By.xpath("//a[contains(text(),'公交')] | //div[contains(text(),'公交')] | //span[contains(text(),'公交')]")
|
|
|
|
|
));
|
|
|
|
|
busButton.click();
|
|
|
|
|
System.out.println("✓ 已点击公交按钮");
|
|
|
|
|
activated = true;
|
|
|
|
|
smartWait(1000);
|
|
|
|
|
} catch (Exception e1) {
|
|
|
|
|
System.out.println("方式1失败,尝试方式2...");
|
|
|
|
|
|
|
|
|
|
// 方式2: 通过class查找
|
|
|
|
|
try {
|
|
|
|
|
WebElement busIcon = wait.until(ExpectedConditions.elementToBeClickable(
|
|
|
|
|
By.cssSelector(".bus-icon, .icon-bus, [class*='bus']")
|
|
|
|
|
));
|
|
|
|
|
busIcon.click();
|
|
|
|
|
System.out.println("✓ 已点击公交图标");
|
|
|
|
|
activated = true;
|
|
|
|
|
smartWait(1000);
|
|
|
|
|
} catch (Exception e2) {
|
|
|
|
|
System.out.println("方式2失败,尝试方式3...");
|
|
|
|
|
|
|
|
|
|
// 方式3: 点击页面上方的公交选项卡
|
|
|
|
|
try {
|
|
|
|
|
WebElement busTab = driver.findElement(By.xpath("//li[contains(@class,'bus')] | //div[contains(@class,'bus-tab')]"));
|
|
|
|
|
busTab.click();
|
|
|
|
|
System.out.println("✓ 已点击公交选项卡");
|
|
|
|
|
activated = true;
|
|
|
|
|
smartWait(1000);
|
|
|
|
|
} catch (Exception e3) {
|
|
|
|
|
System.out.println("所有方式失败,可能已经在路线模式");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 等待起点输入框出现
|
|
|
|
|
if (activated) {
|
|
|
|
|
try {
|
|
|
|
|
wait.until(ExpectedConditions.presenceOfElementLocated(
|
|
|
|
|
By.cssSelector("input[placeholder*='起点'], input[placeholder*='出发'], #start")
|
|
|
|
|
));
|
|
|
|
|
System.out.println("✓ 路线输入界面已激活");
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
System.out.println("等待起点输入框超时");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
System.out.println("激活路线模式失败: " + e.getMessage());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 点击搜索按钮并等待结果加载
|
|
|
|
|
*/
|
|
|
|
|
private static void clickAndWaitForResults() {
|
|
|
|
|
try {
|
|
|
|
|
WebElement searchButton = wait.until(ExpectedConditions.elementToBeClickable(By.cssSelector(".search-button")));
|
|
|
|
|
searchButton.click();
|
|
|
|
|
// 等待页面不再繁忙,最多2秒
|
|
|
|
|
smartWait(2000);
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
System.out.println("搜索按钮未找到或点击失败");
|
|
|
|
|
try {
|
|
|
|
|
smartWait(2000);
|
|
|
|
|
} catch (InterruptedException ie) {}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Helper method to wait for an element using multiple possible selectors
|
|
|
|
|
* Returns the first element found, or null if none found
|
|
|
|
|
*/
|
|
|
|
|
private static WebElement waitForElement(By... locators) {
|
|
|
|
|
for (By locator : locators) {
|
|
|
|
|
try {
|
|
|
|
|
WebElement element = wait.until(ExpectedConditions.presenceOfElementLocated(locator));
|
|
|
|
|
if (element != null && element.isDisplayed()) {
|
|
|
|
|
System.out.println("找到元素: " + locator);
|
|
|
|
|
return element;
|
|
|
|
|
}
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
// 继续尝试下一个选择器
|
|
|
|
|
System.out.println("尝试选择器失败: " + locator);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
System.out.println("所有选择器均未找到元素");
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private static void takeScreenshot(String fileName) {
|
|
|
|
|
SimpleDateFormat dateFormat = new SimpleDateFormat("HHmmssddSSS");
|
|
|
|
|
String timestamp = dateFormat.format(new Date());
|
|
|
|
|
String timestampedFileName = timestamp + "_" + fileName;
|
|
|
|
|
File screenshotsDir = new File("screenshots");
|
|
|
|
|
if (!screenshotsDir.exists()) {
|
|
|
|
|
screenshotsDir.mkdirs();
|
|
|
|
|
}
|
|
|
|
|
String screenshotFilePath = screenshotsDir.getAbsolutePath() + File.separator + timestampedFileName;
|
|
|
|
|
File screenshotFile = ((TakesScreenshot) driver).getScreenshotAs(OutputType.FILE);
|
|
|
|
|
try {
|
|
|
|
|
FileUtils.copyFile(screenshotFile, new File(screenshotFilePath));
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
e.printStackTrace();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|