ExecutionProfilesLoader v2.0 with listing GlogalVariables in action + creating GlobalVariables with Map

2. Loading Profiles by code

Katalon Studio requires you to specify a Profile before launching a test. Katalon Studio provides no way to load Profile(s) by code while your test is running. I would argue that this design is short for a lot of test scenarios.

This library provides a Custom Keywords that supports loading Profile(s) in more flexible manner.

2.1 Loading a Profile programmatically

The following sample code shows how to :

  1. resolve the name of Profile to load by code
  2. load the Profile and update the values of GlobalVariables in action with the initial values declared in the Profile.

Sample code:

// Test Cases/docs/2_loading_Profiles/1_loading_a_Profile_programaticaly

import internal.GlobalVariable

println "\n" + "[BEFORE] GlobalVariable.URL1 = " + GlobalVariable.URL1 + "\n"

CustomKeywords.'com.kazurayam.ks.globalvariable.ExecutionProfilesLoader.loadProfiles'("demoProductionEnvironment")

println "\n" + "[AFTER] GlobalVariable.URL1 = " + GlobalVariable.URL1 + "\n"

Output:

2022-05-08 22:04:35.727 INFO  c.k.katalon.core.main.TestCaseExecutor   - --------------------
2022-05-08 22:04:35.731 INFO  c.k.katalon.core.main.TestCaseExecutor   - START Test Cases/docs/2_loading_Profiles/1_loading_a_Profile_programatically

[BEFORE] GlobalVariable.URL1 = null

[AFTER] GlobalVariable.URL1 = http://demoaut.katalon.com/

2022-05-08 22:04:36.958 INFO  c.k.katalon.core.main.TestCaseExecutor   - END Test Cases/docs/2_loading_Profiles/1_loading_a_Profile_programaticaly

Please find that the GlobalVariable.URL1 was null before the Profile demoProductionEnvironment was loaded. After the Profile was loaded by calling ExecutionProfileLoader.loadProfile(String) , the value changed. Of course, the new value was loaded out of the Profile specified.

2.2 Loading Profiles multiple times

The following sample code shows that your test script can repeat loading Profile(s) multiple times and update a single GlobalVariable to have 2 or more values during a test run.

Sample code:

// Test Cases/docs/2_loading_Profiles/2_loading_Profiles_multiple_times

import internal.GlobalVariable

println "\n" + "[1] GlobalVariable.URL1 = " + GlobalVariable.URL1 + "\n"

CustomKeywords.'com.kazurayam.ks.globalvariable.ExecutionProfilesLoader.loadProfiles'("demoProductionEnvironment")

println "\n" + "[2] GlobalVariable.URL1 = " + GlobalVariable.URL1 + "\n"

CustomKeywords.'com.kazurayam.ks.globalvariable.ExecutionProfilesLoader.loadProfiles'("demoDevelopmentEnvironment")

println "\n" + "[3] GlobalVariable.URL1 = " + GlobalVariable.URL1 + "\n"

Output:

2022-05-08 22:16:49.457 INFO  c.k.katalon.core.main.TestCaseExecutor   - --------------------
2022-05-08 22:16:49.460 INFO  c.k.katalon.core.main.TestCaseExecutor   - START Test Cases/docs/2_loading_Profiles/2_loading_Profiles_multiple_times

[1] GlobalVariable.URL1 = null

2022-05-08 22:16:50.733 INFO  k.k.c.m.CustomKeywordDelegatingMetaClass - com.kazurayam.ks.globalvariable.ExecutionProfilesLoader.loadProfiles is PASSED

[2] GlobalVariable.URL1 = http://demoaut.katalon.com/

2022-05-08 22:16:50.779 INFO  k.k.c.m.CustomKeywordDelegatingMetaClass - com.kazurayam.ks.globalvariable.ExecutionProfilesLoader.loadProfiles is PASSED

[3] GlobalVariable.URL1 = http://demoaut-mimic.kazurayam.com/

