The Core Issue
The problem occurs because your script lacks conditional logic and proper failure handling. When you blindly execute WebUI.click() on an already selected checkbox, one of two things happens depending on your site’s architecture:
-
It unchecks the box (violating your test’s intent to ensure all are checked).
-
It throws an element state exception or fails a strict verification step, which by default instructs Katalon Studio to halt the entire test execution.
To build a robust, scalable test, you must first verify the state of the checkbox using WebUI.verifyElementChecked or WebUI.getAttribute before interacting with it. Furthermore, you must change the default FailureHandling behavior so that an unexpected state doesn’t kill the entire loop.
The Solution
-
Check the State First: Use WebUI.verifyElementChecked() with a brief timeout.
-
Apply Optional Failure Handling: Pass FailureHandling.OPTIONAL as an argument. This tells Katalon, “If this check fails (i.e., the box is NOT checked), do not stop the test—just move to the next line.”
-
Conditional Execution: Wrap the click action inside a logic block so it only fires when necessary.
Custom Keyword Implementation
Instead of cluttering your main test scripts with complex loop logic, the industry standard is to encapsulate this behavior into a reusable Custom Keyword. This allows any tester on your team to check a list of checkboxes safely with a single line of code.
Here is the custom keyword solution.
1. Create the Custom Keyword
In Katalon Studio, navigate to Keywords, create a new Package (e.g., com.helper), create a new Keyword class (e.g., CheckboxUtils), and paste the following code:
Groovy
package com.helper
import com.kms.katalon.core.annotation.Keyword
import com.kms.katalon.core.model.FailureHandling
import com.kms.katalon.core.testobject.TestObject
import com.kms.katalon.core.util.KeywordUtil
import com.kms.katalon.core.webui.keyword.WebUiBuiltInKeywords as WebUI
public class CheckboxUtils {
/**
* Safely loops through a list of checkbox TestObjects and ensures they are checked.
* If a checkbox is already checked, it skips it smoothly.
* * @param checkboxObjects A List of TestObjects representing the checkboxes
*/
@Keyword
def void ensureAllCheckboxesAreChecked(List<TestObject> checkboxObjects) {
for (int i = 0; i < checkboxObjects.size(); i++) {
TestObject checkbox = checkboxObjects.get(i)
// Check if the element is visible/present first
if (WebUI.waitForElementVisible(checkbox, 5, FailureHandling.OPTIONAL)) {
// Verify if checked. Using OPTIONAL prevents the test from stopping if it returns false.
boolean isChecked = WebUI.verifyElementChecked(checkbox, 2, FailureHandling.OPTIONAL)
if (!isChecked) {
WebUI.click(checkbox)
KeywordUtil.logInfo("Checkbox at index " + i + " was unchecked. Clicked successfully.")
} else {
KeywordUtil.logInfo("Checkbox at index " + i + " is already checked. Skipping.")
}
} else {
KeywordUtil.logWarning("Checkbox at index " + i + " was not visible within timeout limits.")
}
}
}
}
2. How to Use It in Your Main Test Script (Script View)
Once the keyword is saved, you can call it elegantly in your main test case like this:
Groovy
import static com.kms.katalon.core.testobject.ObjectRepository.findTestObject
import com.kms.katalon.core.testobject.TestObject
// 1. Gather your checkbox Test Objects into a list
List<TestObject> myCheckboxes = [
findTestObject('Object Repository/Page_Home/checkbox_1'),
findTestObject('Object Repository/Page_Home/checkbox_2'),
findTestObject('Object Repository/Page_Home/checkbox_3')
]
// 2. Call your custom keyword to handle the looping safely
CustomKeywords.'com.helper.CheckboxUtils.ensureAllCheckboxesAreChecked'(myCheckboxes)