Forum Discussion

Nullius's avatar
Nullius
Occasional Contributor
13 years ago

Clone a step with Groovy script

Hi there.

Ive been Groovy-scripting a lot these days and learning a lot.
However, when I try to clone a JDBC TestStep, it always asks me (via the rename dialog) to provide a new name, even when I specify a unique name in the method.
Is this a bug or am I doing something wrong?

Both testCase.cloneStep(step, name) as testStep.clone(case, name) show the same behavior.
def newStep = ResultSetTemplateStep.clone(testRunner.testCase, "uniquenewname")
def newStep = testRunner.testCase.cloneStep(ResultSetTemplateStep, "uniquenewname")
  • Nullius's avatar
    Nullius
    Occasional Contributor
    When cloning to another TestCase, I even noticed that the cloned TestStep receives the same name as the original TestStep.
    Its name hasn't been changed!

    A workaround is to
    - Create a temporary TestCase
    - Clone the original TestStep(s) to the new TestCase
    - Change the name of the the cloned TestStep(s)
    - Clone the renamed TestStep(s) to the original TestCase
    - Remove the temporary TestCase

    The following code creates new JDBC TestSteps for each SQL file in a specified directory (ResultSetsPath) based on a template step (ResultSetTemplateStep)
    It then updates the query from the new step to the query in the SQL file.
    //
    // For every SQL file in the provided ResultStepsPath, clone the template TestStep with the filename as TestStep name
    def tmpCloneTestCase = testRunner.testCase.testSuite.addNewTestCase("TemporaryCloneTestCase")
    new File(ResultSetsPath).eachFile
    {
    // Ignore files that do not end in .sql
    if (it.name.endsWith(".sql"))
    {
    // Make sure we can read the file
    assert it.canRead()

    // Get the new name for the testStep
    String newStepName = it.name[0..-5]

    // Clone the template TestStep
    def newStep = ResultSetTemplateStep.clone(tmpCloneTestCase, newStepName)
    newStep.setName(newStepName)

    // Update the query of the TestStep with the contents of the file
    newStep.setQuery(it.text)

    // Now clone the temporary testStep to the original testCase
    newStep.clone(testRunner.testCase, newStepName)

    // Remove the temporary testStep
    tmpCloneTestCase.removeTestStep(newStep)
    }
    }
    testRunner.testCase.testSuite.removeTestCase(tmpCloneTestCase)

    // Save the project
    assert testRunner.testCase.testSuite.project.save() == true


    However,it feels kinda nasty we have to do this :-)

    Tnx!
  • Nullius's avatar
    Nullius
    Occasional Contributor
    If someone might be interested, here is the complete code of the script.
    It deletes every JDBC testStep in the current testCase that has not 'eemplate' in its name.
    Then it creates JDBC steps based on a specified template with the correct queries.
    The new steps receive the same name as their corresponding SQL filenames (with .sql removed)

    // Define the path where all SQL queries are stored
    String ResultSetsPath = "PATH_TO_DIRECTORY_CONTAINING_SQL_FILES"
    String ResultSetTemplateStepName = "ResultStepTemplate"

    // Try to get the template JDBC TestStep
    def ResultSetTemplateStep = testRunner.testCase.getTestStepByName(ResultSetTemplateStepName)
    // Make sure it's a valid JDBC TestStep
    assert ResultSetTemplateStep != null
    assert ResultSetTemplateStep.getClass().name.contains("JdbcRequestTestStep")

    // Delete every JDBC TestStep in the current TestCase except the template steps
    int TestStepCount = testRunner.testCase.getTestStepCount()
    def TestStepsToDelete = []
    for (int i = 0; i < TestStepCount; i++)
    {
    // Get the current TestStep
    def curTestStep = testRunner.testCase.getTestStepAt(i)

    // Only delete JDBC steps
    if (!curTestStep.getClass().name.contains("JdbcRequestTestStep"))
    continue

    // Don't delete template JDBC steps
    if (curTestStep.name == ResultSetTemplateStepName || curTestStep.name.toLowerCase().contains("template"))
    continue

    TestStepsToDelete.add(i)
    }
    int TestStepsToDeleteCount = TestStepsToDelete.size
    for (int i = TestStepsToDeleteCount - 1; i >= 0; i--)
    testRunner.testCase.removeTestStep(testRunner.testCase.getTestStepAt(TestStepsToDelete[i]))

    //
    // For every SQL file in the provided ResultStepsPath, clone the template TestStep with the filename as TestStep name
    //
    // Because of a bug in the Clone methods, we have to:
    // - Create a temporary TestCase
    // - Clone the original TestStep(s) to the new TestCase
    // - Change the name of the the cloned TestStep(s)
    // - Clone the renamed TestStep(s) to the original TestCase
    // - Remove the temporary TestCase
    def tmpCloneTestCase = testRunner.testCase.testSuite.addNewTestCase("TemporaryCloneTestCase")
    new File(ResultSetsPath).eachFile
    {
    // Ignore files that do not end in .sql
    if (it.name.endsWith(".sql"))
    {
    // Make sure we can read the file
    assert it.canRead()

    // Get the new name for the testStep
    String newStepName = it.name[0..-5]

    // Clone the template TestStep
    def newStep = ResultSetTemplateStep.clone(tmpCloneTestCase, newStepName)
    newStep.setName(newStepName)

    // Update the query of the TestStep with the contents of the file
    newStep.setQuery(it.text)

    // Now clone the temporary testStep to the original testCase
    newStep.clone(testRunner.testCase, newStepName)

    // Remove the temporary testStep
    tmpCloneTestCase.removeTestStep(newStep)
    }
    }
    testRunner.testCase.testSuite.removeTestCase(tmpCloneTestCase)

    // Save the project
    assert testRunner.testCase.testSuite.project.save() == true
    • sachin-chanchal's avatar
      sachin-chanchal
      Occasional Contributor

      Will this above shown solution work for HTTP type test step as well instead of JDBC type test?