2022-05-08 22:16:50.841 INFO  c.k.katalon.core.main.TestCaseExecutor   - END Test Cases/docs/2_loading_Profiles/2_loading_Profiles_multiple_times

2.3 Loading multiple Profiles at once

The following sample code shows that a test script can load multiple Profiles together at once.

Sample code:

// Test Cases/docs/2_loading_Profiles/3_loading_multiple_Profiles_at_once

import internal.GlobalVariable

println ""
println "[BEFORE] GlobalVariable.CATEGORY = " + GlobalVariable.CATEGORY 
println "[BEFORE] GlobalVariable.ENVIRONMENT = " + GlobalVariable.ENVIRONMENT
println "[BEFORE] GlobalVariable.INCLUDE_SHEETS = " + GlobalVariable.INCLUDE_SHEETS
println "[BEFORE] GlobalVariable.INCLUDE_URLS = " + GlobalVariable.INCLUDE_URLS
println ""

CustomKeywords.'com.kazurayam.ks.globalvariable.ExecutionProfilesLoader.loadProfiles'(
    "main_category3",
    "main_envDevelopment",
    "main_includeSheets_GroupG",
    "main_includeURLs_top")

println ""
println "[AFTER] GlobalVariable.CATEGORY = " + GlobalVariable.CATEGORY
println "[AFTER] GlobalVariable.ENVIRONMENT = " + GlobalVariable.ENVIRONMENT
println "[AFTER] GlobalVariable.INCLUDE_SHEETS = " + GlobalVariable.INCLUDE_SHEETS
println "[AFTER] GlobalVariable.INCLUDE_URLS = " + GlobalVariable.INCLUDE_URLS
println ""

Output:

2022-05-08 22:28:38.714 INFO  c.k.katalon.core.main.TestCaseExecutor   - --------------------
2022-05-08 22:28:38.717 INFO  c.k.katalon.core.main.TestCaseExecutor   - START Test Cases/docs/2_loading_Profiles/3_loading_multiple_Profiles_at_once

[BEFORE] GlobalVariable.CATEGORY = 0
[BEFORE] GlobalVariable.ENVIRONMENT =
[BEFORE] GlobalVariable.INCLUDE_SHEETS = []
[BEFORE] GlobalVariable.INCLUDE_URLS = []

2022-05-08 22:28:40.162 INFO  k.k.c.m.CustomKeywordDelegatingMetaClass - com.kazurayam.ks.globalvariable.ExecutionProfilesLoader.loadProfiles is PASSED

[AFTER] GlobalVariable.CATEGORY = 3
[AFTER] GlobalVariable.ENVIRONMENT = Development
[AFTER] GlobalVariable.INCLUDE_SHEETS = [CompanyL, CompanyM, CompanyN]
[AFTER] GlobalVariable.INCLUDE_URLS = [top.html]

2022-05-08 22:28:40.203 INFO  c.k.katalon.core.main.TestCaseExecutor   - END Test Cases/docs/2_loading_Profiles/3_loading_multiple_Profiles_at_once

This sample tells you that the ExecutionProfilesLoader.loadProfies(String…​ profileNames) enables you to modularize Profiles. What do I mean by “modularize Profiles”?

Let me assume I have the following 15 Profiles. Each of them contains a single GlobalVariable: CATEGORY , ENVIRONMENT , INCLUDE_SHEETS , INCLUDE_URLS .

$ tree .
.
├── main_category0.glbl
├── main_category1.glbl
├── main_category2.glbl
├── main_category3.glbl
├── main_envDevelopment.glbl
├── main_envProduction.glbl
├── main_envStaging.glbl
├── main_includeSheets_ALL.glbl
├── main_includeSheets_CompanyA.glbl
├── main_includeSheets_CompanyB.glbl
├── main_includeSheets_CompanyC.glbl
├── main_includeSheets_GroupG.glbl
├── main_includeURLs_ALL.glbl
├── main_includeURLs_login.glbl
├── main_includeURLs_top.glbl

