如何在这个可嵌套的 For 循环中实现 Robot Framework 风格的变量?

2024-05-06

我在 Robot Framework 中见过很多“嵌套”For 循环,主要是创建一个内部带有 For 循环的关键字,然后在另一个 For 循环中调用该关键字。我使用 Python 2.7.13 制作了一个可嵌套的 For 循环,但因为它主要使用 Run keywords 语法,所以我无法使用 Robot Framework 风格的语法创建变量(例如${variable_name}= My Keyword)。根据记录,这是内置机器人框架库下的 Run keywords,它使用以下语法:

Run Keywords    Keyword1    arg11   arg12   AND     Keyword2    arg21   arg22

等价地,可以写成这样:

Run Keywords    Keyword1    arg11   arg12
...     AND     Keyword2    arg21   arg22

它通常不支持在其中创建变量。但是,我使用 Run keywords 作为可嵌套 For 循环的一部分。下面是该关键字的 Python 代码。

from robot.libraries.BuiltIn import BuiltIn

class Loops(object):
    def __init__(self):
        self.selenium_lib = BuiltIn().get_library_instance('ExtendedSelenium2Library')
        self.internal_variables = {}

    def for_loop(self, loop_type, start, end, index_var, *keywords):
        #   Format the keywords
        keywords = self._format_loop(*keywords)

        #   Clean out the internal variables from previous iterations
        self.internal_variables = {}

        #   This is the actual looping part
        for loop_iteration in range(int(start), int(end)):
            keyword_set = self._index_var_swap(loop_iteration, index_var, *keywords)
            #   If it's a one-keyword list with no arguments, then I can use the fastest possible keyword to run it
            if len(keyword_set) == 1:
                BuiltIn().run_keyword(keyword_set)
            #   If it's a one-keyword list with arguments, then I can use a faster keyword to run it
            elif 'AND' not in keyword_set:
                BuiltIn().run_keyword(*keyword_set)
            #   If it's a multiple-keyword list, then I have to use Run Keywords
            else:
                BuiltIn().run_keywords(*keyword_set)

    def _format_loop(self, *keywords):
        keywords = list(keywords)   # I need to format the keywords as a list.
        changed = False             # Whether or not I changed anything in the previous iteration.
        index = 0                   # The item index I'm at in the list of keywords
        del_list = []               # The list of items I need to delete
        swap_list = []              # The list of items i need to swap to AND for the use of Run Keywords
        #   For each argument
        for x in keywords:
            #   Format it to a string
            x = str(x)
            #   If the keyword in question happens to be one of the 'Assign Internal Variable' keywords, then I need
            #       to run it now, not later.
            #   By splitting it up, I add a little complexity to the code but speed up execution when you're just
            #       assigning a scalar variable as opposed to having to search through the next few items just to find
            #       what I know is just going to be the next one.
            #   So, if it's the simple assignment...
            if x.lower() == 'assign internal variable':
                #   ...run the Assign Internal Variable keyword with the two inputs
                BuiltIn().run_keyword(x, *keywords[int(index)+1:int(index)+3])
            #   If it's the more complicated variable...
            elif x.lower() == 'assign internal variable to keyword':
                #   ...initialize variables...
                deliminator_search = 0
                k_check = x
                #   ...search the next few keywords for a deliminator...
                while k_check != '\\' and k_check != '\\\\':
                    deliminator_search = deliminator_search + 1
                    k_check = keywords[int(index)+deliminator_search]
                #   ...and run the Assign Internal Variable to Keyword keyword with the found keyword
                BuiltIn().run_keyword(x, *keywords[int(index)+1:int(index)+2+deliminator_search])

            #   If the previous element was not changed...
            if not changed:
                #   If the current item is not the last one on the list...
                if x != len(keywords) - 1:
                    #   If the current item is a deliminator...
                    if x == '\\':
                        #   If the next item is a deliminator, delete this item and set changed to True
                        if keywords[int(index) + 1] == '\\':
                            del_list.append(index)
                            changed = True
                        #   If the next item is not a deliminator...
                        else:
                            #   If this isn't the first deliminator on the list, swap it to an 'AND'
                            if index != 0:
                                swap_list.append(index)
                                changed = True
                            #   If this deliminator is in position index=0, just delete it
                            else:
                                del_list.append(index)
                                changed = True
                    #   If the current element is not a deliminator, then I don't need to touch anything.
                #   If the current element is the last one, then I don't need to touch anything
            #   If the previous element was changed, then I don't need to "change" this one...
            elif changed:
                changed = False
                #   ...but if it's a deliminator then I do need to set it up for the inner for loop it means.
                if keywords[index] == '\\':
                    keywords[index] = '\\\\'
            index = index + 1   # Advance the index

        # These actually do the swapping and deleting
        for thing in swap_list:
            keywords[thing] = 'AND'
        del_list.reverse()
        for item in del_list:
            del keywords[item]

        # I also need to activate my variables for this set of keywords to run.
        keywords = self._activate_variables(*keywords)

        return keywords

    @staticmethod
    def _index_var_swap(loop_iteration, index_var, *keywords):
        #   Format the keywords as a list for iteration
        keywords = list(keywords)
        index = 0
        #   For every line in keywords
        for line in keywords:
            #   Replace all instances of the index_var in the string with the loop iteration as a string
            keywords[index] = str(line).replace(str(index_var), str(loop_iteration))
            index = index + 1
        return keywords

    def assign_internal_variable(self, variable_name, assignment):
        # This keyword works like any other keyword so that it can be activated by BuiltIn.run_keywords
        # The syntax for an internal variable is '{{varName}}' where varName can be anything
        self.internal_variables[variable_name] = assignment

    def assign_internal_variable_to_keyword(self, variable_name, keyword, *assignment):
        # This keyword works like any other keyword so that it can be activated by BuiltIn.run_keywords
        # The syntax for an internal variable is '{{varName}}' where varName can be anything
        self.internal_variables[variable_name] = BuiltIn.run_keyword(keyword, *assignment)

    def _activate_variables(self, *keywords):
        #   Initialize variables
        keywords = list(keywords)   # Cast keywords as a List
        index = 0                   # The index of the keyword I'm looking at

        #   For each keyword
        for keyword in keywords:
            keyword = str(keyword)  # Cast keyword as a String
            assignment = False      # Whether or not the found variable name is in a variable assignment
            for key in self.internal_variables.keys():
                key = str(key)      # Cast key as a String
                #   If I can find the key in the keyword and it's not an assignment...
                if keyword.find(key) > -1 and not assignment:
                    #   ...replace the text of the key in the keyword.
                    keywords[index] = keyword.replace(str(key), str(self.internal_variables[key]))
                #   If the keyword I'm looking at is an assignment...
                if keyword.lower() == 'assign internal variable'\
                        and keyword.lower() != 'assign internal variable to keyword':
                    #   ...then my next keyword is going to definitely be a known variable, so I don't want to touch it.
                    assignment = True
                #   If the keyword I'm looking at is not an assignment...
                else:
                    #   ...set assignment to False just in case the previous one happened to be an assignment.
                    assignment = False
            index = index + 1   # Advance the index
        return keywords     # Return the list of keywords to be used in the format loop

