一、反思我的代码
对于有相同步骤的代码我只是复制粘贴,不简洁,也显示的不聪明。
package Test12306;
import com.sun.org.apache.bcel.internal.ExceptionConstants;
import org.apache.commons.io.FileUtils;
import org.checkerframework.checker.units.qual.A;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.CsvSource;
import org.openqa.selenium.*;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.chrome.ChromeOptions;
import org.openqa.selenium.interactions.Actions;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;
import java.io.File;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.concurrent.TimeUnit;
public class Test12306 {
private WebDriver driver;
@BeforeEach
public void setup() {
//提交最终代码脚本时,请将驱动路径换回官方路径"C:\\Users\\86153\\AppData\\Local\\Google\\Chrome\\Application\\chromedriver.exe"
System.setProperty("webdriver.chrome.driver", "D:\\RuanJian\\google\\chrome-win64\\chromedriver.exe");
ChromeOptions chromeOptions = new ChromeOptions();
chromeOptions.addArguments("--remote-allow-origins=*");
driver = new ChromeDriver(chromeOptions);
driver.get("https://www.12306.cn/index/index.html");
//https://www.12306.cn/index/index.html
driver.manage().window().maximize();
driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
}
// test-code-start
// 请在这里插入JUnit5测试代码
@ParameterizedTest
@CsvSource({
"12306_R001_001.png, 2024-10-25, 12306_R001_002.png", "12306_R001_001.png, 2024-10-26, 12306_R001_003.png", "12306_R001_001.png, 2024-11-02, 12306_R001_004.png", "12306_R001_001.png, 2024-11-09, 12306_R001_005.png", "12306_R001_001.png, 2024-11-10, 12306_R001_006.png",})
public void test_12306_R001(String fileName1, String date, String filename) throws InterruptedException {
// 请在这里插入测试代码
Actions actions = new Actions(driver);
WebElement ticket = driver.findElement(By.id("J-chepiao"));
actions.moveToElement(ticket).perform();
Thread.sleep(1000);
driver.findElement(By.cssSelector("#member .nav_dan a")).click();
takeScreenshot(fileName1);
driver.findElement(By.id("fromStationText")).clear();
driver.findElement(By.id("fromStationText")).click();
Thread.sleep(1000);
driver.findElement(By.xpath("//*[@id=\"ul_list1\"]/li[1]")).click();
driver.findElement(By.id("toStationText")).clear();
driver.findElement(By.id("toStationText")).click();
Thread.sleep(1000);
driver.findElement(By.xpath("//*[@id=\"ul_list1\"]/li[9]")).click();
driver.findElement(By.name("leftTicketDTO.train_date")).clear();
driver.findElement(By.name("leftTicketDTO.train_date")).sendKeys(date);
driver.findElement(By.id("query_ticket")).click();
Thread.sleep(1500);
takeScreenshot(filename);
}
@ParameterizedTest
@CsvSource({
"2024-10-24, 12306_R002_001.png", "2024-10-25, 12306_R002_002.png", "2024-10-26, 12306_R002_003.png", "2024-10-09, 12306_R002_004.png", "2024-10-10, 12306_R002_005.png", "2024-10-11, 12306_R002_006.png",
})
public void test_12306_R002(String date, String filename) throws InterruptedException {
Actions actions = new Actions(driver);
WebElement ticket = driver.findElement(By.id("J-chepiao"));
actions.moveToElement(ticket).perform();
Thread.sleep(1000);
driver.findElement(By.cssSelector("#member .nav_dan a")).click();
driver.findElement(By.id("fromStationText")).clear();
driver.findElement(By.id("fromStationText")).click();
Thread.sleep(1000);
driver.findElement(By.xpath("//*[@id=\"ul_list1\"]/li[1]")).click();
driver.findElement(By.id("toStationText")).clear();
driver.findElement(By.id("toStationText")).click();
Thread.sleep(1000);
driver.findElement(By.xpath("//*[@id=\"ul_list1\"]/li[9]")).click();
driver.findElement(By.name("leftTicketDTO.train_date")).clear();
driver.findElement(By.name("leftTicketDTO.train_date")).sendKeys(date);
driver.findElement(By.id("query_ticket")).click();
Thread.sleep(1500);
takeScreenshot(filename);
}
@Test
public void test_12306_R003() throws InterruptedException {
Actions actions = new Actions(driver);
WebElement ticket = driver.findElement(By.id("J-chepiao"));
actions.moveToElement(ticket).perform();
Thread.sleep(1000);
driver.findElement(By.cssSelector("#member .nav_dan a")).click();
driver.findElement(By.id("fromStationText")).clear();
driver.findElement(By.id("fromStationText")).click();
Thread.sleep(1000);
driver.findElement(By.xpath("//*[@id=\"ul_list1\"]/li[1]")).click();
driver.findElement(By.id("toStationText")).clear();
driver.findElement(By.id("toStationText")).click();
Thread.sleep(1000);
driver.findElement(By.xpath("//*[@id=\"ul_list1\"]/li[2]")).click();
driver.findElement(By.name("leftTicketDTO.train_date")).clear();
driver.findElement(By.name("leftTicketDTO.train_date")).sendKeys("2024-10-30");
driver.findElement(By.id("query_ticket")).click();
Thread.sleep(1500);
driver.findElement(By.name("cc_type")).click();
Thread.sleep(1500);
takeScreenshot("12306_R003_001.png");
driver.findElement(By.name("cc_type")).click();
driver.findElement(By.name("cc_from_station")).click();
Thread.sleep(1500);
takeScreenshot("12306_R003_002.png");
driver.findElement(By.name("cc_from_station")).click();
driver.findElement(By.name("cc_to_station")).click();
Thread.sleep(1500);
takeScreenshot("12306_R003_003.png");
driver.findElement(By.name("cc_to_station")).click();
driver.findElement(By.name("cc_seat_type")).click();
Thread.sleep(1500);
takeScreenshot("12306_R003_004.png");
driver.findElement(By.name("cc_seat_type")).click();
}
@ParameterizedTest
@CsvSource({"2024-11-07, 12306_R004_001.png", "2024-11-19, 12306_R004_002.png", "2024-11-20, 12306_R004_003.png", "2024-11-21, 12306_R004_004.png",})
//思路是:我写这个代码的时间是11.6,返程日期肯定是在今天之后,我选择了四个日期。分别是今天后的第一天,出发日 的前一天,预售期当天,预售期的后一天
public void test_12306_R004(String date, String filName) throws InterruptedException {
Actions actions = new Actions(driver);
WebElement ticket = driver.findElement(By.id("J-chepiao"));
actions.moveToElement(ticket).perform();
Thread.sleep(1000);
driver.findElement(By.cssSelector("#member .nav_wang a")).click();
//出发地
driver.findElement(By.id("fromStationText")).click();
driver.findElement(By.id("fromStationText")).sendKeys("北京北" + Keys.ENTER);
//目的地
driver.findElement(By.id("toStationText")).click();
driver.findElement(By.id("toStationText")).sendKeys("哈尔滨北" + Keys.ENTER);
//出发日期
driver.findElement(By.id("train_date")).clear();
driver.findElement(By.id("train_date")).sendKeys("2024-11-06");
//返程日期
driver.findElement(By.id("back_train_date")).clear();
driver.findElement(By.id("back_train_date")).sendKeys(date);
driver.findElement(By.id("query_ticket")).click();
Thread.sleep(1500);
takeScreenshot(filName);
}
@ParameterizedTest
@CsvSource({"2024-11-05, 12306_R005_001.png", "2024-11-21, 12306_R005_002.png", "2024-11-22, 12306_R005_003.png",})
public void test_12306_R005(String date, String fileName) throws InterruptedException {
Actions actions = new Actions(driver);
WebElement chePiao = driver.findElement(By.id("J-chepiao"));
actions.moveToElement(chePiao).perform();
Thread.sleep(1000);
driver.findElement(By.cssSelector("#member .nav_wang a")).click();
//出发地
driver.findElement(By.id("fromStationText")).click();
driver.findElement(By.id("fromStationText")).sendKeys("北京北" + Keys.ENTER);
//目的地
driver.findElement(By.id("toStationText")).click();
driver.findElement(By.id("toStationText")).sendKeys("哈尔滨北" + Keys.ENTER);
//出发日期
driver.findElement(By.id("train_date")).clear();
driver.findElement(By.id("train_date")).sendKeys("2024-11-06");
//返程日期
driver.findElement(By.id("back_train_date")).clear();
driver.findElement(By.id("back_train_date")).sendKeys(date);
driver.findElement(By.id("query_ticket")).click();
Thread.sleep(1500);
takeScreenshot(fileName);
}
@ParameterizedTest
@CsvSource({
"12306_R006_001.png"
})
public void test_12306_R006(String fileName) throws InterruptedException {
Actions actions = new Actions(driver);
WebElement chePiao = driver.findElement(By.id("J-chepiao"));
actions.moveToElement(chePiao).perform();
Thread.sleep(1000);
driver.findElement(By.cssSelector("#member .nav_wang a")).click();
//出发地
driver.findElement(By.id("fromStationText")).click();
driver.findElement(By.id("nav_list3")).click();
driver.findElement(By.xpath("//*[@id=\"ul_list3\"]/ul[1]/li[4]")).click();
//目的地
driver.findElement(By.id("toStationText")).click();
driver.findElement(By.xpath("//*[@id=\"ul_list1\"]/li[33]")).click();
//出发日期
driver.findElement(By.id("train_date")).clear();
driver.findElement(By.id("train_date")).sendKeys("2024-11-06");
//返程日期
driver.findElement(By.id("back_train_date")).clear();
driver.findElement(By.id("back_train_date")).sendKeys("2024-11-20");
//选学生票
driver.findElement(By.id("sf2_label")).click();
//查询
driver.findElement(By.id("query_ticket")).click();
//选11.10周日
driver.findElement(By.xpath("//*[@id=\"date_range\"]/ul/li[5]/span[1]/a")).click();
//选智能动车组
driver.findElement(By.name("cc_type")).click();
//选显示折扣车次
driver.findElement(By.xpath("//*[@id=\"avail_zk\"]")).click();
//查询
driver.findElement(By.id("query_ticket")).click();
takeScreenshot(fileName);
}
@ParameterizedTest
@CsvSource({
"哈尔滨, 济南, 12306_R007_001.png",
"哈尔滨, 西安, 12306_R007_002.png",
"哈尔滨, 拉萨, 12306_R007_003.png",
"长春, 济南, 12306_R007_004.png",
"长春, 西安, 12306_R007_005.png",
"长春, 拉萨, 12306_R007_006.png",
"安吉, 济南, 12306_R007_007.png",
"安吉, 西安, 12306_R007_008.png",
"安吉, 拉萨, 12306_R007_009.png",
})
public void test_12306_R007(String from, String to, String fileName) throws InterruptedException {
//鼠标悬停
Actions actions = new Actions(driver);
WebElement chePiao = driver.findElement(By.id("J-chepiao"));
actions.moveToElement(chePiao).perform();
driver.findElement(By.linkText("中转换乘")).click();
//出发地
driver.findElement(By.id("fromStationText")).click();
driver.findElement(By.id("fromStationText")).sendKeys(from + Keys.ENTER);
// 目的地
driver.findElement(By.id("toStationText")).click();
driver.findElement(By.id("toStationText")).sendKeys(to + Keys.ENTER);
// 出发日期
driver.findElement(By.id("train_start_date")).clear();
driver.findElement(By.id("train_start_date")).sendKeys("2024-11-08");
// 点击查询
driver.findElement(By.id("_a_search_btn")).click();
Thread.sleep(2000);
takeScreenshot(fileName);
}
@ParameterizedTest
@CsvSource({
" , 12306_R008_001.png",
"洛阳!, 12306_R008_002.png",
"宝鸡, 12306_R008_003.png",
})
public void test_12306_R008(String changeStation, String fileName) throws InterruptedException {
//鼠标悬停
Actions actions = new Actions(driver);
WebElement chePiao = driver.findElement(By.id("J-chepiao"));
actions.moveToElement(chePiao).perform();
driver.findElement(By.linkText("中转换乘")).click();
//出发地
driver.findElement(By.id("fromStationText")).click();
driver.findElement(By.id("fromStationText")).sendKeys("西安" + Keys.ENTER);
// 目的地
driver.findElement(By.id("toStationText")).click();
driver.findElement(By.id("toStationText")).sendKeys("上海" + Keys.ENTER);
// 出发日期
driver.findElement(By.id("train_start_date")).clear();
driver.findElement(By.id("train_start_date")).sendKeys("2024-11-08");
//指定日期
if(changeStation == null){
driver.findElement(By.id("radio_input_search")).click();
driver.findElement(By.id("changeStationText")).clear();
}else {
driver.findElement(By.id("radio_input_search")).click();
driver.findElement(By.id("changeStationText")).clear();
driver.findElement(By.id("changeStationText")).sendKeys(changeStation + Keys.ENTER);
}
// 点击查询
driver.findElement(By.id("_a_search_btn")).click();
Thread.sleep(1000);
takeScreenshot(fileName);
}
@ParameterizedTest
@CsvSource({
"济南, 12306_R009_001.png",
"安阳, 12306_R009_002.png",
"周口, 12306_R009_003.png",
})
public void test_12306_R009(String changeStation, String fileName) throws InterruptedException {
//鼠标悬停
Actions actions = new Actions(driver);
WebElement chePiao = driver.findElement(By.id("J-chepiao"));
actions.moveToElement(chePiao).perform();
driver.findElement(By.linkText("中转换乘")).click();
//出发地
driver.findElement(By.id("fromStationText")).click();
driver.findElement(By.id("fromStationText")).sendKeys("哈尔滨" + Keys.ENTER);
// 目的地
driver.findElement(By.id("toStationText")).click();
driver.findElement(By.id("toStationText")).sendKeys("南京" + Keys.ENTER);
// 出发日期
driver.findElement(By.id("train_start_date")).clear();
driver.findElement(By.id("train_start_date")).sendKeys("2024-11-08");
//指定日期
driver.findElement(By.id("radio_input_search")).click();
driver.findElement(By.id("changeStationText")).clear();
driver.findElement(By.id("changeStationText")).sendKeys(changeStation + Keys.ENTER);
// 点击查询
driver.findElement(By.id("_a_search_btn")).click();
Thread.sleep(1000);
takeScreenshot(fileName);
}
//R010暂时还没哟写出来
@Test
public void test_12306_R010() throws InterruptedException {
//鼠标悬停
Actions actions = new Actions(driver);
WebElement chePiao = driver.findElement(By.id("J-chepiao"));
actions.moveToElement(chePiao).perform();
driver.findElement(By.linkText("计次•定期票")).click();
driver.findElement(By.linkText("扫码登录")).click();
Thread.sleep(15000);
WebElement chePiao1 = driver.findElement(By.id("J-chepiao"));
actions.moveToElement(chePiao1).perform();
driver.findElement(By.linkText("计次•定期票")).click();
//悬停
WebElement start = driver.findElement(By.id("city-start"));
actions.moveToElement(start).perform();
WebElement st = driver.findElement(By.id("start-box"));
List<WebElement> listItems = st.findElements(By.tagName("li"));
System.out.println('1');
if (!listItems.isEmpty()) {
WebDriverWait wait = new WebDriverWait(driver, 10);
WebElement hankou = listItems.get(0); // 获取第一个 <li> 元素
// 对 hankou 进行操作
wait.until(ExpectedConditions.elementToBeClickable(hankou));
// 点击 hankou 元素
hankou.click();
System.out.println("点击了 hankou 元素");
}
}
// test-code-end
@AfterEach
public void teardown() {
//this.driver.quit();
}
private void takeScreenshot(String fileName) {
SimpleDateFormat dateFormat = new SimpleDateFormat("HHmmssSSS");
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));
System.out.println("Current working directory: " + System.getProperty("user.dir"));
} catch (Exception e) {
e.printStackTrace();
}
}
}
WebElement st = driver.findElement(By.id("start-box")); List<WebElement> listItems = st.findElements(By.tagName("li")); System.out.println('1'); if (!listItems.isEmpty()) { WebElement hankou = listItems.get(0); // 获取第一个 <li> 元素 // 对 hankou 进行操作 hankou.click(); }
二、分析答案
R001
我们在需求文档中可以看到,所有的需求都不是在首页面进行的,而是进入了我们要测试的页面,
所以,我们要将每个模块的具有相同操作的步骤 编写成一个公共的函数,到时候再我们的需求函数中直接调用即可。
还有注意的一个点:答案里的等同于findElementBy()的都以注解的形式出现,而这样我们可以直接调用。
1.遇到的错误:
1.悬浮是Actions(哭笑)
2.我们在编写的每个模块里的公共方法里要写上这么一句代码:PageFactory.initElements(driver, this);
作用:初始化元素,将driver和当前类绑定,就可以用@Findby注解来找到相应的元素就可以进行相应的操作,比如点击。
运行:
@ParameterizedTest
@CsvSource({
"北京,上海,2023-11-14,test_12306_001.png",
})
public void test_12306_R001(String fromStationText, String toStationText, String train_date, String fileName){
meth_oneWay_001_002_003();
fromStationTextElement.sendKeys(fromStationText);
toStationTextElement.sendKeys(toStationText);
train_dateElement.sendKeys(train_date);
query_ticketElement.click();
}
我们只是往这个输入框输入数据sendKeys()会出现这样的情况,此时我们需要改进代码:
2.遇到的错误
我们点击这个出发地输入框
然后再进行输值+回车,但是输入的是第一个,可能是北京北,我们要去掉最后面的北字
用的是:fromStationTextElement(Keys.BACK_SPACE);
尝试这四个的输入情况:
题目要求的地点是
北京,广州
上海,成都
之类的,所以当我们的出发地输入框和目的地输入框的值 不等于“上海”时,我们模拟一次back_space,(必须选择上海,因为上海输入后再ENTER还是上海,此时不用删一次,也就是模拟一次back_space)。
比赛当时的时间是10月26,今天是11.14。
答案里根据边界值和等价类选择的是这三个时间,出发地和目的地有随机性。
@ParameterizedTest
@CsvSource({
//
"北京,广州,2024-11-14,test_12306_R001_001.png",
"北京,成都,2024-11-20,test_12306_R001_002.png",
"上海,广州,2024-11-28,test_12306_R001_003.png",
"上海,成都,2024-11-14,test_12306_R001_004.png",
"北京,广州,2024-11-28,test_12306_R001_005.png",
"北京,成都,2024-11-14,test_12306_R001_006.png",
"上海,广州,2024-11-20,test_12306_R001_007.png",
"上海,成都,2024-11-28,test_12306_R001_008.png",
"北京,成都,2024-11-28,test_12306_R001_009.png",
})
public void test_12306_R001(String fromStationText, String toStationText, String train_date, String fileName) throws InterruptedException {
meth_oneWay_001_002_003();
fromStationTextElement.click();//点击出发地
fromStationTextElement.sendKeys(fromStationText + Keys.ENTER); //输入出发地
if (!Objects.equals(fromStationText, "上海")) {
fromStationTextElement.sendKeys(Keys.BACK_SPACE);
}
toStationTextElement.click();//点击目的地
toStationTextElement.sendKeys(toStationText + Keys.ENTER);//输入目的地
if (!Objects.equals(toStationText, "上海")) {
toStationTextElement.sendKeys(Keys.BACK_SPACE);
}
train_dateElement.clear(); //清空日期
train_dateElement.sendKeys(train_date); //输入日期
query_ticketElement.click();
Thread.sleep(1000);
}
R002
我们采用与R001相同的操作,我们可以选择其中的出发地为上海,这样依旧可以用模拟键盘的方式删掉最后一个多余的字。
这是出发地的无效等价类和边界值分析:
R003
这里有个我不太懂得地方,就是-通过鼠标点击的方式依次对车次类型、出发车站、到达车站和车次席别选中第一个可筛选项并取消选中的方式-,答案是通过先把所有的复选框的第一个先依次点一下,然后再把复选框的第一个依次点一下,相当于取消点击。
//第一个复选框
@FindBy(name = "cc_type")
public WebElement checkboxOneElement;
@FindBy(name = "cc_from_station")
public WebElement checkboxTwoElement;
@FindBy(name = "cc_to_station")
public WebElement checkboxThreeElement;
@FindBy(name = "cc_seat_type")
public WebElement checkboxFourElement;
@ParameterizedTest
@CsvSource({
"北京, 上海, 2024-11-14,test_12306_R003_001.png "
})
public void test_12306_R003(String fromStationText, String toStationText, String train_date, String fileName) throws InterruptedException {
meth_oneWay_001_002_003();
fromStationTextElement.click();//点击出发地
fromStationTextElement.sendKeys( "北京" + Keys.ENTER); //输入出发地
if (!Objects.equals(toStationText, "上海")) {
toStationTextElement.sendKeys(Keys.BACK_SPACE);
}
toStationTextElement.click();
toStationTextElement.sendKeys("上海" + Keys.ENTER);
if (!Objects.equals(toStationText, "上海")) {
toStationTextElement.sendKeys(Keys.BACK_SPACE);
}
train_dateElement.clear();
train_dateElement.sendKeys(train_date);
query_ticketElement.click();
checkboxOneElement.click();
checkboxTwoElement.click();
checkboxThreeElement.click();
checkboxFourElement.click();
Thread.sleep(1000);
checkboxOneElement.click();
checkboxTwoElement.click();
checkboxThreeElement.click();
checkboxFourElement.click();
takeScreenshot(fileName);
}
R004
此时是进入往返车票查询页面,我们先用@Findby()定位到往返车票,我们此时是进入的一个新的模块,所以我们从首页面进入到往返车票查询页面的这些操作我们要重新写一个公共方法
meth_wangFan_004_005_006()
@FindBy(linkText = "往返")
public WebElement wangFanElement;
public void meth_wangFan_004_005_006(){
PageFactory.initElements(driver, this);
//悬浮
Actions actions = new Actions(driver);
actions.moveToElement(ticketElement).perform();
wangFanElement.click();
}
//R004
@FindBy(id = "back_train_date")
public WebElement back_train_dateElement;
@ParameterizedTest
@CsvSource({
"上海, 北京, 2024-11-25,test_12306_R004_001.png ",
"上海, 北京, 2024-11-28, test_12306_R004_001.png",
"上海, 北京, 2024-11-21, test_12306_R004_001.png",
})
public void test_12306_R004(String fromStationText, String toStationText, String back_train_date, String fileName){
meth_wangFan_004_005_006();
//考虑到输入时的操作,题目没有限制说是两个字的目的地,所以我们点击+输入+enter
fromStationTextElement.click();
fromStationTextElement.sendKeys(fromStationText + Keys.ENTER);
toStationTextElement.click();
toStationTextElement.sendKeys(toStationText + Keys.ENTER);
if (!Objects.equals(toStationText, "上海")){
toStationTextElement.sendKeys(Keys.BACK_SPACE);
}
train_dateElement.clear();
train_dateElement.sendKeys("2024-11-22");
back_train_dateElement.clear();
back_train_dateElement.sendKeys(back_train_date);
query_ticketElement.click();
}
遇到的错误
这里需要注意一下找返程的那个元素进行定位的时候@Findby()用的是xpath,我用name就不行
R005
注意:这里的返程日期 若早于预售期会提示“返程日期不得早于出发日期 ”,若超出预期范围的会查到相应的车票。
@ParameterizedTest
@CsvSource({
"北京,上海,2024-11-21,test_12306_R005_001.png",
"北京,上海,2024-11-29,test_12306_R005_002.png",
})
public void test_12306_R005(String fromStationText, String toStationText, String back_train_date, String fileName){
meth_wangFan_004_005_006();
fromStationTextElement.click();
fromStationTextElement.sendKeys(fromStationText + Keys.ENTER);
toStationTextElement.click();
toStationTextElement.sendKeys(toStationText + Keys.ENTER);
train_dateElement.clear();
train_dateElement.sendKeys("2024-11-22");
back_train_dateElement.clear();
back_train_dateElement.sendKeys(back_train_date);
query_ticketElement.click();
}
R006
遇到的问题
点击玩查询后,我们要sleep,然后点 tab中的日期
在自动化测试脚本中,如果不等待查询操作完成后的页面更新就立即尝试与页面上的元素(如日期tab)进行交互,可能会因为以下几个原因导致“点不上”(即无法成功触发点击事件或操作无效):
DOM元素未更新:当查询操作发生时,Web页面的DOM(文档对象模型)可能会发生变化以显示新的查询结果。如果这些变化(如新的元素被添加到DOM中,或现有元素的属性被更改)尚未完成,那么尝试与这些元素交互可能会失败。例如,如果日期tab是在查询结果加载后才被添加到DOM中的,那么在查询操作后立即尝试点击它将会失败,因为此时它还不存在。
元素状态不正确:即使DOM元素已经存在,但如果它的状态(如是否可见、是否可点击)不符合交互要求,那么操作也会失败。例如,如果日期tab在查询结果加载后处于不可点击状态(可能是由于CSS样式、JavaScript事件监听器或其他原因),那么尝试点击它将不会有任何效果。
JavaScript执行未完成:Web页面上的许多交互都依赖于JavaScript的执行。如果查询操作触发了JavaScript代码来更新页面内容或元素状态,并且这些代码尚未执行完成,那么尝试与这些元素交互可能会失败或产生不可预测的结果。
网络延迟:查询操作可能需要从服务器获取数据,这可能会导致网络延迟。如果脚本不等待这些数据加载完成就尝试与页面上的元素交互,那么可能会因为数据尚未到达而导致操作失败。
因此,在自动化测试中,通常需要使用某种形式的等待机制来确保页面已经更新到可以交互的状态。这可以通过简单的
Thread.sleep()
方法来实现(尽管这不是最佳实践),或者更优雅地使用Selenium的WebDriverWait
和ExpectedConditions
来实现显式等待。显式等待允许脚本等待特定的条件成立(如某个元素变得可见或可点击),从而提高了测试的可靠性和灵活性。
//R006
//进入往返车票查询页面,要以控件的方式选择出发地和目的地
@FindBy(xpath = "//*[@id=\"nav_list3\"]")
public WebElement FGHIElement;
@FindBy(xpath = "//*[@id=\"ul_list3\"]/ul[1]/li[4]")
public WebElement FuZhouNanElement;
@FindBy(xpath = "//*[@id=\"ul_list1\"]/li[33]")
public WebElement XiaMenElement;
@FindBy(id = "sf2")
public WebElement checkboxStuElement;
@FindBy(xpath = "//*[@id=\"date_range\"]/ul/li[8]/span[1]")
public WebElement tabDateElement;
@FindBy(xpath = "//*[@id=\"_ul_station_train_code\"]/li[8]/label")// //*[@id="checkbox_ppY2To149M"]有数字不行
public WebElement checkboxLastElement;
@FindBy(id = "from_station_name_all")
public WebElement from_station_name_allElement;
@FindBy(id = "to_station_name_all")
public WebElement to_station_name_allElement;
@FindBy(id = "avail_zk")
public WebElement discountElement;
@Test
public void test_12306_R006() throws InterruptedException {
meth_wangFan_004_005_006();
fromStationTextElement.click();
FGHIElement.click();
FuZhouNanElement.click();
toStationTextElement.click();
XiaMenElement.click();
train_dateElement.clear();
train_dateElement.sendKeys("2024-11-18");
back_train_dateElement.clear();
back_train_dateElement.sendKeys("2024-11-23");
checkboxStuElement.click();
query_ticketElement.click();
Thread.sleep(2000);点击玩查询后,我们要sleep,然后点 tab中的日期
tabDateElement.click();
checkboxLastElement.click();
from_station_name_allElement.click();
to_station_name_allElement.click();
discountElement.click();
query_ticketElement.click();
takeScreenshot("test_12306_R006_001.png");
}
R007
if (Objects.equals(fromStationText, "哈尔滨")){ fromStationTextElement.sendKeys(Keys.BACK_SPACE); }
if (Objects.equals(fromStationText, "西安")){ fromStationTextElement.sendKeys(Keys.BACK_SPACE); }
@FindBy(linkText = "中转换乘")
public WebElement zhongZhuanElement;
@FindBy(id = "train_start_date")
public WebElement train_start_dateElement;
@FindBy(id = "_a_search_btn")
public WebElement chaXunElement;
public void meth_zhongZhuan_007_008_009(){
PageFactory.initElements(driver, this);
Actions actions = new Actions(driver);
actions.moveToElement(ticketElement).perform();
zhongZhuanElement.click();
}
@ParameterizedTest
@CsvSource({
"哈尔滨,济南,2024-11-15,test_12306_R007_001.png",
// "哈尔滨,西安,2024-11-15,test_12306_R007_001.png",
// "哈尔滨,拉萨,2024-11-15,test_12306_R007_001.png",
// "长春, 济南,2024-11-15,test_12306_R007_001.png",
// "长春, 西安,2024-11-15,test_12306_R007_001.png",
// "长春, 拉萨,2024-11-15,test_12306_R007_001.png",
// "安吉, 济南,2024-11-15,test_12306_R007_001.png",
// "安吉, 西安,2024-11-15,test_12306_R007_001.png",
// "安吉, 拉萨,2024-11-15,test_12306_R007_001.png",
})
public void test_12306_R007(String fromStationText, String toStationText, String trainStartDate, String fileName){
meth_zhongZhuan_007_008_009();
fromStationTextElement.click();
fromStationTextElement.sendKeys(fromStationText + Keys.ENTER);
if (Objects.equals(fromStationText, "哈尔滨")){
fromStationTextElement.sendKeys(Keys.BACK_SPACE);
}
toStationTextElement.click();
toStationTextElement.sendKeys(toStationText + Keys.ENTER);
if (Objects.equals(fromStationText, "西安")){
fromStationTextElement.sendKeys(Keys.BACK_SPACE);
}
train_start_dateElement.clear();
train_start_dateElement.sendKeys(trainStartDate);
chaXunElement.click();
}
R008
注意:凡是输入框的都加ENTER
@FindBy(id = "radio_input_search")
public WebElement radioElement;
@FindBy(id = "changeStationText")
public WebElement changeStationTextElement;
@ParameterizedTest
@CsvSource({
"福州南,厦门,2024-11-15,'', test_12306_R007_001.png",
"福州南,厦门,2024-11-15,?, test_12306_R007_002.png",
"福州南,厦门,2024-11-15,西藏, test_12306_R007_003.png",
})
public void test_12306_R008(String fromStationText, String toStationText, String trainStartDate, String change, String fileName){
meth_zhongZhuan_007_008_009();
fromStationTextElement.click();
fromStationTextElement.sendKeys(fromStationText + Keys.ENTER);
toStationTextElement.click();
toStationTextElement.sendKeys(toStationText + Keys.ENTER);
train_start_dateElement.clear();
train_start_dateElement.sendKeys(trainStartDate);
radioElement.click();
changeStationTextElement.click();
changeStationTextElement.sendKeys(change);
chaXunElement.click();
}
R009
@ParameterizedTest
@CsvSource({
// "哈尔滨, 南京 ,2024-11-15,济南, test_12306_R007_001.png",
// "哈尔滨, 南京 ,2024-11-15,安阳, test_12306_R007_002.png",
"哈尔滨, 南京 ,2024-11-15,周口, test_12306_R007_003.png",
})
public void test_12306_R009(String fromStationText, String toStationText, String trainStartDate, String change, String fileName){
meth_zhongZhuan_007_008_009();
fromStationTextElement.click();
fromStationTextElement.sendKeys(fromStationText + Keys.ENTER);
if (Objects.equals(fromStationText,"哈尔滨")){
fromStationTextElement.sendKeys(Keys.BACK_SPACE);
}
toStationTextElement.click();
toStationTextElement.sendKeys(toStationText + Keys.ENTER);
train_start_dateElement.clear();
train_start_dateElement.sendKeys(trainStartDate);
radioElement.click();
changeStationTextElement.click();
changeStationTextElement.sendKeys(change +Keys.ENTER);
if (Objects.equals(change,"周口")){
changeStationTextElement.sendKeys(Keys.BACK_SPACE);
}
chaXunElement.click();
}
三、正确答案
import org.apache.commons.io.FileUtils;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.CsvSource;
import org.openqa.selenium.*;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.chrome.ChromeOptions;
import org.openqa.selenium.interactions.Actions;
import org.openqa.selenium.support.FindBy;
import org.openqa.selenium.support.PageFactory;
import java.io.File;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Objects;
import java.util.concurrent.TimeUnit;
public class Test12306 {
private WebDriver driver;
@BeforeEach
public void setup(){
System.setProperty("webdriver.chrome.driver", "C:\\Users\\86153\\AppData\\Local\\Google\\Chrome\\Application\\chromedriver.exe");
ChromeOptions chromeOptions = new ChromeOptions();
chromeOptions.addArguments("--remote-allow-origins=*");
driver = new ChromeDriver(chromeOptions);
driver.get("https://www.12306.cn/index/index.html");
driver.manage().window().maximize();
driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
}
//test-code-start
@FindBy(linkText = "车票")
public WebElement chepiaoElement;
@FindBy(linkText="单程")
public WebElement g_hrefElement;
@FindBy(linkText = "中转换乘")
public WebElement zzhcElement;
@FindBy(linkText = "往返")
public WebElement wangfanElement;
@FindBy(id = "fromStationText")
public WebElement fromStationElement;
@FindBy(id="toStationText")
public WebElement toStationElement;
@FindBy(id="train_date")
public WebElement trainDate;
@FindBy(linkText="查询")
public WebElement queryTicket;
public void meth_pub_001_002_003(){
PageFactory.initElements(driver,this);
Actions actions =new Actions(driver);
actions.moveToElement(chepiaoElement).perform();
g_hrefElement.click();
}
public void meth_pub_004_005_006(){
PageFactory.initElements(driver,this);
Actions actions =new Actions(driver);
actions.moveToElement(chepiaoElement).perform();
wangfanElement.click();
}
public void meth_pub_007_008_009(){
PageFactory.initElements(driver,this);
Actions actions =new Actions(driver);
actions.moveToElement(chepiaoElement).perform();
zzhcElement.click();
}
//R001
@ParameterizedTest
@CsvSource({
"北京,广州,2024-10-26,test_12306_R001_001.png",
"北京,成都,2024-10-31,test_12306_R001_002.png",
"上海,广州,2024-11-09,test_12306_R001_003.png",
"上海,成都,2024-10-26,test_12306_R001_004.png",
"北京,广州,2024-11-09,test_12306_R001_005.png",
"北京,成都,2024-10-26,test_12306_R001_006.png",
"上海,广州,2024-10-31,test_12306_R001_007.png",
"上海,成都,2024-11-09,test_12306_R001_008.png",
"北京,成都,2024-11-09,test_12306_R001_009.png",
})
public void test_12306_R001(String fromStation,String toStation,String Date,String filename) throws InterruptedException {
meth_pub_001_002_003();
fromStationElement.click();
fromStationElement.sendKeys(fromStation+Keys.ENTER);
if (!Objects.equals(fromStation,"上海")){
fromStationElement.sendKeys(Keys.BACK_SPACE);
}
toStationElement.click();
toStationElement.sendKeys(toStation+Keys.ENTER);
if (!Objects.equals(toStation,"上海")){
toStationElement.sendKeys(Keys.BACK_SPACE);
}
trainDate.clear();
trainDate.sendKeys(Date);
queryTicket.click();
Thread.sleep(1000);
takeScreenshot(filename);
}
//R002
@ParameterizedTest
@CsvSource(
{
"郑州东,上海,2024-10-25,test_12306_R002_001.png",
"郑州东,上海,2024-11-10,test_12306_R002_002.png"
})
public void test_12306_R002(String fromStation,String toStation,String Date,String filename) throws InterruptedException {
meth_pub_001_002_003();
fromStationElement.click();
fromStationElement.sendKeys(fromStation+Keys.ENTER);
toStationElement.click();
toStationElement.sendKeys(toStation+Keys.ENTER);
trainDate.clear();
trainDate.sendKeys(Date);
queryTicket.click();
Thread.sleep(1000);
takeScreenshot(filename);
}
//R003
@FindBy(name = "cc_type")
public WebElement checkboxOne;
@FindBy(name="cc_from_station")
public WebElement checkboxTwo;
@FindBy(name="cc_to_station")
public WebElement checkboxThree;
@FindBy(name="cc_seat_type")
public WebElement checkboxFour;
@Test
public void test_12306_R003() throws InterruptedException {
meth_pub_001_002_003();
fromStationElement.click();
fromStationElement.sendKeys("北京"+Keys.ENTER);
if (!Objects.equals("北京","上海")){
fromStationElement.sendKeys(Keys.BACK_SPACE);
}
toStationElement.click();
toStationElement.sendKeys("上海"+Keys.ENTER);
trainDate.clear();
//此处由于比赛日期已过 故选择一个有效日期去测试
trainDate.sendKeys("2024-11-08");
queryTicket.click();
checkboxOne.click();
checkboxTwo.click();
checkboxThree.click();
checkboxFour.click();
Thread.sleep(2000);
checkboxOne.click();
checkboxTwo.click();
checkboxThree.click();
checkboxFour.click();
Thread.sleep(1000);
takeScreenshot("test_12306_R003_001.png");
}
//R004
@FindBy(id="back_train_date")
public WebElement backTrainDate;
@ParameterizedTest
@CsvSource(
{
"郑州东,上海,2024-11-01,2024-11-01,test_12306_R004_001.png",
"郑州东,上海,2024-11-01,2024-11-08,test_12306_R004_002.png",
"郑州东,上海,2024-11-01,2024-11-11,test_12306_R004_003.png"
})
public void test_12306_R004(String fromStation,String toStation,String Date,String backDate,String filename) throws InterruptedException {
meth_pub_004_005_006();
fromStationElement.click();
fromStationElement.sendKeys(fromStation+Keys.ENTER);
toStationElement.click();
toStationElement.sendKeys(toStation+Keys.ENTER);
trainDate.clear();
trainDate.sendKeys(Date);
backTrainDate.clear();
backTrainDate.sendKeys(backDate);
queryTicket.click();
Thread.sleep(1000);
takeScreenshot(filename);
}
//R005
@ParameterizedTest
@CsvSource(
{
"郑州东,上海,2024-11-02,2024-11-01,test_12306_R005_001.png",
"郑州东,上海,2024-11-02,2024-11-12,test_12306_R005_002.png",
})
public void test_12306_R005(String fromStation,String toStation,String Date,String backDate,String filename) throws InterruptedException {
meth_pub_004_005_006();
fromStationElement.click();
fromStationElement.sendKeys(fromStation+Keys.ENTER);
toStationElement.click();
toStationElement.sendKeys(toStation+Keys.ENTER);
trainDate.clear();
trainDate.sendKeys(Date);
backTrainDate.clear();
backTrainDate.sendKeys(backDate);
queryTicket.click();
Thread.sleep(1000);
takeScreenshot(filename);
}
@FindBy(id="nav_list3")
public WebElement navList3;
@FindBy(xpath = "//li[@title=\'福州南\']")
public WebElement fuZhouNan;
@FindBy(xpath = "//li[@title=\'厦门\']")
public WebElement xiaMen;
@FindBy(id="sf2")
public WebElement stu;
@FindBy(xpath = "//*[@id=\"date_range\"]/ul/li[6]")
public WebElement path1;
@FindBy(xpath = "//*[@id=\"_ul_station_train_code\"]/li[8]")
public WebElement path2;
@FindBy(id = "from_station_name_all")
public WebElement path3;
@FindBy(id = "to_station_name_all")
public WebElement path4;
@FindBy(id = "avail_zk")
public WebElement availZk;
//R006
@Test
public void test_12306_R006() throws InterruptedException {
meth_pub_004_005_006();
fromStationElement.click();
navList3.click();
fuZhouNan.click();
toStationElement.click();
xiaMen.click();
//由于比赛时间已过此处日期填写成出发日2024-11-12 返程日2024-11-15
trainDate.clear();
trainDate.sendKeys("2024-11-12");
backTrainDate.clear();
backTrainDate.sendKeys("2024-11-15");
stu.click();
queryTicket.click();
//此处在Tab中日期选择为11-13
path1.click();
path2.click();
path3.click();
path4.click();
availZk.click();
Thread.sleep(1000);
takeScreenshot("test_12306_R006_001.png");
}
@FindBy(id="train_start_date")
public WebElement trainStartDate;
@ParameterizedTest
@CsvSource({
//此处日期选择2024-11-22
"哈尔滨,济南,2024-11-22,test_12306_R007_001.png",
"哈尔滨,西安,2024-11-22,test_12306_R007_002.png",
"哈尔滨,拉萨,2024-11-22,test_12306_R007_003.png",
"长春,济南,2024-11-22,test_12306_R007_004.png",
"长春,西安,2024-11-22,test_12306_R007_005.png",
"长春,拉萨,2024-11-22,test_12306_R007_006.png",
"安吉,济南,2024-11-22,test_12306_R007_007.png",
"安吉,西安,2024-11-22,test_12306_R007_008.png",
"安吉,拉萨,2024-11-22,test_12306_R007_009.png"
})
public void test_12306_R007(String fromStation,String toStation,String Date,String filename) throws InterruptedException {
meth_pub_007_008_009();
fromStationElement.click();
fromStationElement.sendKeys(fromStation+Keys.ENTER);
if(Objects.equals(fromStation,"哈尔滨")){
fromStationElement.sendKeys(Keys.BACK_SPACE);
}
toStationElement.click();
toStationElement.sendKeys(toStation+Keys.ENTER);
if(Objects.equals(toStation,"西安")){
toStationElement.sendKeys(Keys.BACK_SPACE);
}
trainStartDate.clear();
trainStartDate.sendKeys(Date);
queryTicket.click();
Thread.sleep(1000);
takeScreenshot(filename);
}
@FindBy(id = "radio_input_search")
public WebElement radioInputSearch;
@FindBy(id="changeStationText")
public WebElement changeStationText;
@ParameterizedTest
@CsvSource({
//此处日期选择2024-11-22
"郑州东,上海,2024-11-22,'',test_12306_R008_001.png",
"郑州东,上海,2024-11-22,&$,test_12306_R008_002.png",
"郑州东,上海,2024-11-22,红苹果,test_12306_R008_003.png",
})
public void test_12306_R008(String fromStation,String toStation,String Date,String param,String filename) throws InterruptedException {
meth_pub_007_008_009();
fromStationElement.click();
fromStationElement.sendKeys(fromStation+Keys.ENTER);
toStationElement.click();
toStationElement.sendKeys(toStation+Keys.ENTER);
trainStartDate.clear();
trainStartDate.sendKeys(Date);
radioInputSearch.click();
changeStationText.click();
changeStationText.sendKeys(param);
queryTicket.click();
Thread.sleep(1000);
takeScreenshot(filename);
}
@ParameterizedTest
@CsvSource({
//此处日期选择2024-11-22
"哈尔滨,南京,2024-11-22,济南,test_12306_R009_001.png",
"哈尔滨,南京,2024-11-22,安阳,test_12306_R009_002.png",
"哈尔滨,南京,2024-11-22,周口,test_12306_R009_003.png",
})
public void test_12306_R009(String fromStation,String toStation,String Date,String param,String filename) throws InterruptedException {
meth_pub_007_008_009();
fromStationElement.click();
fromStationElement.sendKeys(fromStation+Keys.ENTER);
if(Objects.equals(fromStation,"哈尔滨")){
fromStationElement.sendKeys(Keys.BACK_SPACE);
}
toStationElement.click();
toStationElement.sendKeys(toStation+Keys.ENTER);
trainStartDate.clear();
trainStartDate.sendKeys(Date);
radioInputSearch.click();
changeStationText.click();
changeStationText.sendKeys(param+Keys.ENTER);
if(Objects.equals(param,"周口")){
changeStationText.sendKeys(Keys.BACK_SPACE);
}
queryTicket.click();
Thread.sleep(2000);
takeScreenshot(filename);
}
//自动发挥部分省略
//test-code-end
@AfterEach
public void teardown(){
this.driver.quit();
}
private void takeScreenshot(String fileName) {
SimpleDateFormat dateFormat = new SimpleDateFormat("HHmmssSSS");
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();
}
}
}