From ff3bc2a809fbea517378b9f12e9e50ea9b151720 Mon Sep 17 00:00:00 2001 From: zzzk1 Date: Sat, 15 Feb 2025 13:04:45 +0800 Subject: [PATCH 1/2] improve(test): Use explicit wait for time-based conditions --- .../test/web/ui/MetalakePageTest.java | 2 +- .../test/web/ui/pages/CatalogsPage.java | 237 ++++++++---------- .../test/web/ui/pages/MetalakePage.java | 18 +- .../test/web/ui/utils/BaseWebIT.java | 10 +- 4 files changed, 115 insertions(+), 152 deletions(-) diff --git a/web/integration-test/src/test/java/org/apache/gravitino/integration/test/web/ui/MetalakePageTest.java b/web/integration-test/src/test/java/org/apache/gravitino/integration/test/web/ui/MetalakePageTest.java index 93617927382..50ed90c4e6a 100644 --- a/web/integration-test/src/test/java/org/apache/gravitino/integration/test/web/ui/MetalakePageTest.java +++ b/web/integration-test/src/test/java/org/apache/gravitino/integration/test/web/ui/MetalakePageTest.java @@ -104,7 +104,7 @@ public void testCreateMultipleMetalakes() throws InterruptedException { for (int i = 0; i < twoPagesCount; i++) { try { - Thread.sleep(ACTION_SLEEP_MILLIS); + Thread.sleep(ACTION_SLEEP * 1000); } catch (Exception e) { LOG.error(e.getMessage(), e); } diff --git a/web/integration-test/src/test/java/org/apache/gravitino/integration/test/web/ui/pages/CatalogsPage.java b/web/integration-test/src/test/java/org/apache/gravitino/integration/test/web/ui/pages/CatalogsPage.java index 1bd2104479e..296059fad3b 100644 --- a/web/integration-test/src/test/java/org/apache/gravitino/integration/test/web/ui/pages/CatalogsPage.java +++ b/web/integration-test/src/test/java/org/apache/gravitino/integration/test/web/ui/pages/CatalogsPage.java @@ -683,79 +683,67 @@ public boolean verifyShowTableTitle(String title) { */ public boolean verifyShowPropertiesItemInList( String item, String key, String value, Boolean isHighlight) { - try { - Thread.sleep(ACTION_SLEEP_MILLIS); - String xpath; - if (isHighlight) { - xpath = "//div[@data-refer='props-" + item + "-" + key + "-highlight']"; - } else { - xpath = "//div[@data-refer='props-" + item + "-" + key + "']"; - } - WebElement propertyElement = driver.findElement(By.xpath(xpath)); - boolean match = Objects.equals(propertyElement.getText(), value); + WebDriverWait wait = new WebDriverWait(driver, ACTION_SLEEP); + String xpath; + if (isHighlight) { + xpath = "//div[@data-refer='props-" + item + "-" + key + "-highlight']"; + } else { + xpath = "//div[@data-refer='props-" + item + "-" + key + "']"; + } + WebElement propertyElement = + wait.until(ExpectedConditions.visibilityOfElementLocated(By.xpath(xpath))); - if (!match) { - LOG.error("Prop: does not include itemName: {}", value); - return false; - } + boolean match = Objects.equals(propertyElement.getText(), value); - return true; - } catch (Exception e) { - LOG.error(e.getMessage(), e); + if (!match) { + LOG.error("Prop: does not include itemName: {}", value); return false; } + return true; } public boolean verifyShowDataItemInList(String itemName, Boolean isColumnLevel) { - try { - Thread.sleep(ACTION_SLEEP_MILLIS); - String xpath = - "//div[@data-refer='table-grid']//div[contains(@class, 'MuiDataGrid-main')]/div[contains(@class, 'MuiDataGrid-virtualScroller')]/div/div[@role='rowgroup']//div[@data-field='name']"; - if (isColumnLevel) { - xpath = xpath + "//p"; - } - List list = driver.findElements(By.xpath(xpath)); - List texts = new ArrayList<>(); - for (WebElement element : list) { - texts.add(element.getText()); - } - - if (!texts.contains(itemName)) { - LOG.error("table list: {} does not include itemName: {}", texts, itemName); - return false; - } + WebDriverWait wait = new WebDriverWait(driver, ACTION_SLEEP); + String xpath = + "//div[@data-refer='table-grid']//div[contains(@class, 'MuiDataGrid-main')]/div[contains(@class, 'MuiDataGrid-virtualScroller')]/div/div[@role='rowgroup']//div[@data-field='name']"; + if (isColumnLevel) { + xpath = xpath + "//p"; + } + List list = + wait.until(ExpectedConditions.visibilityOfAllElementsLocatedBy(By.xpath(xpath))); + List texts = new ArrayList<>(); + for (WebElement element : list) { + texts.add(element.getText()); + } - return true; - } catch (Exception e) { - LOG.error(e.getMessage(), e); + if (!texts.contains(itemName)) { + LOG.error("table list: {} does not include itemName: {}", texts, itemName); return false; } + + return true; } public boolean verifyNoDataItemInList(String itemName, Boolean isColumnLevel) { - try { - Thread.sleep(ACTION_SLEEP_MILLIS); - String xpath = - "//div[@data-refer='table-grid']//div[contains(@class, 'MuiDataGrid-main')]/div[contains(@class, 'MuiDataGrid-virtualScroller')]/div/div[@role='rowgroup']//div[@data-field='name']"; - if (isColumnLevel) { - xpath = xpath + "//p"; - } - List list = driver.findElements(By.xpath(xpath)); - List texts = new ArrayList<>(); - for (WebElement element : list) { - texts.add(element.getText()); - } - - if (texts.contains(itemName)) { - LOG.error("table list: {} does not include itemName: {}", texts, itemName); - return false; - } + String xpath = + "//div[@data-refer='table-grid']//div[contains(@class, 'MuiDataGrid-main')]/div[contains(@class, 'MuiDataGrid-virtualScroller')]/div/div[@role='rowgroup']//div[@data-field='name']"; + if (isColumnLevel) { + xpath = xpath + "//p"; + } + WebDriverWait wait = new WebDriverWait(driver, ACTION_SLEEP); + List list = + wait.until(ExpectedConditions.visibilityOfAllElementsLocatedBy(By.xpath(xpath))); + List texts = new ArrayList<>(); + for (WebElement element : list) { + texts.add(element.getText()); + } - return true; - } catch (Exception e) { - LOG.error(e.getMessage(), e); + if (texts.contains(itemName)) { + LOG.error("table list: {} does not include itemName: {}", texts, itemName); return false; } + + return true; } public boolean verifyTableColumns() { @@ -840,106 +828,83 @@ public boolean verifyTablePropertiesOverview(List cols) { } public boolean verifyBackHomePage() { - try { - WebDriverWait wait = new WebDriverWait(driver, MAX_TIMEOUT); - wait.until(ExpectedConditions.visibilityOf(metalakePageTitle)); - boolean matchTitle = Objects.equals(metalakePageTitle.getText(), "Metalakes"); - if (!matchTitle) { - LOG.error( - "metalakePageTitle: {} does not match with Metalakes", metalakePageTitle.getText()); - return false; - } - return true; - } catch (Exception e) { - LOG.error(e.getMessage(), e); + WebDriverWait wait = new WebDriverWait(driver, MAX_TIMEOUT); + wait.until(ExpectedConditions.visibilityOf(metalakePageTitle)); + boolean matchTitle = Objects.equals(metalakePageTitle.getText(), "Metalakes"); + if (!matchTitle) { + LOG.error("metalakePageTitle: {} does not match with Metalakes", metalakePageTitle.getText()); return false; } + return true; } public boolean verifyRefreshPage() { - try { - WebDriverWait wait = new WebDriverWait(driver, MAX_TIMEOUT); - wait.until( - webDriver -> - ((JavascriptExecutor) webDriver) - .executeScript("return document.readyState") - .equals("complete")); - wait.until(ExpectedConditions.visibilityOf(metalakeNameLink)); - boolean isDisplayed = metalakeNameLink.isDisplayed(); - if (!isDisplayed) { - LOG.error("No match with link, get {}", metalakeNameLink.getText()); - return false; - } - return true; - } catch (Exception e) { - LOG.error(e.getMessage(), e); + WebDriverWait wait = new WebDriverWait(driver, MAX_TIMEOUT); + wait.until( + webDriver -> + ((JavascriptExecutor) webDriver) + .executeScript("return document.readyState") + .equals("complete")); + wait.until(ExpectedConditions.visibilityOf(metalakeNameLink)); + boolean isDisplayed = metalakeNameLink.isDisplayed(); + if (!isDisplayed) { + LOG.error("No match with link, get {}", metalakeNameLink.getText()); return false; } + return true; } public boolean verifyCreatedCatalogs(List catalogNames) { - try { - List list = - tableGrid.findElements( - By.xpath( - "./div[contains(@class, 'MuiDataGrid-main')]/div[contains(@class, 'MuiDataGrid-virtualScroller')]/div/div[@role='rowgroup']//div[@data-field='name']")); - List texts = new ArrayList<>(); - for (WebElement webElement : list) { - String rowItemColName = webElement.getText(); - texts.add(rowItemColName); - } - if (!texts.containsAll(catalogNames)) { - LOG.error("table list: {} does not containsAll catalogNames: {}", texts, catalogNames); - return false; - } - return true; - } catch (Exception e) { - LOG.error(e.getMessage(), e); + List list = + tableGrid.findElements( + By.xpath( + "./div[contains(@class, 'MuiDataGrid-main')]/div[contains(@class, 'MuiDataGrid-virtualScroller')]/div/div[@role='rowgroup']//div[@data-field='name']")); + List texts = new ArrayList<>(); + for (WebElement webElement : list) { + String rowItemColName = webElement.getText(); + texts.add(rowItemColName); + } + if (!texts.containsAll(catalogNames)) { + LOG.error("table list: {} does not containsAll catalogNames: {}", texts, catalogNames); return false; } + return true; } public boolean verifyTreeNodes(List treeNodes) { - try { - Thread.sleep(ACTION_SLEEP_MILLIS); - List list = - driver.findElements( - By.xpath( - "//div[@data-refer='tree-view']//div[@class='ant-tree-list-holder']/div/div[@class='ant-tree-list-holder-inner']/div[contains(@class, 'ant-tree-treenode')]")); - List texts = new ArrayList<>(); - for (WebElement webElement : list) { - String nodeName = - webElement.findElement(By.xpath(".//span[@class='ant-tree-title']")).getText(); - texts.add(nodeName); - } - if (!treeNodes.containsAll(texts)) { - LOG.error("tree nodes list: {} does not containsAll treeNodes: {}", texts, treeNodes); - return false; - } - return true; - } catch (Exception e) { - LOG.error(e.getMessage(), e); + WebDriverWait wait = new WebDriverWait(driver, ACTION_SLEEP); + List list = + wait.until( + ExpectedConditions.visibilityOfAllElementsLocatedBy( + By.xpath( + "//div[@data-refer='tree-view']//div[@class='ant-tree-list-holder']/div/div[@class='ant-tree-list-holder-inner']/div[contains(@class, 'ant-tree-treenode')]"))); + List texts = new ArrayList<>(); + for (WebElement webElement : list) { + String nodeName = + webElement.findElement(By.xpath(".//span[@class='ant-tree-title']")).getText(); + texts.add(nodeName); + } + if (!treeNodes.containsAll(texts)) { + LOG.error("tree nodes list: {} does not containsAll treeNodes: {}", texts, treeNodes); return false; } + return true; } public boolean verifySelectedNode(String nodeName) { - try { - Thread.sleep(ACTION_SLEEP_MILLIS); - WebElement selectedNode = - driver.findElement( - By.xpath( - "//div[@data-refer='tree-view']//div[contains(@class, 'ant-tree-treenode-selected')]//span[@class='ant-tree-title']")); - waitShowText(nodeName, selectedNode); - if (!selectedNode.getText().equals(nodeName)) { - LOG.error( - "selectedNode: {} does not match with nodeName: {}", selectedNode.getText(), nodeName); - return false; - } - return true; - } catch (Exception e) { - LOG.error(e.getMessage(), e); + + WebDriverWait wait = new WebDriverWait(driver, ACTION_SLEEP); + + WebElement selectedNode = + wait.until( + ExpectedConditions.visibilityOfElementLocated( + By.xpath( + "//div[@data-refer='tree-view']//div[contains(@class, 'ant-tree-treenode-selected')]//span[@class='ant-tree-title']"))); + if (!selectedNode.getText().equals(nodeName)) { + LOG.error( + "selectedNode: {} does not match with nodeName: {}", selectedNode.getText(), nodeName); return false; } + return true; } } diff --git a/web/integration-test/src/test/java/org/apache/gravitino/integration/test/web/ui/pages/MetalakePage.java b/web/integration-test/src/test/java/org/apache/gravitino/integration/test/web/ui/pages/MetalakePage.java index f2810ab0736..468d16f37fb 100644 --- a/web/integration-test/src/test/java/org/apache/gravitino/integration/test/web/ui/pages/MetalakePage.java +++ b/web/integration-test/src/test/java/org/apache/gravitino/integration/test/web/ui/pages/MetalakePage.java @@ -132,14 +132,11 @@ public void setMetalakeCommentField(String commentField) { } public void setQueryParams(String queryParams) { - try { - Thread.sleep(ACTION_SLEEP_MILLIS); - clearQueryInput(); - queryMetalakeInput.sendKeys(queryParams); - Thread.sleep(ACTION_SLEEP_MILLIS); - } catch (Exception e) { - LOG.error(e.getMessage(), e); - } + WebDriverWait wait = new WebDriverWait(driver, ACTION_SLEEP); + WebElement queryInputElement = + wait.until(ExpectedConditions.elementToBeClickable(queryMetalakeInput)); + clearQueryInput(); + queryInputElement.sendKeys(queryParams); } public void clearQueryInput() { @@ -187,9 +184,10 @@ public void clickEditMetalakeBtn(String name) { public void clickMetalakeLink(String name) { try { setQueryParams(name); - Thread.sleep(ACTION_SLEEP_MILLIS); + WebDriverWait wait = new WebDriverWait(driver, ACTION_SLEEP); String xpath = "//a[@data-refer='metalake-link-" + name + "']"; - WebElement metalakeLink = metalakeTableGrid.findElement(By.xpath(xpath)); + WebElement metalakeLink = + wait.until(ExpectedConditions.elementToBeClickable(By.xpath(xpath))); clickAndWait(metalakeLink); } catch (Exception e) { LOG.error(e.getMessage(), e); diff --git a/web/integration-test/src/test/java/org/apache/gravitino/integration/test/web/ui/utils/BaseWebIT.java b/web/integration-test/src/test/java/org/apache/gravitino/integration/test/web/ui/utils/BaseWebIT.java index 8ccc5132621..faaa6ee8955 100644 --- a/web/integration-test/src/test/java/org/apache/gravitino/integration/test/web/ui/utils/BaseWebIT.java +++ b/web/integration-test/src/test/java/org/apache/gravitino/integration/test/web/ui/utils/BaseWebIT.java @@ -48,8 +48,8 @@ public class BaseWebIT extends BaseIT { // https://www.selenium.dev/documentation/webdriver/waits/#implicit-waits protected static final long MAX_IMPLICIT_WAIT = 30; protected static final long MAX_TIMEOUT = 60; - protected static final long EACH_TEST_SLEEP_MILLIS = 1_000; - protected static final long ACTION_SLEEP_MILLIS = 1_000; + protected static final long EACH_TEST_SLEEP = 1; + protected static final long ACTION_SLEEP = 1; protected boolean waitShowText(final String text, final Object locator) { try { @@ -82,12 +82,12 @@ protected void clickAndWait(final Object locator) throws InterruptedException { wait.until(ExpectedConditions.elementToBeClickable(locatorElement(locator))); locatorElement(locator).click(); - Thread.sleep(ACTION_SLEEP_MILLIS); + Thread.sleep(ACTION_SLEEP * 1000); } catch (ElementClickInterceptedException e) { // if the previous click did not effected then try clicking in another way Actions action = new Actions(driver); action.moveToElement(locatorElement(locator)).click().build().perform(); - Thread.sleep(ACTION_SLEEP_MILLIS); + Thread.sleep(ACTION_SLEEP * 1000); } } @@ -106,7 +106,7 @@ WebElement locatorElement(final Object locatorOrElement) { @BeforeEach public void beforeEachTest() { try { - Thread.sleep(EACH_TEST_SLEEP_MILLIS); + Thread.sleep(EACH_TEST_SLEEP * 1000); } catch (Exception e) { LOG.error(e.getMessage(), e); } From 788f3bf2bc9803dfb5534f24cd91a00c57ca3711 Mon Sep 17 00:00:00 2001 From: zzzk1 Date: Tue, 25 Feb 2025 19:23:13 +0800 Subject: [PATCH 2/2] fix format --- .../test/web/ui/pages/CatalogsPage.java | 26 ++++++++++++++----- 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/web/integration-test/src/test/java/org/apache/gravitino/integration/test/web/ui/pages/CatalogsPage.java b/web/integration-test/src/test/java/org/apache/gravitino/integration/test/web/ui/pages/CatalogsPage.java index 296059fad3b..add68777e8d 100644 --- a/web/integration-test/src/test/java/org/apache/gravitino/integration/test/web/ui/pages/CatalogsPage.java +++ b/web/integration-test/src/test/java/org/apache/gravitino/integration/test/web/ui/pages/CatalogsPage.java @@ -593,7 +593,8 @@ public boolean verifyShowCatalogDetails(String name, String hiveMetastoreUris) waitShowText( "false", By.xpath( - ".//*[@data-prev-refer='details-props-key-gravitino.bypass.hive.metastore.client.capability.check']")); + ".//*[@data-prev-refer='details-props-key-gravitino." + + "bypass.hive.metastore.client.capability.check']")); boolean verifyAll = isVisible && isText && isHiveURIS && isShowCheck; if (!verifyAll) { @@ -705,7 +706,10 @@ public boolean verifyShowPropertiesItemInList( public boolean verifyShowDataItemInList(String itemName, Boolean isColumnLevel) { WebDriverWait wait = new WebDriverWait(driver, ACTION_SLEEP); String xpath = - "//div[@data-refer='table-grid']//div[contains(@class, 'MuiDataGrid-main')]/div[contains(@class, 'MuiDataGrid-virtualScroller')]/div/div[@role='rowgroup']//div[@data-field='name']"; + "//div[@data-refer='table-grid']" + + "//div[contains(@class, 'MuiDataGrid-main')]" + + "/div[contains(@class, 'MuiDataGrid-virtualScroller')]" + + "/div/div[@role='rowgroup']//div[@data-field='name']"; if (isColumnLevel) { xpath = xpath + "//p"; } @@ -726,7 +730,10 @@ public boolean verifyShowDataItemInList(String itemName, Boolean isColumnLevel) public boolean verifyNoDataItemInList(String itemName, Boolean isColumnLevel) { String xpath = - "//div[@data-refer='table-grid']//div[contains(@class, 'MuiDataGrid-main')]/div[contains(@class, 'MuiDataGrid-virtualScroller')]/div/div[@role='rowgroup']//div[@data-field='name']"; + "//div[@data-refer='table-grid']" + + "//div[contains(@class, 'MuiDataGrid-main')]" + + "/div[contains(@class, 'MuiDataGrid-virtualScroller')]" + + "/div/div[@role='rowgroup']//div[@data-field='name']"; if (isColumnLevel) { xpath = xpath + "//p"; } @@ -858,7 +865,9 @@ public boolean verifyCreatedCatalogs(List catalogNames) { List list = tableGrid.findElements( By.xpath( - "./div[contains(@class, 'MuiDataGrid-main')]/div[contains(@class, 'MuiDataGrid-virtualScroller')]/div/div[@role='rowgroup']//div[@data-field='name']")); + "./div[contains(@class, 'MuiDataGrid-main')]" + + "/div[contains(@class, 'MuiDataGrid-virtualScroller')]" + + "/div/div[@role='rowgroup']//div[@data-field='name']")); List texts = new ArrayList<>(); for (WebElement webElement : list) { String rowItemColName = webElement.getText(); @@ -877,7 +886,10 @@ public boolean verifyTreeNodes(List treeNodes) { wait.until( ExpectedConditions.visibilityOfAllElementsLocatedBy( By.xpath( - "//div[@data-refer='tree-view']//div[@class='ant-tree-list-holder']/div/div[@class='ant-tree-list-holder-inner']/div[contains(@class, 'ant-tree-treenode')]"))); + "//div[@data-refer='tree-view']" + + "//div[@class='ant-tree-list-holder']" + + "/div/div[@class='ant-tree-list-holder-inner']" + + "/div[contains(@class, 'ant-tree-treenode')]"))); List texts = new ArrayList<>(); for (WebElement webElement : list) { String nodeName = @@ -899,7 +911,9 @@ public boolean verifySelectedNode(String nodeName) { wait.until( ExpectedConditions.visibilityOfElementLocated( By.xpath( - "//div[@data-refer='tree-view']//div[contains(@class, 'ant-tree-treenode-selected')]//span[@class='ant-tree-title']"))); + "//div[@data-refer='tree-view']" + + "//div[contains(@class, 'ant-tree-treenode-selected')]" + + "//span[@class='ant-tree-title']"))); if (!selectedNode.getText().equals(nodeName)) { LOG.error( "selectedNode: {} does not match with nodeName: {}", selectedNode.getText(), nodeName);