As you can guess from the above, GlobalVariable.CATEGORY can possibly take 4 variations of values, ENVIRONMENT can take 3, INCLUDE_SHEETS can take 5, and INCLUDE_URLS can take 3. So my test script can programmatically enumerate 4 * 3 * 5 * 3 = 180 possible combinations of values provided with 15 Profiles manually prepared. If I need to increase the number of INCLUDE_SHEETS values from 5 → 10, then the number of combinations will go up to 4 * 3 * 10 * 3 = 360.

If I don’t have the ExecutionProfilesLoader class, I have to prepare 180 or 360 Profiles manually in Katalon Studio’s GUI. It’s just terrible. Modularization of Execution Profiles by ExecutionProfilesLoader class shines to me.

3. Looking at GlobalVariables in action

In a test case script, you can write a code like this:

import internal.GlobalVariable

println "\n" + "GlobalVariable.Hostname=" + GlobalVariable.Hostname + "\n"

This will give you an output like this:

2022-05-08 22:57:04.910 INFO  c.k.katalon.core.main.TestCaseExecutor   - --------------------
2022-05-08 22:57:04.914 INFO  c.k.katalon.core.main.TestCaseExecutor   - START Test Cases/docs/3_looking-at_GlobalVariables_in_action/0_show_GlobalVariable_value

GlobalVariable.Hostname=demoaut.katalon.com

2022-05-08 22:57:05.937 INFO  c.k.katalon.core.main.TestCaseExecutor   - END Test Cases/docs/3_looking-at_GlobalVariables_in_action/0_show_GlobalVariable_value

OK. Then, how can I list all of GlobalVariables currently in action in scope of the running test? Any Katalon’s API? — No. Katalon’s API does not support it.

This library support a feature of looking at GlobalVariables in action.

3.1 Looking at GlobalVariables

Sample code:

// Test Cases/main/3_retrieving_GlobalVariables_in_memory/1_show_GVs_loaded_from_default

CustomKeywords.'com.kazurayam.ks.globalvariable.ExecutionProfilesLoader.loadProfile'('default')

String GVsLoadedFromDefaultProfile = CustomKeywords.'com.kazurayam.ks.globalvariable.LookAtGlobalVariablesKeyword.toJson'()
println "\n" + "GVsLoadedFromDefaultProfile: " + GVsLoadedFromDefaultProfile + "\n"

String GVsLoadedFromDefaultProfile_pretty = CustomKeywords.'com.kazurayam.ks.globalvariable.LookAtGlobalVariablesKeyword.toJson'(true)
println "\n" + "GVsLoadedFromDefaultProfile_pretty: " + GVsLoadedFromDefaultProfile_pretty + "\n"

Output:

2022-05-08 23:10:57.941 INFO  c.k.katalon.core.main.TestCaseExecutor   - --------------------
2022-05-08 23:10:57.947 INFO  c.k.katalon.core.main.TestCaseExecutor   - START Test Cases/docs/3_looking-at_GlobalVariables_in_action/1_look-at_GVs_loaded_from_the_default_Profile
2022-05-08 23:10:59.349 INFO  k.k.c.m.CustomKeywordDelegatingMetaClass - com.kazurayam.ks.globalvariable.ExecutionProfilesLoader.loadProfile is PASSED
2022-05-08 23:10:59.487 INFO  k.k.c.m.CustomKeywordDelegatingMetaClass - com.kazurayam.ks.globalvariable.LookAtGlobalVariablesKeyword.toJson is PASSED

GVsLoadedFromDefaultProfile: {"CATEGORY":0,"CONFIG":"./Include/fixture/Config.xlsx","DEBUG_MODE":false,"ENVIRONMENT":"","Hostname":"demoaut.katalon.com","INCLUDE_SHEETS":[],"INCLUDE_URLS":[],"SAVE_HTML":false,"TIMEOUT":10}