如您所见,我的解决方法是创建一个名为“分配内部变量”的新关键字及其伙伴“将内部变量分配给关键字”。然而,这对 Robot Framework 循环的语法的改变有点太显着了,不符合我的喜好,并且有些限制,因为内部变量与外部变量完全分开。该关键字在 Robot Framework 测试用例中的作用示例如下:

*** Variables ***
${gold_squadron} =  Gold
${red_squadron} =   Red

*** Test Cases ***
Test For Loop
    For Loop    IN RANGE    0   1   INDEX0
    ...     \\  For Loop    IN RANGE    1   6   INDEX1
    ...     \\  \\  Assign Internal Variable    {{standing_by}}     Standing By Red Leader
    ...     \\  \\  Run Keyword If      INDEX1 == 1     Log to Console  ${red_squadron} Leader Standing By
    ...     \\  \\  Run Keyword Unless  INDEX1 == 1     Log to Console  ${red_squadron} INDEX1 {{standing_by}}
    ...     \\  For Loop    IN RANGE    1   6   INDEX2
    ...     \\  \\  Assign Internal Variable    {{standing_by_2}}   Standing By Gold Leader
    ...     \\  \\  Run Keyword If      INDEX2 == 1     Log to Console  ${gold_squadron} Leader Standing By
    ...     \\  \\  Run Keyword Unless  INDEX2 == 1     Log to Console  ${gold_squadron} INDEX2 {{standing_by_2}}

