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 :
- resolve the name of Profile to load by code
- 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.
- 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.
- 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
- I want to use a
GlobalVariable.URL
to tell the processURL
module of the target URL string.
- I want to create 2 Execution Profiles named
demoProductionEnv
and demoDevelopmentEnv
.
- 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.
The Test Suite Collection TCS
comprises with the following code modules.
Test Suites/demo_using_TestSuiteCollection/TSC
Test Suites/demo_using_TestSuiteCollection/preProcess
Test Suites/demo_using_TestSuiteCollection/processURL
Test Suites/demo_using_TestSuiteCollection/postProcess
Test Cases/demo/demo_using_TestSuiteCollection/preProcess
Test Cases/demo/demo_using_TestSuiteCollection/processURL
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.