Katalon suite taking 30 seconds between steps and I can't figure out why

Well, hard to choose the right solution right now, but I think users not aware about smart wait specific, are just using it as it is.
So, keeping the global setting enabled by default but enabling the users willing to disable it locally on specific needs no matter of the global setting will be the path with minimum breakage.
the main issue seems to be caused by this duplicated logic (global vs local) and how it is handled.
I will think a bit more on this, should be a decent solution …

LE: there mai be two main cases, i guess:

  • globaly enabled but the user needs to temporary disable
  • globaly disabled but the user needs to temporary enable

I think an if / else is needed to handle them properly.

this code looks a bit fishy

boolean localSmartWaitEnabled = (boolean) Optional
                .ofNullable(RunConfiguration.getExecutionProperties().get(RunConfiguration.LOCAL_SMART_WAIT_MODE))
                .orElse(true);

If i understand the doc about Optional right, it means if the LOCAL_SMART is unset (null) this code returns true. which is odd.
removing the orElse method, the if can be modified a bit.
check first the localSmart with isPresent so if this is not null (has value) should preffer the local value, otherwise the global one

+1

If we are going to modify the system, I want to change this to .Else(false);.

A bit more changes may be needed for things to work properly.
Keeping the cast as boolean (but removing orElse) will return false. Easy to do but …
This is not what I wanted to see, since I may like to check if this is actually set or unset (user choice).
Attempting to use isPresent() on a boolean will throw an exception, obvioulsy.

So, I made a sample code like this to see how we can play better.
The main trick is at:

	Optional<Boolean> localSmartWaitEnabled = Optional
		.ofNullable(RunConfiguration.getExecutionProperties().get(RunConfiguration.LOCAL_SMART_WAIT_MODE));

Full code:

import com.kms.katalon.core.configuration.RunConfiguration
import com.kms.katalon.core.webui.keyword.WebUiBuiltInKeywords as WebUI

def simulateSmartWait() {
	Optional<Boolean> localSmartWaitEnabled = Optional
		.ofNullable(RunConfiguration.getExecutionProperties().get(RunConfiguration.LOCAL_SMART_WAIT_MODE));
		
	boolean globalSmartWaitEnabled = (boolean) Optional
		.ofNullable(RunConfiguration.getExecutionProperties().get(RunConfiguration.GLOBAL_SMART_WAIT_MODE))
		.orElse(false);
	
	println "Global setting: " + globalSmartWaitEnabled;
	println "Local is present: " + localSmartWaitEnabled.isPresent();
	println "Local settings: " + localSmartWaitEnabled;

}

println "With default settings"
simulateSmartWait()

println "Disable locally"
WebUI.disableSmartWait()
simulateSmartWait()

println "Enable locally"
WebUI.enableSmartWait()
simulateSmartWait()

running it (with Smart wait disabled from UI) I got:

2023-11-19 11:48:49.800 INFO  c.k.katalon.core.main.TestCaseExecutor   - --------------------
2023-11-19 11:48:49.801 INFO  c.k.katalon.core.main.TestCaseExecutor   - START Test Cases/Check SmartWait
2023-11-19 11:48:50.091 DEBUG testcase.Check SmartWait                 - 1: println("With default settings")
With default settings
2023-11-19 11:48:50.097 DEBUG testcase.Check SmartWait                 - 2: simulateSmartWait()
2023-11-19 11:48:50.100 DEBUG testcase.Check SmartWait                 - 1: localSmartWaitEnabled = Optional.ofNullable(getExecutionProperties().get(LOCAL_SMART_WAIT_MODE))
2023-11-19 11:48:50.126 DEBUG testcase.Check SmartWait                 - 2: globalSmartWaitEnabled = get(GLOBAL_SMART_WAIT_MODE)).orElse(false)
2023-11-19 11:48:50.132 DEBUG testcase.Check SmartWait                 - 3: println("Global setting: " + globalSmartWaitEnabled)
Global setting: false
2023-11-19 11:48:50.138 DEBUG testcase.Check SmartWait                 - 4: println("Local is present: " + localSmartWaitEnabled.isPresent())
Local is present: false
2023-11-19 11:48:50.142 DEBUG testcase.Check SmartWait                 - 5: println("Local settings: " + localSmartWaitEnabled)
Local settings: Optional.empty
2023-11-19 11:48:50.146 DEBUG testcase.Check SmartWait                 - 3: println("Disable locally")
Disable locally
2023-11-19 11:48:50.150 DEBUG testcase.Check SmartWait                 - 4: disableSmartWait()
2023-11-19 11:48:50.274 DEBUG testcase.Check SmartWait                 - 5: simulateSmartWait()
2023-11-19 11:48:50.275 DEBUG testcase.Check SmartWait                 - 1: localSmartWaitEnabled = Optional.ofNullable(getExecutionProperties().get(LOCAL_SMART_WAIT_MODE))
2023-11-19 11:48:50.277 DEBUG testcase.Check SmartWait                 - 2: globalSmartWaitEnabled = get(GLOBAL_SMART_WAIT_MODE)).orElse(false)
2023-11-19 11:48:50.279 DEBUG testcase.Check SmartWait                 - 3: println("Global setting: " + globalSmartWaitEnabled)
Global setting: false
2023-11-19 11:48:50.280 DEBUG testcase.Check SmartWait                 - 4: println("Local is present: " + localSmartWaitEnabled.isPresent())
Local is present: true
2023-11-19 11:48:50.281 DEBUG testcase.Check SmartWait                 - 5: println("Local settings: " + localSmartWaitEnabled)
Local settings: Optional[false]
2023-11-19 11:48:50.283 DEBUG testcase.Check SmartWait                 - 6: println("Enable locally")
Enable locally
2023-11-19 11:48:50.285 DEBUG testcase.Check SmartWait                 - 7: enableSmartWait()
2023-11-19 11:48:50.298 DEBUG testcase.Check SmartWait                 - 8: simulateSmartWait()
2023-11-19 11:48:50.300 DEBUG testcase.Check SmartWait                 - 1: localSmartWaitEnabled = Optional.ofNullable(getExecutionProperties().get(LOCAL_SMART_WAIT_MODE))
2023-11-19 11:48:50.301 DEBUG testcase.Check SmartWait                 - 2: globalSmartWaitEnabled = get(GLOBAL_SMART_WAIT_MODE)).orElse(false)
2023-11-19 11:48:50.302 DEBUG testcase.Check SmartWait                 - 3: println("Global setting: " + globalSmartWaitEnabled)
Global setting: false
2023-11-19 11:48:50.304 DEBUG testcase.Check SmartWait                 - 4: println("Local is present: " + localSmartWaitEnabled.isPresent())
Local is present: true
2023-11-19 11:48:50.305 DEBUG testcase.Check SmartWait                 - 5: println("Local settings: " + localSmartWaitEnabled)
Local settings: Optional[true]
2023-11-19 11:48:50.315 INFO  c.k.katalon.core.main.TestCaseExecutor   - END Test Cases/Check SmartWait

So, now, I can actually use isPresent() for further logic.

Did some changes to my simulated function to mimic the proposed behaviour.
Now is like this:

def simulateSmartWait() {
	Optional<Boolean> localSmartWaitEnabled = Optional
		.ofNullable(RunConfiguration.getExecutionProperties().get(RunConfiguration.LOCAL_SMART_WAIT_MODE));
		
	boolean globalSmartWaitEnabled = (boolean) Optional
		.ofNullable(RunConfiguration.getExecutionProperties().get(RunConfiguration.GLOBAL_SMART_WAIT_MODE))
		.orElse(false);
	
//	println "Global setting: " + globalSmartWaitEnabled;
//	println "Local is present: " + localSmartWaitEnabled.isPresent();
//	println "Local settings: " + localSmartWaitEnabled;
	
	if (localSmartWaitEnabled.isPresent()) {
		if (localSmartWaitEnabled.get()) {
			println "Locally enabled. do SmartWait"
		} else {
			println "Locally disabled. no SmartWait"
		}
	} else {
		if (globalSmartWaitEnabled) {
			println "Locally unset, enabled globally. do SmartWait"
		} else {
			println "Locally unset, disabled globally. no SmartWait"
		}
	}
}

Running with global enabled, I got:

2023-11-19 12:33:07.653 INFO  c.k.katalon.core.main.TestCaseExecutor   - --------------------
2023-11-19 12:33:07.654 INFO  c.k.katalon.core.main.TestCaseExecutor   - START Test Cases/Check SmartWait improved
2023-11-19 12:33:07.937 DEBUG testcase.Check SmartWait improved        - 1: println("With default settings")
With default settings
2023-11-19 12:33:07.942 DEBUG testcase.Check SmartWait improved        - 2: simulateSmartWait()
2023-11-19 12:33:07.945 DEBUG testcase.Check SmartWait improved        - 1: localSmartWaitEnabled = Optional.ofNullable(getExecutionProperties().get(LOCAL_SMART_WAIT_MODE))
2023-11-19 12:33:07.957 DEBUG testcase.Check SmartWait improved        - 2: globalSmartWaitEnabled = get(GLOBAL_SMART_WAIT_MODE)).orElse(false)
2023-11-19 12:33:07.963 DEBUG testcase.Check SmartWait improved        - 3: if (localSmartWaitEnabled.isPresent())
2023-11-19 12:33:07.972 DEBUG testcase.Check SmartWait improved        - 4: else
2023-11-19 12:33:07.974 DEBUG testcase.Check SmartWait improved        - 1: if (globalSmartWaitEnabled)
2023-11-19 12:33:07.977 DEBUG testcase.Check SmartWait improved        - 1: println("Locally unset, enabled globally. do SmartWait")
Locally unset, enabled globally. do SmartWait
2023-11-19 12:33:07.979 DEBUG testcase.Check SmartWait improved        - 3: println("Disable locally")
Disable locally
2023-11-19 12:33:07.983 DEBUG testcase.Check SmartWait improved        - 4: disableSmartWait()
2023-11-19 12:33:08.103 DEBUG testcase.Check SmartWait improved        - 5: simulateSmartWait()
2023-11-19 12:33:08.105 DEBUG testcase.Check SmartWait improved        - 1: localSmartWaitEnabled = Optional.ofNullable(getExecutionProperties().get(LOCAL_SMART_WAIT_MODE))
2023-11-19 12:33:08.107 DEBUG testcase.Check SmartWait improved        - 2: globalSmartWaitEnabled = get(GLOBAL_SMART_WAIT_MODE)).orElse(false)
2023-11-19 12:33:08.108 DEBUG testcase.Check SmartWait improved        - 3: if (localSmartWaitEnabled.isPresent())
2023-11-19 12:33:08.109 DEBUG testcase.Check SmartWait improved        - 1: if (localSmartWaitEnabled.get())
2023-11-19 12:33:08.111 DEBUG testcase.Check SmartWait improved        - 2: else
2023-11-19 12:33:08.112 DEBUG testcase.Check SmartWait improved        - 1: println("Locally disabled. no SmartWait")
Locally disabled. no SmartWait
2023-11-19 12:33:08.114 DEBUG testcase.Check SmartWait improved        - 6: println("Enable locally")
Enable locally
2023-11-19 12:33:08.117 DEBUG testcase.Check SmartWait improved        - 7: enableSmartWait()
2023-11-19 12:33:08.134 DEBUG testcase.Check SmartWait improved        - 8: simulateSmartWait()
2023-11-19 12:33:08.137 DEBUG testcase.Check SmartWait improved        - 1: localSmartWaitEnabled = Optional.ofNullable(getExecutionProperties().get(LOCAL_SMART_WAIT_MODE))
2023-11-19 12:33:08.138 DEBUG testcase.Check SmartWait improved        - 2: globalSmartWaitEnabled = get(GLOBAL_SMART_WAIT_MODE)).orElse(false)
2023-11-19 12:33:08.138 DEBUG testcase.Check SmartWait improved        - 3: if (localSmartWaitEnabled.isPresent())
2023-11-19 12:33:08.139 DEBUG testcase.Check SmartWait improved        - 1: if (localSmartWaitEnabled.get())
2023-11-19 12:33:08.141 DEBUG testcase.Check SmartWait improved        - 1: println("Locally enabled. do SmartWait")
Locally enabled. do SmartWait
2023-11-19 12:33:08.150 INFO  c.k.katalon.core.main.TestCaseExecutor   - END Test Cases/Check SmartWait improved

Running with globally disabled:

2023-11-19 12:31:41.157 INFO  c.k.katalon.core.main.TestCaseExecutor   - --------------------
2023-11-19 12:31:41.159 INFO  c.k.katalon.core.main.TestCaseExecutor   - START Test Cases/Check SmartWait improved
2023-11-19 12:31:41.445 DEBUG testcase.Check SmartWait improved        - 1: println("With default settings")
With default settings
2023-11-19 12:31:41.450 DEBUG testcase.Check SmartWait improved        - 2: simulateSmartWait()
2023-11-19 12:31:41.452 DEBUG testcase.Check SmartWait improved        - 1: localSmartWaitEnabled = Optional.ofNullable(getExecutionProperties().get(LOCAL_SMART_WAIT_MODE))
2023-11-19 12:31:41.465 DEBUG testcase.Check SmartWait improved        - 2: globalSmartWaitEnabled = get(GLOBAL_SMART_WAIT_MODE)).orElse(false)
2023-11-19 12:31:41.471 DEBUG testcase.Check SmartWait improved        - 3: if (localSmartWaitEnabled.isPresent())
2023-11-19 12:31:41.480 DEBUG testcase.Check SmartWait improved        - 4: else
2023-11-19 12:31:41.482 DEBUG testcase.Check SmartWait improved        - 1: if (globalSmartWaitEnabled)
2023-11-19 12:31:41.484 DEBUG testcase.Check SmartWait improved        - 2: else
2023-11-19 12:31:41.487 DEBUG testcase.Check SmartWait improved        - 1: println("Locally unset, disabled globally. no SmartWait")
Locally unset, disabled globally. no SmartWait
2023-11-19 12:31:41.489 DEBUG testcase.Check SmartWait improved        - 3: println("Disable locally")
Disable locally
2023-11-19 12:31:41.492 DEBUG testcase.Check SmartWait improved        - 4: disableSmartWait()
2023-11-19 12:31:41.616 DEBUG testcase.Check SmartWait improved        - 5: simulateSmartWait()
2023-11-19 12:31:41.617 DEBUG testcase.Check SmartWait improved        - 1: localSmartWaitEnabled = Optional.ofNullable(getExecutionProperties().get(LOCAL_SMART_WAIT_MODE))
2023-11-19 12:31:41.619 DEBUG testcase.Check SmartWait improved        - 2: globalSmartWaitEnabled = get(GLOBAL_SMART_WAIT_MODE)).orElse(false)
2023-11-19 12:31:41.620 DEBUG testcase.Check SmartWait improved        - 3: if (localSmartWaitEnabled.isPresent())
2023-11-19 12:31:41.622 DEBUG testcase.Check SmartWait improved        - 1: if (localSmartWaitEnabled.get())
2023-11-19 12:31:41.624 DEBUG testcase.Check SmartWait improved        - 2: else
2023-11-19 12:31:41.626 DEBUG testcase.Check SmartWait improved        - 1: println("Locally disabled. no SmartWait")
Locally disabled. no SmartWait
2023-11-19 12:31:41.629 DEBUG testcase.Check SmartWait improved        - 6: println("Enable locally")
Enable locally
2023-11-19 12:31:41.632 DEBUG testcase.Check SmartWait improved        - 7: enableSmartWait()
2023-11-19 12:31:41.647 DEBUG testcase.Check SmartWait improved        - 8: simulateSmartWait()
2023-11-19 12:31:41.650 DEBUG testcase.Check SmartWait improved        - 1: localSmartWaitEnabled = Optional.ofNullable(getExecutionProperties().get(LOCAL_SMART_WAIT_MODE))
2023-11-19 12:31:41.651 DEBUG testcase.Check SmartWait improved        - 2: globalSmartWaitEnabled = get(GLOBAL_SMART_WAIT_MODE)).orElse(false)
2023-11-19 12:31:41.652 DEBUG testcase.Check SmartWait improved        - 3: if (localSmartWaitEnabled.isPresent())
2023-11-19 12:31:41.653 DEBUG testcase.Check SmartWait improved        - 1: if (localSmartWaitEnabled.get())
2023-11-19 12:31:41.654 DEBUG testcase.Check SmartWait improved        - 1: println("Locally enabled. do SmartWait")
Locally enabled. do SmartWait
2023-11-19 12:31:41.666 INFO  c.k.katalon.core.main.TestCaseExecutor   - END Test Cases/Check SmartWait improved

I think, this should be backward compatible. Can be improved a bit i guess, but I will let it to Katalon team to decide.
Until this is addressed, the only option for the user is to manually override GLOBAL_SMART_WAIT_MODE per the @kazurayam example

since this may be a bit TLDR, let us summarize:

The right logic when this has been implemented, as repeated few times by @Russ_Thomas, should have been:

  • opt in for smart wait, no matter globally or locally (default disabled)
    … however, now is a bit late

The current logic is:

  • user can enable or disable smart wait by code only if is globally enabled
    … which is meh IMHO (i was tempted to say ‘childish’ but I may be sued again)

The improved logic can be (with backward compatibility in mind):

  • choice by code should be respected, global settings should be followed only if there is no code choice

Having all this sumarrized, for the current topic the @kazurayam workaround has to be marked as solution, the remaining are just details on what katalon developers may have to do:

Hi,

Thank you all for such an interesting discussion and lots of effort here. I have raised the issue of this Smart Wait for my team and hope to update with you soon if any further thing.
Sorry for not able to read the whole thread and late response. Have a good day~

Hi…

I have some problem when trying to connect using Windows 11 here are the errors

java.util.concurrent.ExecutionException: org.openqa.selenium.WebDriverException: Connection refused: no further information

Build info: version: '3.141.59', revision: 'e82be7d358', time: '2018-11-14T08:25:53'

System info: host: 'SYLVIA-ASTRIDA', ip: '192.168.10.184', os.name: 'Windows 11', os.arch: 'amd64', os.version: '10.0', java.version: '17.0.7'

Driver info: driver.version: WindowsDriver

at com.kms.katalon.composer.components.impl.dialogs.ProgressMonitorDialogWithThread.runAndWait(ProgressMonitorDialogWithThread.java:49)

at com.kms.katalon.composer.windows.dialog.WindowsAppComposite$5.run(WindowsAppComposite.java:240)

at org.eclipse.jface.operation.ModalContext$ModalContextThread.run(ModalContext.java:122)

Caused by: org.openqa.selenium.WebDriverException: Connection refused: no further information

Build info: version: '3.141.59', revision: 'e82be7d358', time: '2018-11-14T08:25:53'

System info: host: 'SYLVIA-ASTRIDA', ip: '192.168.10.184', os.name: 'Windows 11', os.arch: 'amd64', os.version: '10.0', java.version: '17.0.7'

Driver info: driver.version: WindowsDriver

at io.appium.java_client.remote.AppiumCommandExecutor.lambda$5(AppiumCommandExecutor.java:251)

at io.appium.java_client.remote.AppiumCommandExecutor.execute(AppiumCommandExecutor.java:250)

at org.openqa.selenium.remote.RemoteWebDriver.execute(RemoteWebDriver.java:552)

at io.appium.java_client.DefaultGenericMobileDriver.execute(DefaultGenericMobileDriver.java:42)

at io.appium.java_client.AppiumDriver.execute(AppiumDriver.java:1)

at io.appium.java_client.windows.WindowsDriver.execute(WindowsDriver.java:1)

at org.openqa.selenium.remote.RemoteWebDriver.startSession(RemoteWebDriver.java:213)

at org.openqa.selenium.remote.RemoteWebDriver.<init>(RemoteWebDriver.java:131)

at io.appium.java_client.DefaultGenericMobileDriver.<init>(DefaultGenericMobileDriver.java:38)

at io.appium.java_client.AppiumDriver.<init>(AppiumDriver.java:84)

at io.appium.java_client.windows.WindowsDriver.<init>(WindowsDriver.java:38)

at com.kms.katalon.core.windows.driver.WindowsDriverFactory.newWindowsDriver(WindowsDriverFactory.java:194)

at com.kms.katalon.core.windows.driver.WindowsDriverFactory.startApplication(WindowsDriverFactory.java:112)

at com.kms.katalon.composer.windows.spy.WindowsInspectorController.startApplication(WindowsInspectorController.java:150)

at com.kms.katalon.composer.windows.dialog.WindowsAppComposite$5$1.call(WindowsAppComposite.java:243)

at com.kms.katalon.composer.components.impl.dialogs.ProgressMonitorDialogWithThread.startThreadAndWait(ProgressMonitorDialogWithThread.java:36)

at com.kms.katalon.composer.components.impl.dialogs.ProgressMonitorDialogWithThread.runAndWait(ProgressMonitorDialogWithThread.java:48)

... 2 more

Caused by: java.net.ConnectException: Connection refused: no further information

at okhttp3.internal.platform.Platform.connectSocket(Platform.java:129)

at okhttp3.internal.connection.RealConnection.connectSocket(RealConnection.java:245)

at okhttp3.internal.connection.RealConnection.connect(RealConnection.java:165)

at okhttp3.internal.connection.StreamAllocation.findConnection(StreamAllocation.java:257)

at okhttp3.internal.connection.StreamAllocation.findHealthyConnection(StreamAllocation.java:135)

at okhttp3.internal.connection.StreamAllocation.newStream(StreamAllocation.java:114)

at okhttp3.internal.connection.ConnectInterceptor.intercept(ConnectInterceptor.java:42)

at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147)

at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:121)

at okhttp3.internal.cache.CacheInterceptor.intercept(CacheInterceptor.java:93)

at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147)

at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:121)

at okhttp3.internal.http.BridgeInterceptor.intercept(BridgeInterceptor.java:93)

at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147)

at okhttp3.internal.http.RetryAndFollowUpInterceptor.intercept(RetryAndFollowUpInterceptor.java:126)

at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147)

at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:121)

at okhttp3.RealCall.getResponseWithInterceptorChain(RealCall.java:200)

at okhttp3.RealCall.execute(RealCall.java:77)

at org.openqa.selenium.remote.internal.OkHttpClient.execute(OkHttpClient.java:103)

at org.openqa.selenium.remote.ProtocolHandshake.createSession(ProtocolHandshake.java:105)

at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)

at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)

at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)

at io.appium.java_client.remote.AppiumCommandExecutor$1.createSession(AppiumCommandExecutor.java:186)

at io.appium.java_client.remote.AppiumCommandExecutor.createSession(AppiumCommandExecutor.java:217)

at io.appium.java_client.remote.AppiumCommandExecutor.execute(AppiumCommandExecutor.java:239)

... 17 more

Please help us

Thanks
Sylvia