Hey aaronpliu
well if it isn't broke, don't fix it - so I'm happy to defer to your greater knowledge in this regard and steal your approach as it appears your approach is more efficient than what I would put together anyway!
I cant thank you enough - I don't know whether this is actually beyond me - I know this is pretty basic coding - but it still falls far outside my skillset. I'm hopeful I can apply what you provided - but it depends on the answer you provide to see if I can actually get my head around this or not.
I have a number of questions based on your approach if thats ok? I will BOLD the questions and also highlight in RED text too. I have specific questions on each of the steps listed in your response.
I do however, understand if there are too many questions and this is just too much work for you to answer.
Considering the code snippet:
// Step 1: create 4 folders with your properties file.
// 4 folders named with your database name
// each properties file named with your table name under current database
./namespace1/table1.properties
./namespace1/table2.properties
...
./namepsace4/table16.properties
Q1. Can you confirm that I create properties files that contain the tables?
Q2. So your step 1 is to create 4 folders (1 for each namespace) and 1 properties file for each dataset/table - right? Does the tableX.properties file contain name/value pairs of the table's attributes and attribute values for a single record?
Q3. Can you please confirm that each tableX.properties file contains a name/value pair mapping of the attributes contained within the table and an example data record (e.g. so each attribute is mapped to a single record's value)?
Next question relates to the next bit of code:
// Step 2: create a config file to construct relationship of database and table
// assume that namespace1 / table1 is name of database / table
// (Example: the config file named with config.groovy)
database {
namespace1 = ["table1", "table2", "table3", "table4", "table5"]
namespace2 = ["table6", "table7", "table8", "table9", "table10"]
namespace3 = ["table11", "table12", "table13", "table14", "table15"]
namespace4 = ["table16", "table117", "table18", "table19", "table20"]
}
Q4. So I create a flat file entitled 'config.groovy' and the contents of the file will be as follows?
database {
namespace1 = ["table1", "table2", "table3", "table4", "table5"]
namespace2 = ["table6", "table7", "table8", "table9", "table10"]
namespace3 = ["table11", "table12", "table13", "table14", "table15"]
namespace4 = ["table16", "table117", "table18", "table19", "table20"]
}
re: the following code snippet:
// Step 3: set global property (in test case level)
testRunner.testCase.setPropertyValue("namespace_index", "0")
testRunner.testCase.setPropertyValue("table_index", "0")
Q5. Can you confirm that I create 2 custom properties on the test case. 1 entitled 'namespace_index' and set the value to '0' and 1 entitled 'table_index' and set the value to '0'??
re: the following code snippet:
// Step 4: Groovy step to load config file and set property
def index = context.expand('${#TestCase#namespace_index}').toInteger()
def config = new groovy.util.ConfigSlurper().parse(new File('./config.groovy').toURI().toURL())
def _map = config.database
Map.metaClass.takeAt = {int num ->
def keys = _map.keySet() as String[]
def key = keys[num]
["$key": _map.get(key)]
} //add a extension method to get a sub map
def map = config.database.takeAt(index) // return a submap
def namespace = map.keySet() as String[]
testRunner.testCase.setPropertyValue("namespace", namespace[0]) //namespace name
testRunner.testCase.setPropertyValue("namespaceMap", groovy.json.JsonOutput.toJson(map))
testRunner.testCase.setPropertyValue("namespaceCount", config.database.size().toString())
Q6. The bottom 3 lines set properties. Does this mean that I don't actually have to create the 3 properties on teh testcase and the script will do it for me?
On the 3rd line from the bottom it reads:
testRunner.testCase.setPropertyValue("namespace", namespace[0]) //namespace name
Q7. the commented //namespace name. Are you saying replace 'namespace[0]' with the namespace name so it reads 'geography[0]' if namespace is 'geography'?
re: the code snippet:
// Step 5: Groovy step to set property of table
def map = new groovy.json.JsonSlurper().parseText(context.expand('${#TestCase#namespaceMap}'))
def key = map.keySet()[0]
testRunner.testCase.setPropertyValue("tableCount", map.get(key).size().toString())
Q8. Can you confirm what this is actually doing please? I can see that you've expanded the namespaceMap property on the TestCase, but then you are setting a 2nd property entitled 'tablecount'. Can you please explain what this is doing?
re: the code snippet:
// Step 6: Groovy step to load properties file
def props = new Properties()
def map = new groovy.json.JsonSlurper().parseText(context.expand('${#TestCase#namespaceMap}'))
def index = context.expand('${#TestCase#table_index}').toInteger()
def tableName = map.entrySet()[0].value[index]
testRunner.testCase.setPropertyValue("dataset", tableName)
new File("./${tableName}.properties").withInputStream {
props.load(it)
}
Q9. I can see the comment indicates that this loads a properties file - can you confirm what this snippet actually does please? does it load tableX.properties files? The final 3 lines makes me think it does load a specific tableX.properties file - each test will only hit 1 specific namespace/table.?
The last 3 lines are as follows:
testRunner.testCase.setPropertyValue("dataset", tableName)
new File("./${tableName}.properties").withInputStream {
props.load(it)
Q10. There are 2 instances of 'tableName' - do I replace these with the actually dataset/tablenames?
re: the following code snippets at the end of 'step6'
//remove property
def teststep = testRunner.testCase.testSteps["Step7"]
teststep.getPropertyList().each{
if (! it.name.equalsIgnoreCase("namespace") || ! it.name.equalsIgnoreCase("dataset"))
teststep.testRequest.removeProperty(it.name)
}
//add property
for (p in props) { //set all properties into REST step
testRunner.testCase.testSteps["Step7"].testRequest.setPropertyValue(p.key, p.value)
}
Q11. Can you confirm what the '//remove property' snippet does please? yes obviously it removes a property - but why are you mentioning 'step7' in this?
Q12. Can you confirm 'what property' it is actually removing?
Q13. If I'm correct and the properties being added earlier at the tables' attributes (e.g. tableX.properties), does this mean that this is delete all the properties previously loaded in, earlier in steps?
Q14. Can you confirm what the '//add property' snippet does please?
yes I get that it adds a property - but I don't understand - surely the tableX.properties files have already been added in earlier in the script?
Q15. the line ' testRunner.testCase.testSteps["Step7"].testRequest.setPropertyValue(p.key, p.value)' - can you confirm what 'p.key' and 'p.value' actually mean please?
I have a dataset entitled 'certificate-commodity-type' and this sources data from the [mdm].[vw_CertNom_CommodityType] table (its SQLServer).
re: the code snippets for steps 7, 8 & 9
// Step 7: REST step to query
// parameterize "namespace" and "dataset"
namespace = ${#TestCase#namespace}
dataset = ${#TestCase#dataset}
// Step 8: Groovy step to control table loop
def table_index = context.expand('${#TestCase#table_index}').toInteger()
def tableCount = context.expand('${#TestCase#tableCount}').toInteger()
def namespace = context.expand('${#TestCase#namespace}')
if (table_index + 1 < tableCount) {
testRunner.testCase.setPropertyValue("table_index", (++table_index).toString())
testRunner.gotoStepByName("Step6")
} else {
log.info("Query all tables with parameters under $namespace")
}
// Step 9: Groovy step to control namespace loop
def namespace_index = context.expand('${#TestCase#namesapce_index}').toInteger()
def namespaceCount = context.expand('${#TestCase#namespaceCount}').toInteger()
if (namespace_index + 1 < namespaceCount) {
testRunner.testCase.setPropertyValue("namespace_index", (++namespace_index).toString())
testRunner.gotoStepByName("Step4")
} else {
log.info("Query all namespace done")
}
Q16. Can you confirm what these steps (steps7, 8 & 9) actually do please?
I am just trying to work out my test case object hierarchy using the steps you've provided. The place I'm using aren't java/groovy coders - so fortunately (or unfortunately - I always like to learn new things) - I need to create the tests using the OTB functionality and only extend the existing OTB functionality using groovy script when absolutely necessary. I suspect you've done all the work in groovy - so I think I need to grab what I can from what you've done but create the tests using the OTB functionality.
Thanks man,
richie
With this in mind I am thinking that
I initially the tableX.properties files for each of the datasets/tables I am querying.
I create a groovy.config file that indicates the different tables for each of the 4 namespaces.
I then have a groovy step containing step3, step4, step5, step6,
I then have a GET REST request grabbing certain attributes to build the Query parms on the GET.
I then have a follow up JDBC step to confirm the GET worked correctly (retrieves the data I expect)
Q17. Does that seem ok from your greater understanding?