假设您已正确将 Loops.py python 文件导入为库,该循环将按预期工作。然而,我正在寻找的语法类似于以下内容:

*** Variables ***
${gold_squadron} =  Gold
${red_squadron} =   Red

*** Test Cases ***
Test For Loop
    For Loop    IN RANGE    0   1   INDEX0
    ...     \\  For Loop    IN RANGE    1   6   INDEX1
    ...     \\  \\  {standing_by}=      Standing By Red Leader
    ...     \\  \\  Run Keyword If      INDEX1 == 1     Log to Console  ${red_squadron} Leader Standing By
    ...     \\  \\  Run Keyword Unless  INDEX1 == 1     Log to Console  ${red_squadron} INDEX1 {{standing_by}}
    ...     \\  For Loop    IN RANGE    1   6   INDEX2
    ...     \\  \\  {standing_by_2}=    Standing By Gold Leader
    ...     \\  \\  Run Keyword If      INDEX2 == 1     Log to Console  ${gold_squadron} Leader Standing By
    ...     \\  \\  Run Keyword Unless  INDEX2 == 1     Log to Console  ${gold_squadron} INDEX2 {{standing_by_2}}

对于那些不想深入研究 Robot Framework 基本代码的人(不推荐,这很痛苦),For 循环通常不能嵌套在 Robot Framework 中的原因是因为在基本层面上,关键字和 For 循环完全是两个不同的对象。某些关键字经过编码,以便它们可以使用其他关键字(例如“Run Keyword”),但 For 循环不是这样编码的。如果有人能够找到一种方法来改变我的 For 循环的语法,那么对于刚刚来自 Robot Framework 的人来说,这将使最终结果更加直观。

需要明确的是,如果示例中不清楚,我可以使用测试用例和 For 循环外部的 Robot Framework 变量。我问的是如何在 For 循环本身中创建它们。


我终于明白了。这是更正后的代码。

from robot.libraries.BuiltIn import BuiltIn


