Skip to content

Commit f7719f8

Browse files
authored
[#6459]improve(test): Use explicit wait for time-based condition (#6460)
### What changes were proposed in this pull request? This improvement follows our [E2E testing guide](https://gravitino.apache.org/docs/0.8.0-incubating/webui#e2e-test) by utilizing the wait methods and removing `Thread.sleep(sleepTimeMillis)`. ### Why are the changes needed? Fix: #6459 ### Does this PR introduce _any_ user-facing change? no ### How was this patch tested? CI
1 parent af9c2b4 commit f7719f8

File tree

4 files changed

+132
-155
lines changed

4 files changed

+132
-155
lines changed

web/integration-test/src/test/java/org/apache/gravitino/integration/test/web/ui/MetalakePageTest.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ public void testCreateMultipleMetalakes() throws InterruptedException {
104104

105105
for (int i = 0; i < twoPagesCount; i++) {
106106
try {
107-
Thread.sleep(ACTION_SLEEP_MILLIS);
107+
Thread.sleep(ACTION_SLEEP * 1000);
108108
} catch (Exception e) {
109109
LOG.error(e.getMessage(), e);
110110
}

web/integration-test/src/test/java/org/apache/gravitino/integration/test/web/ui/pages/CatalogsPage.java

+118-139
Original file line numberDiff line numberDiff line change
@@ -593,7 +593,8 @@ public boolean verifyShowCatalogDetails(String name, String hiveMetastoreUris)
593593
waitShowText(
594594
"false",
595595
By.xpath(
596-
".//*[@data-prev-refer='details-props-key-gravitino.bypass.hive.metastore.client.capability.check']"));
596+
".//*[@data-prev-refer='details-props-key-gravitino."
597+
+ "bypass.hive.metastore.client.capability.check']"));
597598

598599
boolean verifyAll = isVisible && isText && isHiveURIS && isShowCheck;
599600
if (!verifyAll) {
@@ -683,79 +684,73 @@ public boolean verifyShowTableTitle(String title) {
683684
*/
684685
public boolean verifyShowPropertiesItemInList(
685686
String item, String key, String value, Boolean isHighlight) {
686-
try {
687-
Thread.sleep(ACTION_SLEEP_MILLIS);
688-
String xpath;
689-
if (isHighlight) {
690-
xpath = "//div[@data-refer='props-" + item + "-" + key + "-highlight']";
691-
} else {
692-
xpath = "//div[@data-refer='props-" + item + "-" + key + "']";
693-
}
694-
WebElement propertyElement = driver.findElement(By.xpath(xpath));
695-
boolean match = Objects.equals(propertyElement.getText(), value);
687+
WebDriverWait wait = new WebDriverWait(driver, ACTION_SLEEP);
688+
String xpath;
689+
if (isHighlight) {
690+
xpath = "//div[@data-refer='props-" + item + "-" + key + "-highlight']";
691+
} else {
692+
xpath = "//div[@data-refer='props-" + item + "-" + key + "']";
693+
}
694+
WebElement propertyElement =
695+
wait.until(ExpectedConditions.visibilityOfElementLocated(By.xpath(xpath)));
696696

697-
if (!match) {
698-
LOG.error("Prop: does not include itemName: {}", value);
699-
return false;
700-
}
697+
boolean match = Objects.equals(propertyElement.getText(), value);
701698

702-
return true;
703-
} catch (Exception e) {
704-
LOG.error(e.getMessage(), e);
699+
if (!match) {
700+
LOG.error("Prop: does not include itemName: {}", value);
705701
return false;
706702
}
703+
return true;
707704
}
708705

709706
public boolean verifyShowDataItemInList(String itemName, Boolean isColumnLevel) {
710-
try {
711-
Thread.sleep(ACTION_SLEEP_MILLIS);
712-
String xpath =
713-
"//div[@data-refer='table-grid']//div[contains(@class, 'MuiDataGrid-main')]/div[contains(@class, 'MuiDataGrid-virtualScroller')]/div/div[@role='rowgroup']//div[@data-field='name']";
714-
if (isColumnLevel) {
715-
xpath = xpath + "//p";
716-
}
717-
List<WebElement> list = driver.findElements(By.xpath(xpath));
718-
List<String> texts = new ArrayList<>();
719-
for (WebElement element : list) {
720-
texts.add(element.getText());
721-
}
722-
723-
if (!texts.contains(itemName)) {
724-
LOG.error("table list: {} does not include itemName: {}", texts, itemName);
725-
return false;
726-
}
727-
728-
return true;
729-
} catch (Exception e) {
730-
LOG.error(e.getMessage(), e);
707+
WebDriverWait wait = new WebDriverWait(driver, ACTION_SLEEP);
708+
String xpath =
709+
"//div[@data-refer='table-grid']"
710+
+ "//div[contains(@class, 'MuiDataGrid-main')]"
711+
+ "/div[contains(@class, 'MuiDataGrid-virtualScroller')]"
712+
+ "/div/div[@role='rowgroup']//div[@data-field='name']";
713+
if (isColumnLevel) {
714+
xpath = xpath + "//p";
715+
}
716+
List<WebElement> list =
717+
wait.until(ExpectedConditions.visibilityOfAllElementsLocatedBy(By.xpath(xpath)));
718+
List<String> texts = new ArrayList<>();
719+
for (WebElement element : list) {
720+
texts.add(element.getText());
721+
}
722+
723+
if (!texts.contains(itemName)) {
724+
LOG.error("table list: {} does not include itemName: {}", texts, itemName);
731725
return false;
732726
}
727+
728+
return true;
733729
}
734730

735731
public boolean verifyNoDataItemInList(String itemName, Boolean isColumnLevel) {
736-
try {
737-
Thread.sleep(ACTION_SLEEP_MILLIS);
738-
String xpath =
739-
"//div[@data-refer='table-grid']//div[contains(@class, 'MuiDataGrid-main')]/div[contains(@class, 'MuiDataGrid-virtualScroller')]/div/div[@role='rowgroup']//div[@data-field='name']";
740-
if (isColumnLevel) {
741-
xpath = xpath + "//p";
742-
}
743-
List<WebElement> list = driver.findElements(By.xpath(xpath));
744-
List<String> texts = new ArrayList<>();
745-
for (WebElement element : list) {
746-
texts.add(element.getText());
747-
}
748-
749-
if (texts.contains(itemName)) {
750-
LOG.error("table list: {} does not include itemName: {}", texts, itemName);
751-
return false;
752-
}
753-
754-
return true;
755-
} catch (Exception e) {
756-
LOG.error(e.getMessage(), e);
732+
String xpath =
733+
"//div[@data-refer='table-grid']"
734+
+ "//div[contains(@class, 'MuiDataGrid-main')]"
735+
+ "/div[contains(@class, 'MuiDataGrid-virtualScroller')]"
736+
+ "/div/div[@role='rowgroup']//div[@data-field='name']";
737+
if (isColumnLevel) {
738+
xpath = xpath + "//p";
739+
}
740+
WebDriverWait wait = new WebDriverWait(driver, ACTION_SLEEP);
741+
List<WebElement> list =
742+
wait.until(ExpectedConditions.visibilityOfAllElementsLocatedBy(By.xpath(xpath)));
743+
List<String> texts = new ArrayList<>();
744+
for (WebElement element : list) {
745+
texts.add(element.getText());
746+
}
747+
748+
if (texts.contains(itemName)) {
749+
LOG.error("table list: {} does not include itemName: {}", texts, itemName);
757750
return false;
758751
}
752+
753+
return true;
759754
}
760755

761756
public boolean verifyTableColumns() {
@@ -840,106 +835,90 @@ public boolean verifyTablePropertiesOverview(List<String> cols) {
840835
}
841836

842837
public boolean verifyBackHomePage() {
843-
try {
844-
WebDriverWait wait = new WebDriverWait(driver, MAX_TIMEOUT);
845-
wait.until(ExpectedConditions.visibilityOf(metalakePageTitle));
846-
boolean matchTitle = Objects.equals(metalakePageTitle.getText(), "Metalakes");
847-
if (!matchTitle) {
848-
LOG.error(
849-
"metalakePageTitle: {} does not match with Metalakes", metalakePageTitle.getText());
850-
return false;
851-
}
852-
return true;
853-
} catch (Exception e) {
854-
LOG.error(e.getMessage(), e);
838+
WebDriverWait wait = new WebDriverWait(driver, MAX_TIMEOUT);
839+
wait.until(ExpectedConditions.visibilityOf(metalakePageTitle));
840+
boolean matchTitle = Objects.equals(metalakePageTitle.getText(), "Metalakes");
841+
if (!matchTitle) {
842+
LOG.error("metalakePageTitle: {} does not match with Metalakes", metalakePageTitle.getText());
855843
return false;
856844
}
845+
return true;
857846
}
858847

859848
public boolean verifyRefreshPage() {
860-
try {
861-
WebDriverWait wait = new WebDriverWait(driver, MAX_TIMEOUT);
862-
wait.until(
863-
webDriver ->
864-
((JavascriptExecutor) webDriver)
865-
.executeScript("return document.readyState")
866-
.equals("complete"));
867-
wait.until(ExpectedConditions.visibilityOf(metalakeNameLink));
868-
boolean isDisplayed = metalakeNameLink.isDisplayed();
869-
if (!isDisplayed) {
870-
LOG.error("No match with link, get {}", metalakeNameLink.getText());
871-
return false;
872-
}
873-
return true;
874-
} catch (Exception e) {
875-
LOG.error(e.getMessage(), e);
849+
WebDriverWait wait = new WebDriverWait(driver, MAX_TIMEOUT);
850+
wait.until(
851+
webDriver ->
852+
((JavascriptExecutor) webDriver)
853+
.executeScript("return document.readyState")
854+
.equals("complete"));
855+
wait.until(ExpectedConditions.visibilityOf(metalakeNameLink));
856+
boolean isDisplayed = metalakeNameLink.isDisplayed();
857+
if (!isDisplayed) {
858+
LOG.error("No match with link, get {}", metalakeNameLink.getText());
876859
return false;
877860
}
861+
return true;
878862
}
879863

880864
public boolean verifyCreatedCatalogs(List<String> catalogNames) {
881-
try {
882-
List<WebElement> list =
883-
tableGrid.findElements(
884-
By.xpath(
885-
"./div[contains(@class, 'MuiDataGrid-main')]/div[contains(@class, 'MuiDataGrid-virtualScroller')]/div/div[@role='rowgroup']//div[@data-field='name']"));
886-
List<String> texts = new ArrayList<>();
887-
for (WebElement webElement : list) {
888-
String rowItemColName = webElement.getText();
889-
texts.add(rowItemColName);
890-
}
891-
if (!texts.containsAll(catalogNames)) {
892-
LOG.error("table list: {} does not containsAll catalogNames: {}", texts, catalogNames);
893-
return false;
894-
}
895-
return true;
896-
} catch (Exception e) {
897-
LOG.error(e.getMessage(), e);
865+
List<WebElement> list =
866+
tableGrid.findElements(
867+
By.xpath(
868+
"./div[contains(@class, 'MuiDataGrid-main')]"
869+
+ "/div[contains(@class, 'MuiDataGrid-virtualScroller')]"
870+
+ "/div/div[@role='rowgroup']//div[@data-field='name']"));
871+
List<String> texts = new ArrayList<>();
872+
for (WebElement webElement : list) {
873+
String rowItemColName = webElement.getText();
874+
texts.add(rowItemColName);
875+
}
876+
if (!texts.containsAll(catalogNames)) {
877+
LOG.error("table list: {} does not containsAll catalogNames: {}", texts, catalogNames);
898878
return false;
899879
}
880+
return true;
900881
}
901882

902883
public boolean verifyTreeNodes(List<String> treeNodes) {
903-
try {
904-
Thread.sleep(ACTION_SLEEP_MILLIS);
905-
List<WebElement> list =
906-
driver.findElements(
907-
By.xpath(
908-
"//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')]"));
909-
List<String> texts = new ArrayList<>();
910-
for (WebElement webElement : list) {
911-
String nodeName =
912-
webElement.findElement(By.xpath(".//span[@class='ant-tree-title']")).getText();
913-
texts.add(nodeName);
914-
}
915-
if (!treeNodes.containsAll(texts)) {
916-
LOG.error("tree nodes list: {} does not containsAll treeNodes: {}", texts, treeNodes);
917-
return false;
918-
}
919-
return true;
920-
} catch (Exception e) {
921-
LOG.error(e.getMessage(), e);
884+
WebDriverWait wait = new WebDriverWait(driver, ACTION_SLEEP);
885+
List<WebElement> list =
886+
wait.until(
887+
ExpectedConditions.visibilityOfAllElementsLocatedBy(
888+
By.xpath(
889+
"//div[@data-refer='tree-view']"
890+
+ "//div[@class='ant-tree-list-holder']"
891+
+ "/div/div[@class='ant-tree-list-holder-inner']"
892+
+ "/div[contains(@class, 'ant-tree-treenode')]")));
893+
List<String> texts = new ArrayList<>();
894+
for (WebElement webElement : list) {
895+
String nodeName =
896+
webElement.findElement(By.xpath(".//span[@class='ant-tree-title']")).getText();
897+
texts.add(nodeName);
898+
}
899+
if (!treeNodes.containsAll(texts)) {
900+
LOG.error("tree nodes list: {} does not containsAll treeNodes: {}", texts, treeNodes);
922901
return false;
923902
}
903+
return true;
924904
}
925905

926906
public boolean verifySelectedNode(String nodeName) {
927-
try {
928-
Thread.sleep(ACTION_SLEEP_MILLIS);
929-
WebElement selectedNode =
930-
driver.findElement(
931-
By.xpath(
932-
"//div[@data-refer='tree-view']//div[contains(@class, 'ant-tree-treenode-selected')]//span[@class='ant-tree-title']"));
933-
waitShowText(nodeName, selectedNode);
934-
if (!selectedNode.getText().equals(nodeName)) {
935-
LOG.error(
936-
"selectedNode: {} does not match with nodeName: {}", selectedNode.getText(), nodeName);
937-
return false;
938-
}
939-
return true;
940-
} catch (Exception e) {
941-
LOG.error(e.getMessage(), e);
907+
908+
WebDriverWait wait = new WebDriverWait(driver, ACTION_SLEEP);
909+
910+
WebElement selectedNode =
911+
wait.until(
912+
ExpectedConditions.visibilityOfElementLocated(
913+
By.xpath(
914+
"//div[@data-refer='tree-view']"
915+
+ "//div[contains(@class, 'ant-tree-treenode-selected')]"
916+
+ "//span[@class='ant-tree-title']")));
917+
if (!selectedNode.getText().equals(nodeName)) {
918+
LOG.error(
919+
"selectedNode: {} does not match with nodeName: {}", selectedNode.getText(), nodeName);
942920
return false;
943921
}
922+
return true;
944923
}
945924
}

web/integration-test/src/test/java/org/apache/gravitino/integration/test/web/ui/pages/MetalakePage.java

+8-10
Original file line numberDiff line numberDiff line change
@@ -132,14 +132,11 @@ public void setMetalakeCommentField(String commentField) {
132132
}
133133

134134
public void setQueryParams(String queryParams) {
135-
try {
136-
Thread.sleep(ACTION_SLEEP_MILLIS);
137-
clearQueryInput();
138-
queryMetalakeInput.sendKeys(queryParams);
139-
Thread.sleep(ACTION_SLEEP_MILLIS);
140-
} catch (Exception e) {
141-
LOG.error(e.getMessage(), e);
142-
}
135+
WebDriverWait wait = new WebDriverWait(driver, ACTION_SLEEP);
136+
WebElement queryInputElement =
137+
wait.until(ExpectedConditions.elementToBeClickable(queryMetalakeInput));
138+
clearQueryInput();
139+
queryInputElement.sendKeys(queryParams);
143140
}
144141

145142
public void clearQueryInput() {
@@ -187,9 +184,10 @@ public void clickEditMetalakeBtn(String name) {
187184
public void clickMetalakeLink(String name) {
188185
try {
189186
setQueryParams(name);
190-
Thread.sleep(ACTION_SLEEP_MILLIS);
187+
WebDriverWait wait = new WebDriverWait(driver, ACTION_SLEEP);
191188
String xpath = "//a[@data-refer='metalake-link-" + name + "']";
192-
WebElement metalakeLink = metalakeTableGrid.findElement(By.xpath(xpath));
189+
WebElement metalakeLink =
190+
wait.until(ExpectedConditions.elementToBeClickable(By.xpath(xpath)));
193191
clickAndWait(metalakeLink);
194192
} catch (Exception e) {
195193
LOG.error(e.getMessage(), e);

web/integration-test/src/test/java/org/apache/gravitino/integration/test/web/ui/utils/BaseWebIT.java

+5-5
Original file line numberDiff line numberDiff line change
@@ -48,8 +48,8 @@ public class BaseWebIT extends BaseIT {
4848
// https://www.selenium.dev/documentation/webdriver/waits/#implicit-waits
4949
protected static final long MAX_IMPLICIT_WAIT = 30;
5050
protected static final long MAX_TIMEOUT = 60;
51-
protected static final long EACH_TEST_SLEEP_MILLIS = 1_000;
52-
protected static final long ACTION_SLEEP_MILLIS = 1_000;
51+
protected static final long EACH_TEST_SLEEP = 1;
52+
protected static final long ACTION_SLEEP = 1;
5353

5454
protected boolean waitShowText(final String text, final Object locator) {
5555
try {
@@ -82,12 +82,12 @@ protected void clickAndWait(final Object locator) throws InterruptedException {
8282
wait.until(ExpectedConditions.elementToBeClickable(locatorElement(locator)));
8383

8484
locatorElement(locator).click();
85-
Thread.sleep(ACTION_SLEEP_MILLIS);
85+
Thread.sleep(ACTION_SLEEP * 1000);
8686
} catch (ElementClickInterceptedException e) {
8787
// if the previous click did not effected then try clicking in another way
8888
Actions action = new Actions(driver);
8989
action.moveToElement(locatorElement(locator)).click().build().perform();
90-
Thread.sleep(ACTION_SLEEP_MILLIS);
90+
Thread.sleep(ACTION_SLEEP * 1000);
9191
}
9292
}
9393

@@ -106,7 +106,7 @@ WebElement locatorElement(final Object locatorOrElement) {
106106
@BeforeEach
107107
public void beforeEachTest() {
108108
try {
109-
Thread.sleep(EACH_TEST_SLEEP_MILLIS);
109+
Thread.sleep(EACH_TEST_SLEEP * 1000);
110110
} catch (Exception e) {
111111
LOG.error(e.getMessage(), e);
112112
}

0 commit comments

Comments
 (0)