How to update GlobalVariable permanently

Hello,

there were few requests to add an ability to change GlobalVariable permanently.
I wrote a custom keyword which can do it.
Works with Katalon Studio 6.3.0

Disclaimer: I am not responsible for any damages caused by this code. This method modifies profile file in your project folder and changes are permanent. Make sure you have proper backup of all your files in any case.

Code:

Click me
import java.nio.file.Files
import java.nio.file.Paths

import javax.xml.parsers.DocumentBuilder
import javax.xml.parsers.DocumentBuilderFactory
import javax.xml.transform.OutputKeys
import javax.xml.transform.Transformer
import javax.xml.transform.TransformerFactory
import javax.xml.transform.dom.DOMSource
import javax.xml.transform.stream.StreamResult

import org.w3c.dom.Document
import org.w3c.dom.Element
import org.w3c.dom.NodeList

import com.kms.katalon.core.configuration.RunConfiguration
import com.kms.katalon.core.util.KeywordUtil

/**
 * @author mmelocik
 *
 */
public class GlobalVariableUpdater {
	
	
	/** WARNING - Permanently updates a variable in currently used execution profile.<br>
	 * Original value will be replaced with new value and cannot be restored.
	 * @param varName
	 * @param newValue
	 */
	public static void updatePermanently(String varName, String newValue) {
		updatePermanently(RunConfiguration.getExecutionProfile(), varName, newValue)
	}
	
	/** WARNING - Permanently updates a variable in specified execution profile.<br>
	 * Original value will be replaced with new value and cannot be restored.
	 * @param envName
	 * @param varName
	 * @param newValue
	 */
	public static void updatePermanently(String envName, String varName, String newValue) {
		File inputFile = new File(RunConfiguration.getProjectDir() + "//Profiles//" + envName + ".glbl")
		if(!Files.exists(Paths.get(inputFile.getAbsolutePath()))) {
			KeywordUtil.markFailed("A file with profile was not found - check path: " + inputFile.getAbsolutePath())
		}

		DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance()
		DocumentBuilder builder = factory.newDocumentBuilder()
		Document document = builder.parse(inputFile)

		NodeList elems = document.getDocumentElement().getElementsByTagName("GlobalVariableEntity")
		for(Element elem in elems) {
			if(elem.getElementsByTagName("name").item(0).getTextContent() == varName) {
				elem.getElementsByTagName("initValue").item(0).setTextContent("'" + newValue + "'")
				document.getDocumentElement().normalize()
				Transformer transformer = TransformerFactory.newInstance().newTransformer()
				DOMSource source = new DOMSource(document)
				StreamResult result = new StreamResult(inputFile)
				transformer.setOutputProperty(OutputKeys.INDENT, "yes")
				transformer.transform(source, result)
				return
			}
		}
		KeywordUtil.markWarning("Global variable with name " + varName + " was not found.")
	}
}

Usage:

// change selected profile
GlobalVariableUpdater.updatePermanently("myProfileName", "VariableName", "new value")

// change current profile
GlobalVariableUpdater.updatePermanently("VariableName", "new value")
6 Likes

Hello
thank you for this Keyword but i have a problem,
every time i put a new value for the same GlobalVariable, i must run my testcase twice to make the new value taking effect
do you know why ??

Hello,

I’d say that once your test is running, all variables are cached and Katalon does not check for updates in the file, which contains your variables. I will try to look for a solution for your problem.

2 Likes

@Marek_Melocik thanks bro, this keyword fit perfectly what I was needing

I just wanted to increase a number inside my GlobalVariable Email and It’s working and increasing perfectly well

This is my Code
@TearDown(skipped = false) // Please change skipped to be false to activate this method.
def tearDown() {
	String number = GlobalVariable.RealtorEmail.split('realtor')[1].substring(0,2).trim()
	Integer numberInt = Integer.parseInt(number)+1
	String newEmail1= "lemonbrewqa+realtor" + numberInt.toString() + "@gmail.com";
	
	'Assign new value in real time (not updates the profile)'
	//GlobalVariable.RealtorEmail=newEmail1
	
	'Assign new value in real time (updates the profile with new value)'
	CustomKeywords.'lemonbrew.GlobalVariableUpdater.updatePermanently'("Agent", "RealtorEmail" , newEmail1)
}

@mtayahi I saw the following maybe could helps you, as commented by @Marek_Melocik is that Katalon does not look for updates in the execution profile until the executions are finished. For me it is not a problem because I configured this code in TearDown and it works. But if you are trying to update the same variable, check the commented line in my code. Maybe you can increase this value in every testcase and at the end of the suit you Update the variable value in your profile

To take in mind and was freaking me out was that the profile wasn’t updating automatically in the IDE (but is updating in the folder file). To see that the value increased, you have to close the profile tab and open it again after Katalon finishes loading and sending the reports

PD: This was my first keyword and I didn’t realize that the word “@Keyword” was missing over the public static void functions, so for those whose are in the same take a look on that guys :slight_smile:

1 Like

You can do it even without @Keyword annotation as well. Just write

GlobalVariableUpdater.updatePermanently("Agent", "RealtorEmail" , newEmail1)
and add necessary import :slight_smile:

Regarding to runtime variable update, I wasn’t able to find any method which can refresh it on the fly. Maybe Katalon devs can provide one.

1 Like

Thanks Marek!

Just a doubt, is any function or parameter that could we could use to make this “keyword” runs only if all tests got passed?

I think you can use teardown method for whole Test Suite, see more

1 Like

Regarding parallel test suite execution, is this keyword thread-safe?

is this keyword thread-safe?

i don’t think so.
this keyword will update the content of the .xml file from which the global profile instance is created.
if some threads are using the same profile, you will have a race-condition.

can be safe to use with parallel execution only if each thread is using a different profile.

Hello,
Thanks a lot, you help me :slight_smile: