GlobalVariable Map is not picking up the latest key value

Found that the GlobalVariable Map is not picking up the latest Value of a Key during execution.

1. Define a Global Variable Map, ie. TestingA variable.
2. Assign value to the TestingA Map in the TestListener, Before Test Case
eg. GlobalVariable.TestingA.put(“A”,“Testing 123”)
3. In the Test Case, modify the TestingA value, eg. GlobalVariable.TestingA.put(“A”, “This is modified”)
4. in the TestListner, After Test Case, found below:
GlobalVariable.TestingA.get(“A”) → Resulting in the value : “Testing 123”. I am expecting the value should be “This is modified” instead .

This is happening in the GlobalVariable with MAP, Please assist.

You need to explicitly cast a GlobalVariable to a variable of type Map, then you can call put/get methods on it.

def map = (Map)GlobalVariable.TestingA
map.put("A","Testing 123")WebUI.comment("map['A'] is ${map['A']}")

Thanks @4280-kazurayam
but this does not work either… still the value capture at the “@AfterTestCase” is referring to the old value

@BeforeTestCase

def map= (Map)GlobalVariable.testingA

map.put(‘A’,‘Original Value’)

in the test case:

def map= (Map)GlobalVariable.testingA

map.put(‘A’, ‘New Value’)

@AfterTestCase

def map= (Map)GlobalVariable.testingA

map.get(‘A’)

println “A=” + map.get(‘A’)

–> This will show the value ‘A=Original value’

Tried also:

@BeforeTestCase

GlobalVariable.testingA.put(‘A’,‘Original Value’)

in the test case:

GlobalVariable.testingA.put(‘A’, ‘newValue’)

@AfterTestCase

GlobalVariable.testingA.get(‘A’)

The output is still “Original value” , in both of the case above.

Try re-assigning value to the GlobalVariabl in the test case:

def map= (Map)GlobalVariable.testingA
map.put('A', 'New Value')
GlobalVariable.testingA = map

same @4280-kazurayam , no luck with this as well…

I have made a demo project here:

I copy&paste its readme as follows.
------------

How to run the demo

  1. Download the latest zip of the project from the [releases]https://github.com/kazurayam/KatalonDiscussion10064/releases) page, unzip it.
  2. Open the project with your Katalon Studio.
  3. Open the Test Cases/TC and run it with any browser

How it worked

Please find the source here:

  • Test Listeners/TL

    import com.kms.katalon.core.annotation.AfterTestCaseimport com.kms.katalon.core.annotation.BeforeTestCaseimport com.kms.katalon.core.context.TestCaseContextimport com.kms.katalon.core.webui.keyword.WebUiBuiltInKeywords as WebUIimport internal.GlobalVariable as GlobalVariableclass TL {		@BeforeTestCase	def beforeTestCase(TestCaseContext testCaseContext) {		Map m = (Map)GlobalVariable.TestingA		m.put("A","Testing 123")	}		@AfterTestCase	def afterTestCase(TestCaseContext testCaseContext) {		Map m = (Map)GlobalVariable.TestingA		WebUI.comment(">>> after test case, m.get('A')=${m.get('A')}")	}	}
    
  • Test Cases/TC

    import com.kms.katalon.core.webui.keyword.WebUiBuiltInKeywords as WebUIimport internal.GlobalVariable as GlobalVariableMap m = (Map)GlobalVariable.TestingAWebUI.comment(">>> before update, m.get('A')=${m.get('A')}")m.put("A", "This is modified")
    

When I executed the Test Case, I got the following messages in the log:

...10-11-2018 09:40:06 AM - [INFO]   - >>> before update, m.get('A')=Testing 123...10-11-2018 09:40:06 AM - [INFO]   - >>> after test case, m.get('A')=This is modified...

Conclusion

In my environment, the Test Lister TL and the Test Case TC successfully read and update the GlobalVariable of type java.util.Map.

I presume the questioner who raised the original question has a problem unique to his own environment. For example the Groovy source of the GlobalVariable is not compiled by Groovy properly.

Countermeasure

I would like to suggest him to take the following procedure:

  1. stop Katalon Studio GUI.
  2. remove the <project directory>/bin/ directory where all of the compiled class files are stored including the internal.GlobalVariable class.
  3. restart Katalon Studio GUI.
  4. run the Test Case TC again; then all of Groovy sources will be recompiled. You will see the result by clean-built binaries.

Thanks @4280-kazurayam for the detail explanation. I found the root cause of the problem was on the looping assignment.
Can check if there is any differences if the value is assign into the global variable via another map loop? Detail code as below, For eg.

In the Test listener:

@BeforeTestCasedef beforeTestCase(TestCaseContext testCaseContext) {
	Map m = (Map)GlobalVariable.TestingA
	m.put("A","Testing 123")
}
@AfterTestCasedef afterTestCase(TestCaseContext testCaseContext) {	Map m = (Map)GlobalVariable.TestingA	WebUI.comment(">>> after test case, m.get('A')=${m.get('A')}")	GlobalVariable.TestingA.each{k, v ->	println "After Key=" + "${k}" + ";Value=" + GlobalVariable.DataTable.get("${k}")	}	WebUI.comment(">>> before test case, m.get('A')=${m.get('A')}")	}

**In the Test case: **

localMap.put('A', 'Value in Test Case')
localMap.put('B', 'Second Value in Test Case')
localMap.each{k, v ->
	GlobalVariable.TestingA.put("${k}","${v}")
	println "Key=" + "${k}" + ";Value=" + GlobalVariable.TestingA.get("${k}")
}

The result:
before test case, m.get(‘A’) = Testing 123
Key=A; Value=Value in Test Case
Key=B; Value=Second Value in Test Case
**after test case, m.get(‘A’) = Testing 123 -> Problem: The value retrieved is Old value, instead of the value assigned in Test Case
**After Key=A; Value=Value in Test Case
After Key=B; Value=Second Value in Test Case

@AfterTestCasedef afterTestCase(TestCaseContext testCaseContext) {	Map m = (Map)GlobalVariable.TestingA	WebUI.comment(">>> after test case, m.get('A')=${m.get('A')}")	GlobalVariable.TestingA.each{k, v ->	println "After Key=" + "${k}" + ";Value=" + GlobalVariable.DataTable.get("${k}")	}

What is “DataTable” here? I do not understand this.

Sorry @4280-kazurayam , was a typo. Should be :
println “After Key=” + “${k}” + “;Value=” + GlobalVariable.TestingA.get("${k}") instead.

my actual code in used is using that as my Global variable name. Just replaced with the TestingA var name to be consistent with my initial post…

**In the Test case: **

localMap.put('A', 'Value in Test Case')

I do not see how the localMap variable is declared and initilaized. Please paste your test case fully (no cut-off please)

Also in the test case:

localMap.each{k, v ->	GlobalVariable.TestingA.put("${k}","${v}")...

What are you doing here? I do not see the intention of this code.

Hi @4280-kazurayam
Leave aside the purpose why I assign a local Map value into the global Map. Yes, I know & agreed that by casting the GlobalVariable is more straight forward option.

My doubt is why is the Value being put through the loop wasn’t able to retrieved directly, since it was put into the same GlobalVariable.

Full Code as below (Exclude all the Import part, since it is default import):

import internal.GlobalVariable as GlobalVariableimport com.kms.katalon.core.annotation.BeforeTestCaseimport com.kms.katalon.core.annotation.BeforeTestSuiteimport com.kms.katalon.core.annotation.AfterTestCaseimport com.kms.katalon.core.annotation.AfterTestSuiteimport com.kms.katalon.core.context.TestCaseContextimport com.kms.katalon.core.context.TestSuiteContextclass NewTestListener {	/**	 * Executes before every test case starts.	 * @param testCaseContext related information of the executed test case.	 */	@BeforeTestCase	def sampleBeforeTestCase(TestCaseContext testCaseContext) {		Map m = (Map)GlobalVariable.TestingA		m.put("A","Testing 123")		WebUI.comment(">>> Before test case, m.get('A')=${m.get('A')}")	}	/**	 * Executes after every test case ends.	 * @param testCaseContext related information of the executed test case.	 */	@AfterTestCase	def sampleAfterTestCase(TestCaseContext testCaseContext) {		Map m = (Map)GlobalVariable.TestingA		WebUI.comment(">>> after test case, m.get('A')=${m.get('A')}")		GlobalVariable.TestingA.each{k, v ->			WebUI.comment ">>> After Test Case Loop Key=" + "${k}" + ";Value=" + GlobalVariable.TestingA.get("${k}")			}	}}Test Case:import internal.GlobalVariable as GlobalVariableMap<String,String> localMap = [:]localMap.put('A', 'Value in Test Case')localMap.put('B', 'Second Value in Test Case')localMap.each{k, v ->	GlobalVariable.TestingA.put("${k}","${v}")	WebUI.comment ">>>In Test Case Loop Key=" + "${k}" + ";Value=" + GlobalVariable.TestingA.get("${k}")}

Result in Console:

10-12-2018 05:16:25 PM - [INFO]   - >>> Before test case, m.get('A')=Testing 12310-12-2018 05:16:26 PM - [INFO]   - >>>In Test Case Loop Key=A;Value=Value in Test Case10-12-2018 05:16:26 PM - [INFO]   - >>>In Test Case Loop Key=B;Value=Second Value in Test Case10-12-2018 05:16:26 PM - [INFO]   - >>> after test case, m.get('A')=Testing 12310-12-2018 05:16:26 PM - [INFO]   - >>> After Test Case Loop Key=A;Value=Value in Test Case10-12-2018 05:16:26 PM - [INFO]   - >>> After Test Case Loop Key=A;Value=Value in Test Case10-12-2018 05:16:26 PM - [INFO]   - >>> After Test Case Loop Key=B;Value=Second Value in Test Case

In the Test Case as well, you need to cast the internal.GlobalVariable.TestingA object to java.util.Map before calling its put method:

localMap.each{k, v ->	Map m = (Map)GlobalVariable.TestingA        m.put("${k}","${v}")