Enhancing Your Automated Testing With Chrome Devtools In Katalon Studio

04-02-2024 door Roy de Kleijn

Katalon still relies on Selenium WebDriver 3.*, which means we can't use Chrome DevTools directly. This blog describes a few cases where we might want to use Chrome DevTools. Hence the name, Chrome DevTools is only available in Chromium-based browsers.

Prerequisite As a prerequisite, we need to make sure both Java SDK and Gradle are installed / available on the path.

Setting Up the Environment

  • Modifying build.gradle

    • Open your Katalon project and locate the build.gradle file.
    • Add the cdt-java-client dependency to the file:

    implementation group: 'io.testsmith', name: 'cdt-java-client', version: '4.0.0-testsmith-2'

  • Running Gradle Command

    • Open the terminal or command prompt.
    • Navigate to the Katalon project directory.
    • Run the command: gradle katalonCopyDependencies.
  • Make Chrome DevTools Available

public class CdpUtils {
	public static String[] getServiceEndpoint() {
		WebDriver driver = DriverFactory.getWebDriver()
		HasCapabilities hc = ((driver) as HasCapabilities)
		Map<?, ?> m = hc.getCapabilities().asMap()
		m = m.get('goog:chromeOptions')
		String da = m.get('debuggerAddress')
		String[] daElements = da.split(':')
		return daElements
	}

	public static ChromeDevToolsService getService() {
		WebDriver driver = DriverFactory.getWebDriver()
		String[] daElements = getServiceEndpoint()
		String host = daElements[0]
		int port = Integer.parseInt(daElements[1])
		ChromeService cs = new ChromeServiceImpl(host, port)
		ChromeTab t = cs.getTabs().find({
			ChromeTab tab = ((it) as ChromeTab)
			if (tab.getUrl().equals(driver.getCurrentUrl())) {
				return tab
			}
		})

		ChromeDevToolsService cdts = cs.createDevToolsService(t)
		return cdts
	}
}

Implementing Chrome Dev Tools Features in Katalon

Now we can implement the following features (and many more...) into Katalon.

  • setGeoLocation(double latitude, double longitude, int accuracy):
    • Testing Geo-specific Content and Services: This function allows you to simulate the geographical location of your web application's users. You can test your application's behavior in various geographic locations by setting different latitudes and longitudes. This is particularly useful for services that deliver location-specific content or functionalities, such as local news, weather forecasts, or location-based search results.
    • Debugging Geo-restriction Issues: You can use this feature to verify the implementation of geo-restrictions or geo-fencing features, ensuring that content or services meant for specific regions are appropriately restricted or enabled.
@Keyword
def setGeoLocation(double latitude, double longitude, int accuracy) {
	WebDriver driver = DriverFactory.getWebDriver()

	ChromeDevToolsService cdts = CdpUtils.getService()
	cdts.emulation.setGeolocationOverride(latitude, longitude, accuracy)
	driver.navigate().refresh()
}
  • setTimezone(String timezone):
    • Testing Timezone-Sensitive Features: This function is vital for testing applications that display or rely on timezone-specific data. It helps ensure that features like event scheduling, calendar functionalities, and time displays work correctly across different time zones.
    • Identifying Bugs Related to Timezone Handling: Timezone-related bugs can be subtle and hard to detect. By setting different timezones, you can uncover issues related to date and time calculations, daylight saving changes, and time format display.
@Keyword
def setTimezone(String timezone) {
	WebDriver driver = DriverFactory.getWebDriver()

	ChromeDevToolsService cdts = CdpUtils.getService()
	cdts.emulation.setTimezoneOverride(timezone)

	driver.navigate().refresh()
}
  • waitForNetworkRequest(String pathEndsWidth, int expectedAmount):
    • Validating API Calls and Data Loading: It's particularly useful for testing applications that rely heavily on API calls. You can verify if the correct API requests are made and the expected number of times, which is essential for functionalities like data fetching, dynamic content loading, or form submissions.
@Keyword
def waitForNetworkRequest(String pathEndsWidth, int expectedAmount) {
	/** Get DevTools service to a tab in Chrome browser */
	WebDriver driver = DriverFactory.getWebDriver()
	ChromeDevToolsService cdts = CdpUtils.getService()

	/** Get individual CDP commands */
	Page page = cdts.getPage()
	Network network = cdts.getNetwork()
	page.enable()
	network.enable()

	// Variable to track the completion of the desired request
	int desiredRequestComplete = 0
	String desiredRequestUrl = pathEndsWidth // Change this to your specific request URL

	/** Log requests */
	network.onRequestWillBeSent({ RequestWillBeSent event ->
		println "request : ${event.getRequest().getMethod()} ${event.getRequest().getUrl()}"
	})

	/** Log responses and check for the desired request */
	network.onResponseReceived({ ResponseReceived event ->
		Response resp = event.getResponse()
		println "response: ${resp.getStatus()} ${resp.getStatusText()} ${resp.getUrl()}"
		if (resp.getUrl().endsWith(desiredRequestUrl)) {
			desiredRequestComplete++;
		}
	})

	WebUI.navigateToUrl(GlobalVariable.baseUrl)

	// Wait until the desired request is completed
	while (desiredRequestComplete != expectedAmount) {
		Thread.sleep(500)
	}
	cdts.close()
	cdts.waitUntilClosed()
}

Delen: