1

I got a very specific scenario, where I'm inserting some data to the database(e.g. let's say 3 inserts and each one of them returns some ID) and based on a return value I want to create dynamically test cases for those return values E.g.

*** Variables ***
@{result}    ${EMPTY}

*** Test Cases ***
Some dummy sql inserts
    ${result}    Insert sql statements    dt1    dt2    dt3 #e.g. return ['123', '456', '789']

Verify some ids
    # NOPE, sorry i can't use [Template] because each iteration is not marked on a report as a "TEST" but as a "VAR"
    Verify if ids exist somewhere ${result} #This keyword execution should create another 3 test cases, one for each item from ${result} list

*** Keywords ***
Insert sql statement
    [Arguments]    @{data}
    Create List    ${result}
    FOR    ${elem}    IN    @{data}
        ${return_id}    SomeLib.Execute SQL    INSERT INTO some_table(some_id) VALUES (${elem})
        Append To List    ${result}    ${return_id}
    END
    [Return]    ${result}

Verify if ids exist somewhere
    [Arguments]    ${some_list_of_ids}
    FOR    ${id}    IN    @{some_list_of_ids}
        So some stuff on ${id}
    END

I was trying to figure out how to do that by reffering to robot API documentation but without any success. Can you please tell/advise if it's feasible, if so, than how can I achieve that.
So far I've figured out that there might be 2 ways of doing this:

  1. by creating a listener
  2. by creating own keyword

In both cases, I have to put the logic there, but can't figure out how to create test cases on-the-fly.
Help, please? :)

P.S. Some examples are more than welcome. Thanks in advance

1

2 Answers 2

3

There is a blog post with a answer for you: https://gerg.dev/2018/09/dynamically-create-test-cases-with-robot-framework/

As you suggested the solution is to create a listener so you can add tests dynamically. Just carefully read the post as there are some constrains as when you can and cannot create tests (during the execution process). Also, the post was for 3.x framework and for 4.x you need to make a tiny change in the class, by replacing: tc.keywords.create(name=kwname, args=args) with: tc.body.create_keyword(name=kwname, args=args).

Example on how to implement this:

demo.robot:

*** Settings ***
Library           DynamicTestCases.py

*** Test Cases ***
Create Dynamic Test Cases
    @{TestNamesList}    Create List    "Test 1"    "Test 2"    "Test 3"
    FOR    ${element}    IN    @{TestNamesList}
        Add Test Case    ${element}   Keyword To Execute
    END

*** Keywords ***
Keyword To Execute
    Log    This is executed for each test!

DynamicTestCases.py contents (basic copy from the url I posted + the changed line):

from __future__ import print_function
from robot.running.model import TestSuite


class DynamicTestCases(object):
    ROBOT_LISTENER_API_VERSION = 3
    ROBOT_LIBRARY_SCOPE = 'TEST SUITE'

    def __init__(self):
        self.ROBOT_LIBRARY_LISTENER = self
        self.current_suite = None

    def _start_suite(self, suite, result):
        # save current suite so that we can modify it later
        self.current_suite = suite

    def add_test_case(self, name, kwname, *args):
        """Adds a test case to the current suite

        'name' is the test case name
        'kwname' is the keyword to call
        '*args' are the arguments to pass to the keyword

        Example:
            add_test_case  Example Test Case  
            ...  log  hello, world  WARN
        """
        tc = self.current_suite.tests.create(name=name)
        #tc.keywords.create(name=kwname, args=args) #deprecated in 4.0
        tc.body.create_keyword(name=kwname, args=args)

# To get our class to load, the module needs to have a class
# with the same name of a module. This makes that happen:
globals()[__name__] = DynamicTestCases

This is a small example how to make it work. If for example you want to give a variable to the keyword, just add the argument:

*** Settings ***
Library           DynamicTestCases.py

*** Test Cases ***
Create Dynamic Test Cases
    @{TestNamesList}    Create List    "Test 1"    "Test 2"    "Test 3"
    FOR    ${element}    IN    @{TestNamesList}
        Add Test Case    ${element}   Keyword To Execute    ${element}
    END

*** Keywords ***
Keyword To Execute
    [Arguments]    ${variable}
    Log    The variable sent to the test was: ${variable}
Sign up to request clarification or add additional context in comments.

3 Comments

How do we pass tags to the Add Test Case method ? Also how can we use Suite Setup and TearDown in this scenario ?
You should open a new question for that.
@VidurOberoi I know you asked over a year ago, but I just came across this answer and provided my own showing Test Case Setup, Teardown, and Tags.
0

I wasn't sure if this should be a separate answer or an edit onto the existing approved one. I am using Robot Framework 5.0, and was able to add Setup, Teardown, and tags for the different test cases. Just in case another user comes along and wants to know how:

*** Settings ***
Documentation   Test cases for dynamic test cases.

# Library files
Library     DynamicTestCases.py

*** Keywords ***
Keyword To Execute
    [Arguments]    ${variable}
    Log    The variable sent to the test was: ${variable}

Setup keyword
    ${variable}    Set Variable    This is from the setup keyword
    Log  ${variable}
    Log To Console  ${variable}

Teardown keyword
    ${variable}    Set Variable    This is from the teardown keyword
    Log  ${variable}
    Log To Console  ${variable}

*** Test Cases ***
Create Dynamic Test Cases
    @{TestNamesList}    Create List    "Test 1"    "Test 2"    "Test 3"
    FOR    ${element}    IN    @{TestNamesList}
        ${testCase} =  AddTestCase  ${element}  dynamic_tag_${element}
        AddKeywordToTestCase  ${testCase}  Keyword To Execute  ${element}
        AddSetupToTestCase  ${testCase}  Setup keyword
        AddTeardownToTestCase  ${testCase}  Teardown keyword
    END

And the python library, DynamicTestCases.py:

# While this import does not seem necessary, it was useful in the python console.
from robot.running.model import TestSuite, TestCase, Keyword


class DynamicTestCases(object):
    ROBOT_LISTENER_API_VERSION = 3
    ROBOT_LIBRARY_SCOPE = 'TEST SUITE'

    def __init__(self):
        self.ROBOT_LIBRARY_LISTENER = self
        self.currentSuite = None

    def _start_suite(self, suite, result):
        # Don't change the name of this method. 
        # save current suite so that we can modify it later
        self.currentSuite = suite

    def AddTestCase(self, name, tags):
        """
        Adds a test case to the current suite

        Args:
            - name: is the test case name
            - tags: is a list of tags to add to the test case

        Returns: The test case that was added
        """
        testCase = self.currentSuite.tests.create(name=name, tags=tags)
        return testCase

    def AddKeywordToTestCase(self, testCase, keywordName, *args):
        """
        Adds a keyword to the given test case.

        Args:
            - testCase: The test case to add the keyword to
            - keywordName: The name of the keyword to add
            - *args: The arguments to pass to the keyword
        """
        testCase.body.create_keyword(name=keywordName, args=args)

    def AddSetupToTestCase(self, testCase: TestCase, keywordName: str, *args) -> Keyword:
        """
        Adds a setup keyword to the given test case.

        Args:
            - testCase: The test case to add the keyword to
            - keywordName: The name of the keyword to add
            - *args: The arguments to pass to the keyword
        """
        setupKeyword = testCase.body.create_keyword(name=keywordName, args=args, type='setup')
        testCase.setup = setupKeyword
        return setupKeyword

    def AddTeardownToTestCase(self, testCase: TestCase, keywordName: str, *args) -> Keyword:
        """
        Adds a teardown keyword to the given test case.

        Args:
            - testCase: The test case to add the keyword to
            - keywordName: The name of the keyword to add
            - *args: The arguments to pass to the keyword
        """
        teardownKeyword = testCase.body.create_keyword(name=keywordName, args=args, type='teardown')
        testCase.teardown = teardownKeyword
        return teardownKeyword

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.