使用Java Selenium WebDriver移除购物车商品后如何正确断言已删除
问题根因
- 断言逻辑完全错误:你的@Then步骤是要验证购物车为空,但你用了
contains(expected)匹配器,这个匹配器的作用是校验列表包含指定元素,完全和需求相反;同时你声明的expected变量没有做任何赋值操作,是空值,必然触发断言失败。 - 匹配器使用错误:
contains是Hamcrest的严格匹配器,要求列表的元素数量、顺序、值完全和入参一致,如果你只是要校验列表是否包含单个元素,应该用hasItem匹配器。 - 缺少异步等待:前端移除购物车商品一般是异步请求渲染,点击移除按钮后立即获取商品列表,大概率拿到的是操作前的旧数据,导致断言结果不符合预期。
- 如果你需要校验被移除的商品不在列表中,你现有的代码没有在移除前记录要删除的商品名称,没有预期值可以用来对比。
修复方案
场景1:验证移除后购物车完全为空(匹配你现有@Then注解的逻辑)
第一步:在TrolleyPage中加显式等待逻辑,避免拿旧数据
import org.openqa.selenium.support.ui.WebDriverWait; import org.openqa.selenium.support.ui.ExpectedConditions; import java.time.Duration; public class TrolleyPage { // 初始化显式等待,超时时间可根据你的页面响应速度调整 private WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(10)); public void removeFromTrolley() { List<WebElement> removeProductBtnList = driver.findElements(By.cssSelector("button[data-test='basket-removeproduct']")); int size = removeProductBtnList.size(); System.out.println("Number of size of Added product in trolley " + size); WebElement removedWebElement = removeProductBtnList.get(0); removedWebElement.click(); } public List<String> getAllProductsInTrolley() { List<String> actualList = new ArrayList<>(); // 先等商品名称元素加载稳定 wait.until(ExpectedConditions.presenceOfAllElementsLocatedBy(By.cssSelector("a[data-e2e='product-name']"))); List<WebElement> productWebElements = driver.findElements(By.cssSelector("a[data-e2e='product-name']")); for (WebElement product : productWebElements) { String productName = product.getText(); if (!productName.isEmpty()) { actualList.add(productName); System.out.println("Product :" + productName); } } return actualList; } }
第二步:修改断言逻辑
import static org.hamcrest.Matchers.empty; import static org.hamcrest.MatcherAssert.assertThat; @Then("^I should see the the trolley is empty$") public void i_should_see_the_the_trolley_is_empty() { List<String> actualList = trolleyPage.getAllProductsInTrolley(); // 校验列表为空 assertThat(actualList, empty()); // 也可以用原生断言:Assert.assertTrue(actualList.isEmpty()); }
场景2:验证被移除的指定商品不在购物车中(适用于移除多个商品中的一个的场景)
第一步:修改TrolleyPage的移除方法,返回被移除的商品名称
public class TrolleyPage { private WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(10)); // 移除第一个商品,返回被移除的商品名 public String removeFirstProductFromTrolley() { // 先获取第一个商品的名称 List<WebElement> productWebElements = driver.findElements(By.cssSelector("a[data-e2e='product-name']")); String removedProductName = productWebElements.get(0).getText().trim(); // 点击移除按钮 List<WebElement> removeProductBtnList = driver.findElements(By.cssSelector("button[data-test='basket-removeproduct']")); removeProductBtnList.get(0).click(); return removedProductName; } // getAllProductsInTrolley方法同上,保留显式等待逻辑 }
第二步:修改测试步骤和断言
import static org.hamcrest.Matchers.not; import static org.hamcrest.Matchers.hasItem; import static org.hamcrest.MatcherAssert.assertThat; public class RemoveTheProductDefs { private TrolleyPage trolleyPage = new TrolleyPage(); private String removedProductName; // 存储被移除的商品名 @When("^I remove a product$") public void i_remove_a_product() { removedProductName = trolleyPage.removeFirstProductFromTrolley(); } @Then("^the removed product should not exist in trolley$") public void the_removed_product_should_not_exist_in_trolley() { List<String> actualList = trolleyPage.getAllProductsInTrolley(); // 校验列表不包含被移除的商品名 assertThat(actualList, not(hasItem(removedProductName))); } }
内容的提问来源于stack exchange,提问作者Jigar Patel
相关产品推荐
相关产品推荐