class Loops(object):

    def __init__(self):
        self.selenium_lib = BuiltIn().get_library_instance('ExtendedSelenium2Library')
        self.internal_variables = {}

    def for_loop(self, loop_type, start, end, index_var, *keywords):
        #   Format the keywords
    keywords = self._format_loop(*keywords)

        #   Clean out the internal variables from previous iterations
        self.internal_variables = {}

        #   This is the actual looping part
        for loop_iteration in range(int(start), int(end)):
            keyword_set = self._index_var_swap(loop_iteration, index_var, *keywords)
            #   If it's a one-keyword list with no arguments, then I can use the fastest possible keyword to run it
            if len(keyword_set) == 1:
                BuiltIn().run_keyword(keyword_set)
            #   If it's a one-keyword list with arguments, then I can use a faster keyword to run it
            elif 'AND' not in keyword_set:
                BuiltIn().run_keyword(*keyword_set)
            #   If it's a multiple-keyword list, then I have to use Run Keywords
            else:
                BuiltIn().run_keywords(*keyword_set)

    def _format_loop(self, *keywords):
        keywords = list(keywords)   # I need to format the keywords as a list.
        changed = False             # Whether or not I changed anything in the previous iteration.
        index = 0                   # The item index I'm at in the list of keywords
        del_list = []               # The list of items I need to delete
        swap_list = []              # The list of items i need to swap to AND for the use of Run Keywords

        def _new_variable():
            #   Default to a variable declaration of 'name='
            t = 1
            #   If my variable declaration is 'name ='
            if x[-2:] == ' =':
                #   Reflect that in the value of t
                t = 2

            #   Count the number of cells until the end of the line
            length = self._deliminator_search(index, x, *keywords)

            if length == 3 and not BuiltIn().run_keyword_and_return_status("Keyword Should Exist", keywords[index + 1]):
                #   If I'm assigning a value to my variable
                self._assign_internal_variable(x[:-t], str(keywords[index + 1]))

            elif length == 3:
                #   If I'm assigning the result of a keyword without any arguments
                self._assign_internal_variable_to_keyword(keywords[index][:-t], str(keywords[index + 1]))
            else:
                #   If I'm assigning the result of a keyword with arguments
                self._assign_internal_variable_to_keyword(keywords[index][:-t], keywords[index + 1],
                                                          keywords[index + 2:index + (length - 1)])

            #   Add the variable declaration code to the delete list.
            del_list.extend(range(index - 1, index + length))

        #   For each argument
        for x in keywords:
            #   Format it to a string
            x = str(x)
            #   Assign new variables
            if x[-1:] == '=':
                _new_variable()

            #   If the previous element was not changed...
            if not changed:
                #   If the current item is not the last one on the list...
                if x != len(keywords) - 1:
                    #   If the current item is a deliminator...
                    if x == '\\':
                        #   If the next item is a deliminator, delete this item and set changed to True
                        if keywords[int(index) + 1] == '\\':
                            del_list.append(index)
                            changed = True
                        #   If the next item is not a deliminator...
                        else:
                            #   If this isn't the first deliminator on the list, swap it to an 'AND'
                            if index != 0:
                                swap_list.append(index)
                                changed = True
                            #   If this deliminator is in position index=0, just delete it
                            else:
                                del_list.append(index)
                                changed = True
                    #   If the current element is not a deliminator, then I don't need to touch anything.
                #   If the current element is the last one, then I don't need to touch anything
            #   If the previous element was changed, then I don't need to "change" this one...
            elif changed:
                changed = False
                #   ...but if it's a deliminator then I do need to set it up for the inner for loop it means.
                if keywords[index] == '\\':
                    keywords[index] = keywords[index]*2
            index = index + 1   # Advance the index

        # These actually do the swapping and deleting
        for thing in swap_list:
            keywords[thing] = 'AND'
        del_list.reverse()
        for item in del_list:
            del keywords[item]

        # I also need to activate my variables for this set of keywords to run.
        keywords = self._activate_variables(*keywords)

        return keywords

    @staticmethod
    def _index_var_swap(loop_iteration, index_var, *keywords):
        #   Format the keywords as a list for iteration
        keywords = list(keywords)
        index = 0
        #   For every line in keywords
        for line in keywords:
            #   Replace all instances of the index_var in the string with the loop iteration as a string
            keywords[index] = str(line).replace(str(index_var), str(loop_iteration))
            index = index + 1
        return keywords

    def _assign_internal_variable(self, variable_name, assignment):
        # This keyword works like any other keyword so that it can be activated by BuiltIn.run_keywords
        self.internal_variables[variable_name] = assignment

    def _assign_internal_variable_to_keyword(self, variable_name, keyword, *arguments):
        # Uses assign_internal_variable to simplify code.
        # BuiltIn().log_to_console(BuiltIn().run_keyword(keyword, *arguments))
        self._assign_internal_variable(variable_name, BuiltIn().run_keyword(keyword, *arguments))
        # BuiltIn().log_to_console(self.internal_variables[variable_name])

    def _activate_variables(self, *keywords):
        #   Initialize variables
        keywords = list(keywords)   # Cast keywords as a List
        index = 0                   # The index of the keyword I'm looking at

        #   For each keyword
        for keyword in keywords:
            keyword = str(keyword)  # Cast keyword as a String
            assignment = False      # Whether or not the found variable name is in a variable assignment
            for key in self.internal_variables.keys():
                key = str(key)      # Cast key as a String
                #   If I can find the key in the keyword and it's not an assignment...
                if keyword.find(key) > -1 and not assignment:
                    #   ...replace the text of the key in the keyword.
                    keywords[index] = keyword.replace(str(key), str(self.internal_variables[key]))
                #   If the keyword I'm looking at is an assignment...
                if keyword.lower() == 'assign internal variable'\
                        and keyword.lower() != 'assign internal variable to keyword':
                    #   ...then my next keyword is going to definitely be a known variable, so I don't want to touch it.
                    assignment = True
                #   If the keyword I'm looking at is not an assignment...
                else:
                    #   ...set assignment to False just in case the previous one happened to be an assignment.
                    assignment = False
            index = index + 1   # Advance the index
            #   NOTE: Replaces the EXACT text, even if it's in another keyword or variable, so be very careful
        return keywords     # Return the list of keywords to be used in the format loop

    @staticmethod
    def _deliminator_search(start, keyword, *keywords):
        index = 0
        while keyword != '\\' and keyword != '\\\\':
            keyword = keywords[int(start) + index]
            index = index + 1
        return index

这是测试它的代码:

*** Variables ***
${blue_squadron} =      Blue
${gold_squadron} =      Gold
${green_squadron} =     Green
${red_squadron} =       Red

*** Test Cases ***
Test For Loop
    For Loop    IN RANGE    0   1   INDEX0
    ...     \\  For Loop    IN RANGE    1   6   INDEX1
    ...     \\  \\  {standing_by}=      standing by
    ...     \\  \\  Run Keyword If      INDEX1 == 1     Log to Console  This is ${red_squadron} Leader standing by
    ...     \\  \\  Run Keyword Unless  INDEX1 == 1     Log to Console  ${red_squadron} INDEX1 {standing_by}
    ...     \\  For Loop    IN RANGE    1   6   INDEX2
    ...     \\  \\  standing_by_2 =     standing by
    ...     \\  \\  Run Keyword If      INDEX2 == 1     Log to Console  This is ${gold_squadron} Leader standing by
    ...     \\  \\  Run Keyword Unless  INDEX2 == 1     Log to Console  ${gold_squadron} INDEX2 standing_by_2
    ...     \\  For Loop    IN RANGE    1   6   INDEX3
    ...     \\  \\  standing_by_3=      Get Blue Squadron
    ...     \\  \\  Run Keyword If      INDEX3 == 1     Log to Console  This is ${blue_squadron} Leader standing by
    ...     \\  \\  Run Keyword Unless  INDEX3 == 1     Log to Console  ${blue_squadron} INDEX3 standing_by_3
    ...     \\  For Loop    IN RANGE    1   6   INDEX4
    ...     \\  \\  standing_by_4 =     Get Green Squadron   null input
    ...     \\  \\  Run Keyword If      INDEX4 == 1     Log to Console  This is ${green_squadron} Leader standing by
    ...     \\  \\  Run Keyword Unless  INDEX4 == 1     Log to Console  ${green_squadron} INDEX4 standing_by_4

*** Keywords ***
Get Blue Squadron
    [Return]    standing by

Get Green Squadron
    [Arguments]     ${null_input}
    [Return]        standing by

为了对此解决方案添加一些说明,我不需要变量采用特定格式。如果您希望进一步准确地明确变量的含义,则可以这样做,但这不是必需的。我宁愿在这种程序中留下更多的选择。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何在这个可嵌套的 For 循环中实现 Robot Framework 风格的变量? 的相关文章

随机推荐

  • 调用事件,h(args) 与 EventName?.Invoke()

    我总是这样调用事件 void onSomeEvent string someArg var h this EventName if h null h this new MyEventArgs someArg 今天 VS 2015 告诉我这可
  • 为什么 getSession() 在短时间内间隔的后续请求中不返回相同的会话?

    我正在发送一个 getJSON HTTP GET 请求两次 使用不同的数据 一次又一次 假设我们有 request1 和 request2 我可以在 FF 和 Chrome 的开发者工具中看到我有相同的cookie JSESSIONID F
  • 使用 leaflet.js 在点周围添加设定大小的正方形多边形

    有点奇怪 希望有人能帮忙 在传单中 一旦用户输入了纬度 经度并向地图添加了一个点 我希望能够在该点周围添加一个 10 公里的正方形 我尝试四处寻找计算方法来找到 x 公里外的正方形角点 但没有挖出任何东西 但肯定有更简单的方法 有人有想法吗
  • 如何在 Django 中创建多选框?

    我正在尝试创建多选框字段来自姜戈选择 2 https github com applegrew django select2库如下图所示 我使用了下一个代码 但它返回简单的选择多个小部件 我想我忘了补充一些东西 我的错误在哪里 有人可以告诉
  • 使用 stringstreams 将字符串转换为 __uint128_t

    我正在尝试从字符串中提取不同类型的数据 void readHeader char buf BUFFSIZE std istringstream hdr buf uint128 t id client hdr gt gt id client
  • C++:初始化结构体并设置函数指针

    我正在尝试使用函数指针初始化结构 但是除非使用全局函数完成 否则我很难这样做 以下代码有效 float tester float v return 2 0f v struct MyClass Example typedef float My
  • 为什么 Visual Studio 2019 不会运行我的单元测试?

    我在 VS2019 中看到 NUnit 测试的一些非常奇怪的行为 而相同的解决方案在 VS2017 中运行良好 我的脑海里有几个 NUnit 测试项目 在安装了 NUnit Runner 扩展的 VS2017 中 我可以在 测试资源管理器
  • 使用 java 执行 Matlab 函数

    我正在编写一个应用程序 它使用 matlab 进行图像处理 然后使用 Java 接口显示结果 由于某些原因 我必须同时使用 Java 和 Matlab 如何在java中使用matlab函数 如何创建和访问界面 MATLAB控制 http m
  • 有没有办法通过 Outlook API 获取建议的联系人?

    我目前正在开发一个应用程序来获取我的 Microsoft 帐户中的联系人 问题是 与 Google 不同 当我向新联系人发送电子邮件或从新联系人接收电子邮件时 该电子邮件不会复制到 我的联系人 中 因此我无法通过该电子邮件https out
  • 如何修复 Visual Studio Code 终端中的“分段错误”错误?

    在 Windows 10 上 我安装了 Visual Studio Code 当我打开终端 Git Bash 并输入less watch compiler 我收到错误 分段故障 但是如果我转到 Git Bash 终端本身 在 Visual
  • 重新创建 Siri 按钮发光动画

    有没有办法复制 Siri 按钮发光动画 它看起来绝对华丽 但我现在不知道如何开始 是否有在线预格式化的旋转PNG 或者是用CoreAnimation完成的 我相信 Siri 动画是用 CAEmitterLayer 和 CAEmitterCe
  • 渲染脚本渲染在Android上比OpenGL渲染慢很多

    背景 我想根据Android相机应用程序的代码添加实时滤镜 但Android相机应用程序的架构是基于OpenGL ES 1 x 我需要使用着色器来自定义我们的过滤器实现 然而 将相机应用程序更新到OpenGL ES 2 0太困难了 然后我必
  • 查询不可更新

    我正在尝试使用 BE SQL Server 2012 Express 中的记录更新本地 Access 2007 表 我的步骤在这里 SQL Server中存在带有4个参数的存储过程来获取所需的记录 Access VBA中有调用SP并进行临时
  • BitBucket+Jenkins:仅在特定分支更改时触发构建

    以下是该问题的据称解决方案 尽管它看起来确实是一种解决方法 而不是最终的解决方案 有没有一种方法 通过作业配置或 bitbucket 挂钩配置 我可以将作业设置为仅在推送到特定分支时运行构建 是否可以仅从一个特定分支触发 Jenkins h
  • PySide2/QML 填充 Gridview 模型/委托并为其设置动画

    我是 QML 的新手 正在寻求以下几点帮助 如何基于 TextField 输入 如 Regex 通过 PySide2 过滤 Gridview 模型中的 QAbstractListModel 数据 标题 如何在鼠标悬停时为 Gridview
  • Spark:Aggregator和UDAF有什么区别?

    在Spark的文档中 Aggregator 抽象类聚合器 IN BUF OUT 扩展可序列化 用户定义聚合的基类 可以是 在数据集操作中用于获取组中的所有元素并 将它们减少到单个值 用户定义的聚合函数是 抽象类 UserDefinedAgg
  • JavaScript:发送 POST,重定向到响应

    我有一个带有 onclick 的图像 当单击事件触发时 我想发送 HTTP POST 并将 window location 重定向到 POST 的响应 我怎样才能做到这一点 只需将按钮绑定到表单元素的提交方法 重定向就会自然发生
  • 如何将NSDate转换为unix时间戳iphone sdk?

    如何转换NSDate转换为 Unix 时间戳 我读过很多相反的帖子 但我没有找到与我的问题相关的任何内容 我相信这是您正在寻找的 NSDate 选择器 NSTimeInterval timeIntervalSince1970
  • Struts 2 中的 Java 应用程序可以管理多少个会话?

    我正在开发事务管理应用程序 并且正在使用 Struts2 我在内部使用了一个会话来设置和获取值 例如 ActionContext getContext getSession put string string 在应用程序中使用这样的会话是否
  • 如何在这个可嵌套的 For 循环中实现 Robot Framework 风格的变量?

    我在 Robot Framework 中见过很多 嵌套 For 循环 主要是创建一个内部带有 For 循环的关键字 然后在另一个 For 循环中调用该关键字 我使用 Python 2 7 13 制作了一个可嵌套的 For 循环 但因为它主要