2022-05-08 23:10:59.548 INFO  k.k.c.m.CustomKeywordDelegatingMetaClass - com.kazurayam.ks.globalvariable.LookAtGlobalVariablesKeyword.toJson is PASSED

GVsLoadedFromDefaultProfile_pretty: {
  "CATEGORY": 0.0,
  "CONFIG": "./Include/fixture/Config.xlsx",
  "DEBUG_MODE": false,
  "ENVIRONMENT": "",
  "Hostname": "demoaut.katalon.com",
  "INCLUDE_SHEETS": [],
  "INCLUDE_URLS": [],
  "SAVE_HTML": false,
  "TIMEOUT": 10.0
}

2022-05-08 23:10:59.560 INFO  c.k.katalon.core.main.TestCaseExecutor   - END Test Cases/docs/3_looking-at_GlobalVariables_in_action/1_look-at_GVs_loaded_from_the_default_Profile

As you can see, the toJson() method of LookAtGlobalVariablesKeyword class generates a JSON string, which contains all GlobalVariables that are present in scope of the running test. The toJson(true) makes the JSON string to be pretty-printed with NEWLINEs and indents.

This JSON shows the current value of GlobalVariables in memory, which could be different from the initial values written in the .glbl files in the Profiles directory.

3.2 Looking at GlobalVariables

When you do not explicity specify a Profile to load, Katalon Studio loads the default Profiles. Consequently the JSON by LookAtGlobalVariablesKeyword.toJson() will show GlobalVariables as defined in the default Profile. If you call ExecutionProfilesLoader.loadProfile(String profileName) , then the JSON will overwrite the GlobalVariables with values loaded out of the specified Profile. The following sample code shows this scenario.

Sample code:

// Test Cases/main/3_retrieving_GlobalVariables_in_memory/2_look-at_GVs_added_with_another_Profile

CustomKeywords.'com.kazurayam.ks.globalvariable.ExecutionProfilesLoader.loadProfile'('default')

String defaultJson = CustomKeywords.'com.kazurayam.ks.globalvariable.LookAtGlobalVariablesKeyword.toJson'(true)
println "\n" + "loaded from the default profile: " + defaultJson + "\n"

CustomKeywords.'com.kazurayam.ks.globalvariable.ExecutionProfilesLoader.loadProfile'('test_A')

String plusJson = CustomKeywords.'com.kazurayam.ks.globalvariable.LookAtGlobalVariablesKeyword.toJson'(true)
println "\n" + "plus test_A: " + plusJson + "\n"

Output:

2022-05-08 23:07:27.013 INFO  c.k.katalon.core.main.TestCaseExecutor   - --------------------
2022-05-08 23:07:27.017 INFO  c.k.katalon.core.main.TestCaseExecutor   - START Test Cases/docs/3_looking-at_GlobalVariables_in_action/2_look-at_GVs_loaded_from_multiple_Profiles
2022-05-08 23:07:28.414 INFO  k.k.c.m.CustomKeywordDelegatingMetaClass - com.kazurayam.ks.globalvariable.ExecutionProfilesLoader.loadProfile is PASSED
2022-05-08 23:07:28.531 INFO  k.k.c.m.CustomKeywordDelegatingMetaClass - com.kazurayam.ks.globalvariable.LookAtGlobalVariablesKeyword.toJson is PASSED

loaded from the default profile: {
  "CATEGORY": 0.0,
  "CONFIG": "./Include/fixture/Config.xlsx",
  "DEBUG_MODE": false,
  "ENVIRONMENT": "",
  "Hostname": "demoaut.katalon.com",
  "INCLUDE_SHEETS": [],
  "INCLUDE_URLS": [],
  "SAVE_HTML": false,
  "TIMEOUT": 10.0
}

2022-05-08 23:07:28.614 INFO  k.k.c.m.CustomKeywordDelegatingMetaClass - com.kazurayam.ks.globalvariable.ExecutionProfilesLoader.loadProfile is PASSED
2022-05-08 23:07:28.644 INFO  k.k.c.m.CustomKeywordDelegatingMetaClass - com.kazurayam.ks.globalvariable.LookAtGlobalVariablesKeyword.toJson is PASSED

plus test_A: {
  "AVAR1": "I\u0027m from test_A",
  "AVAR2": 999.0,
  "AVAR3": {
    "keyA": "valueA",
    "keyB": true
  },
  "CATEGORY": 0.0,
  "CONFIG": "./Include/fixture/Config.xlsx",
  "DEBUG_MODE": false,
  "ENVIRONMENT": "",
  "Hostname": "demoaut.katalon.com",
  "INCLUDE_SHEETS": [],
  "INCLUDE_URLS": [],
  "SAVE_HTML": false,
  "TIMEOUT": 10.0
}

2022-05-08 23:07:28.654 INFO  c.k.katalon.core.main.TestCaseExecutor   - END Test Cases/docs/3_looking-at_GlobalVariables_in_action/2_look-at_GVs_loaded_from_multiple_Profiles

4. Creating GlobalVariables without Profile

In Katalon Studio, if you want to add a new GlobalVariable to use in your test script, you have to prepare a Profile where you declare the name of the GV. Katalon Studio provides no way to add a GlobalVariable programmatically without the glbl files.

This library supports creating GlobalVariable(s) with an instance of java.util.Map<String, Object> as parameter.

Please note that an additional GlobalVariable is present only in memory during a run of test; it is not persisted into any glbl file in the Profiles directory.

4.1 Creating GlobalVariables with an instance of Map<String,Object>

Just see the sample code. You will easily see what happens.

Sample code:

// Test Cases/docs/4_creating_GlobalVariables_dynamically/1_creating_GV_from_Map_object

import internal.GlobalVariable

String beforeAddition = CustomKeywords.'com.kazurayam.ks.globalvariable.LookAtGlobalVariablesKeyword.toJson'(true)

println "\n" + "[BEFORE] " + beforeAddition + "\n"

int count = CustomKeywords.'com.kazurayam.ks.globalvariable.ExecutionProfilesLoader.loadEntries'(
		[
			"MY_FAVORITE_AUTHOR": "King, Steven",
			"MY_CURRENT_READ": "Rita Hayworth and Shawshank Redemption"
		])

println ""
println "GlobalVariable.MY_FAVORITE_AUTHOR = " + GlobalVariable.MY_FAVORITE_AUTHOR
println "GlobalVariable.MY_CURRENT_READ = " + GlobalVariable.MY_CURRENT_READ

GlobalVariable.MY_CURRENT_READ = "SHINING"

println "GlobalVariable.MY_CURRENT_READ = " + GlobalVariable.MY_CURRENT_READ
println ""

String afterAddition = CustomKeywords.'com.kazurayam.ks.globalvariable.LookAtGlobalVariablesKeyword.toJson'(true)

println "\n" + "[AFTER] " + afterAddition + "\n"

Output:

2022-05-10 20:47:48.328 INFO  c.k.katalon.core.main.TestCaseExecutor   - --------------------
2022-05-10 20:47:48.334 INFO  c.k.katalon.core.main.TestCaseExecutor   - START Test Cases/docs/4_creating_GlobalVariables_dynamically/1_creating_GV_from_Map_objects
2022-05-10 20:47:50.091 INFO  k.k.c.m.CustomKeywordDelegatingMetaClass - com.kazurayam.ks.globalvariable.LookAtGlobalVariablesKeyword.toJson is PASSED

[BEFORE] {
  "CATEGORY": 0.0,
  "CONFIG": "./Include/fixture/Config.xlsx",
  "DEBUG_MODE": false,
  "ENVIRONMENT": "",
  "Hostname": "demoaut.katalon.com",
  "INCLUDE_SHEETS": [],
  "INCLUDE_URLS": [],
  "SAVE_HTML": false,
  "TIMEOUT": 10.0
}

2022-05-10 20:47:50.296 INFO  k.k.c.m.CustomKeywordDelegatingMetaClass - com.kazurayam.ks.globalvariable.ExecutionProfilesLoader.loadEntries is PASSED

GlobalVariable.MY_FAVORITE_AUTHOR = King, Steven
GlobalVariable.MY_CURRENT_READ = Rita Hayworth and Shawshank Redemption
GlobalVariable.MY_CURRENT_READ = SHINING

2022-05-10 20:47:50.332 INFO  k.k.c.m.CustomKeywordDelegatingMetaClass - com.kazurayam.ks.globalvariable.LookAtGlobalVariablesKeyword.toJson is PASSED

[AFTER] {
  "CATEGORY": 0.0,
  "CONFIG": "./Include/fixture/Config.xlsx",
  "DEBUG_MODE": false,
  "ENVIRONMENT": "",
  "Hostname": "demoaut.katalon.com",
  "INCLUDE_SHEETS": [],
  "INCLUDE_URLS": [],
  "MY_CURRENT_READ": "SHINING",
  "MY_FAVORITE_AUTHOR": "King, Steven",
  "SAVE_HTML": false,
  "TIMEOUT": 10.0
}

2022-05-10 20:47:50.345 INFO  c.k.katalon.core.main.TestCaseExecutor   - END Test Cases/docs/4_creating_GlobalVariables_dynamically/1_creating_GV_from_Map_objects

Background story: why I developed this library

A few years ago (sometime in 2019) I developed a project with Katalon Studio where I wanted to implement the following items.

  1. I want to compare 2 URLs: http://demoaut.katalon.com and http://demoaut-mimic.kazurayam.com to find if these 2 pages have any visual differences.
  2. I will write 3 script modules
  • preProsess, which does some preparention (create work directories, etc)
  • processURL, which will visit a URL and take a screenshot
  • postProcess, which will compile a report in HTML format
  1. I want to use a GlobalVariable.URL to tell the processURL module of the target URL string.
  2. I want to create 2 Execution Profiles named demoProductionEnv and demoDevelopmentEnv .
  3. I want to execute the processURL module 2 twice while applying 2 Profiles demoProductionEnv and demoDevelopmentEnv

Yes. I could develop a set of code that implements this idea.

You can try it by opening the Test Suites/demo_using_TestSuiteCollection of this Katalon project. The following screenshot shows how that Test Suite Collection is constructed.

demo2 TSC

The Test Suite Collection TCS comprises with the following code modules.

  1. Test Suites/demo_using_TestSuiteCollection/TSC
  2. Test Suites/demo_using_TestSuiteCollection/preProcess
  3. Test Suites/demo_using_TestSuiteCollection/processURL
  4. Test Suites/demo_using_TestSuiteCollection/postProcess
  5. Test Cases/demo/demo_using_TestSuiteCollection/preProcess
  6. Test Cases/demo/demo_using_TestSuiteCollection/processURL
  7. Test Cases/demo/demo_using_TestSuiteCollection/postProcess

7 modules! The problem I wanted to solve was simple, but the code set I got was complicated as such. Why?

The reason is that Katalon Studio does not provide any means of loading an Execution Profile in test script programmatically. Katalon Studio forces me to create a Test Suite Collection, in which I execute the Test Suite processURL 2 twice while applying 2 Profiles demoProductionEnv and demoEnvironmentEnv .

I thought about this for several months and I got an idea of the ExecutionProfilesLoader class. This tool changes many things.

Now I have developed the ExecutionProfilesLoader and other classes. Using this supportive library, I could develop an alternative solution. The following single Test Case script of just 84 lines does exactly the same as my old solution achieved.

Conclusion

The ExecutionProfilesLoader library helps me organize my Katalon projects with GlobalVariables with much flexibilities.

2 Likes