自动化测试框架Robot Framework入门

news2024/10/6 1:57:31

什么是RF

RF是一个基于 Python 的、可扩展的关键字驱动的自动化 验收测试框架、验收测试驱动开发 (ATDD)、 行为驱动开发 (BDD) 和机器人流程自动化 (RPA)。它 可用于分布式、异构环境,其中自动化 需要使用不同的技术和接口。

该框架周围有一个丰富的生态系统,由各种通用 作为单独项目开发的库和工具。查看更多 有关机器人框架和生态系统的信息,请参阅 http://robotframework.org。

为什么使用RF?

  • 支持易于使用的表格语法,以便在统一的环境中创建测试用例 道路。
  • 提供从 现有关键字。
  • 以 HTML 格式提供易于阅读的结果报告和日志。
  • 独立于平台和应用程序。
  • 提供用于创建自定义测试库的简单库 API 可以使用 Python 本地实现。
  • 提供命令行界面和基于 XML 的输出文件 集成到现有的构建基础架构中(持续集成 系统)。
  • 为测试 Web 应用程序、rest API、移动应用程序提供支持 运行进程,通过 Telnet 或 SSH 连接到远程系统等。
  • 支持创建数据驱动的测试用例。
  • 内置对变量的支持,特别适用于测试 不同的环境。
  • 提供标记以对要执行的测试用例进行分类和选择。
  • 实现与源代码管理的轻松集成:测试套件只是文件 以及可以使用生产代码进行版本控制的目录。
  • 提供测试用例和测试套件级别的设置和拆卸。
  • 模块化架构支持创建测试,甚至对于具有 几种不同的接口。

环境准备

  1. 安装python
  2. 虚拟环境中安装robotframework
cd C:\projects
mkdir MyProject
cd MyProject
python -m venv .venv
.venv\Scripts\activate.bat
pip install robotframework
robot --version

  3.pycharm安装插件

Robot Framework Language Server

 为 Robot Framework 添加调试配置以运行当前测试套件

添加 Robot Framework 的调试配置以运行当前测试用例(通过选定的文本)

4、安装库文件

pip install --upgrade robotframework-seleniumlibrary

5、下载浏览器驱动,放置python路径的Scripts目录下。 

Library 

关于射频指南 |机器人框架 (robotframework.org)

使用RF需要使用Library,常用的第三方库如下:

在web浏览器中进行web应用程序测试可以使用的库是

  • Selenium Library 在内部使用流行的 Selenium 工具的 Web 测试库
  • Browser Library 由 Playwright 提供支持。以速度、可靠性和可见性为目标。

web service和restful API可以用的库是

  • Requests Library 一个机器人框架库,旨在通过包装众所周知的 Python 请求库来提供 HTTP API 测试功能
Appium Library Android and iOS UI测试,内部使用appium. 
Database Library 基于python的数据库测试
标准库 Logging, File Handling, Operating System, Process, String, and XML and much more

标准库

RF标准库是Robot Framework(RF)在安装完成后自带的库。这些库无需额外安装,可以直接在RF中使用。其中,Builtin库是一个常用关键字库,它包含经常需要使用的关键字,无需导入即可直接使用。除Builtin库外,其他标准库如Dialogs、Collections、OperatingSystem、Remote、Screenshot和Process等,都需要通过import导入才能使用。这些库提供了丰富的功能,例如暂停测试执行和从用户获取输入、处理Python列表和字典、执行各种操作系统相关的任务、远程库接口的支持、捕获和存储桌面截图以及管理系统中运行的过程等。

标准库 |机器人框架 (robotframework.org)

selenium Library

https://robotframework.org/SeleniumLibrary/SeleniumLibrary.html

selenium Library是RF的一个web测试库,内部使用selenium。

pip install --upgrade robotframework-seleniumlibrary

新建一个test.robot文件,robot是RF测试用例文件的后缀。

 首先在Settings导入SeleniumLibrary,然后在TestCase里写测试用例,如下例的Open Browser都是SeleniumLibrary提供的关键字,如下用例打开edge浏览器,输入框中输入关键字,并点击百度一下按钮,最后关闭浏览器。

*** Settings ***
Library     SeleniumLibrary

*** Test Cases ***
Search keywords in baidu

    Open Browser    url=https://www.baidu.com    browser=edge
    Input Text    //input[@id="kw"]    周杰伦
    Click Element    //input[@id="su"]
    Sleep    5
    Close Browser

导入Library失败

 原因是python环境变量错了,电脑上有3.7的和3.8的,我用的3.8的,但是没有把3.8设置为环境变了

输入关键字,会有提示如图Input password,会提示让输入定位和密码。

Browser Library

这个库是由playwright支持的

Browser Library | ROBOT FRAMEWORK

pip install robotframework-browser

rfbrowser init 

Installing playwright...
Installing playwright-chromium...
Installing playwright-firefox...
Installing playwright-webkit...
Done!

 Requests Library

这个库可以进行API测试,基于Python的Requests

pip install robotframework-requests

*** Settings ***
Library               RequestsLibrary

*** Test Cases ***

Quick Get Request Test
    ${response}=    GET  https://www.google.com

Quick Get Request With Parameters Test
    ${response}=    GET  https://www.google.com/search  params=query=ciao  expected_status=200

Quick Get A JSON Body Test
    ${response}=    GET  https://jsonplaceholder.typicode.com/posts/1
    Should Be Equal As Strings    1  ${response.json()}[id]

运行用例

方法一:使用配置的run testsuite按钮。

方法二:

点击在测试文件里左侧的按钮,这里的按钮其实也是插件配置出的按钮。

运行后可以看到测试结果,并生成了html格式的测试报告。

测试报告

项目结构

Test Suites 可以组织在一个或多个robot文件里,可以放在tests/文件夹下

resources 资源文件,里面存放的是可重复使用的keywords,可以是robot文件或py文件,可以放在resources文件夹下,如

common.resource -存放一般的关键字,如Login/Logout,导航

search.robot,跟查询有关的关键字

util.py python相关的关键字

libraries 常用的python关键字库,可以存放在libraries/文件夹下,某些项目会区分libraries和resources,有些不会。

my_project
├── tests
│   ├── suiteA.robot
│   ├── suiteB.robot
│   ├── ...
│   
├── resources
│   ├── common.resource
│   ├── some_other.resource
│   ├── custom_library.py
│   ├── variables.py
│   ├── ...

├── .gitlab-ci.yml
├── .gitignore
├── README.md
├── requirements.txt

执行用例

$ robot --pythonpath . tests 

一些项目还会有data文件,存放测试数据

my_project
├── tests
│   ├── authentication
│   │   ├── login.robot
│   │   ├── ...
│   │
│   ├── master-data
│   │   ├── customers.robot
│   │   ├── products.robot
│   │   ├── ...
│   │
│   ├── order
│   │   ├── order_creation.robot
│   │   ├── order_processing.robot
│   │   ├── ...
│   
├── resources
│   ├── common.resource
│   ├── search.resource
│   ├── master-data
│   │   ├── customers.resource
│   │   ├── products.resource
│   │   ├── ...
│   │
│   ├── ...

├── data
│   ├── master-data
│   │   ├── customers.py
│   │   ├── products.py
│   │   ├── ...
│   │
│   ├── order
│   │   ├── order_creation.yaml
│   │   ├── order_processing.yaml
│   │   ├── ...

├── .gitlab-ci.yml
├── .gitignore
├── README.md
├── requirements.txt 

示例 项目

RF官网提供了几个例子

Examples Overview | ROBOT FRAMEWORK

Vehicle Insurance App

根据下面的例子可以看到,RF的测试文件,包含

*** Settings ***-用来引入库和资源

*** Variables *** 用来指定变量,在测试用例中可使用${}来引用。

*** Test Cases *** 下面为用例,其中用例Create Quote for Car下包含的关键字,都是在*** Keywords ***中自定义的。

*** Keywords *** 定义关键字,关键字下调用Browser库文件中的关键字

  1. [Arguments] firstname=Max{lastname}=Mustermann

    • 这行定义了这个关键字需要的参数及其默认值。在这个例子中,Enter Insurant Data 关键字接受两个参数:firstname 和 lastname。如果调用这个关键字时没有提供这些参数的值,那么它们将分别默认为 Max 和 Mustermann
*** Settings ***
Library    Browser

*** Variables ***
${BROWSER}    chromium
${HEADLESS}    false

*** Test Cases ***
Create Quote for Car
    Open Insurance Application
    Enter Vehicle Data for Automobile
    Enter Insurant Data
    Enter Product Data
    Select Price Option
    Send Quote
    End Test

*** Keywords ***
Open Insurance Application
    New Browser    browser=${BROWSER}    headless=${HEADLESS}
    New Context    locale=en-GB
    New Page    http://sampleapp.tricentis.com/

Enter Vehicle Data for Automobile
    Click    div.main-navigation >> "Automobile"
    Select Options By    id=make    text    Audi
    Fill Text    id=engineperformance    110
    Fill Text    id=dateofmanufacture    06/12/1980
    Select Options By    id=numberofseats    text    5
    Select Options By    id=fuel    text    Petrol    
    Fill Text    id=listprice    30000
    Fill Text    id=licenseplatenumber    DMK1234
    Fill Text    id=annualmileage   10000 
    Click    section[style="display: block;"] >> text=Next »

Enter Insurant Data
    [Arguments]    ${firstname}=Max    ${lastname}=Mustermann
    Fill Text    id=firstname    Max
    Fill Text    id=lastname    Mustermann
    Fill Text    id=birthdate    01/31/1980
    Check Checkbox    *css=label >> id=gendermale
    Fill Text    id=streetaddress    Test Street
    Select Options By    id=country    text    Germany
    Fill Text    id=zipcode    40123
    Fill Text    id=city    Essen
    Select Options By    id=occupation    text    Employee
    Click    text=Cliff Diving
    Click    section[style="display: block;"] >> text=Next »

Enter Product Data
    Fill Text    id=startdate    06/01/2023
    Select Options By    id=insurancesum    text    7.000.000,00
    Select Options By    id=meritrating    text    Bonus 1
    Select Options By    id=damageinsurance    text    No Coverage
    Check Checkbox    *css=label >> id=EuroProtection
    Select Options By    id=courtesycar    text    Yes
    Click    section[style="display: block;"] >> text=Next »

Select Price Option
    [Arguments]    ${price_option}=Silver
    Click    *css=label >> css=[value=${price_option}]
    Click    section[style="display: block;"] >> text=Next »

Send Quote
    Fill Text    "E-Mail" >> .. >> input    max.mustermann@example.com
    Fill Text    "Phone" >> .. >> input    0049201123456
    Fill Text    "Username" >> .. >> input    max.mustermann
    Fill Text    "Password" >> .. >> input    SecretPassword123!
    Fill Text    "Confirm Password" >> .. >> input    SecretPassword123!
    Fill Text    "Comments" >> .. >> textarea    Some comments
    ${promise}=     Promise To    Wait For Response     matcher=http://sampleapp.tricentis.com/101/tcpdf/pdfs/quote.php     timeout=10
    Click    "« Send »"
    ${body}=    Wait For    ${promise}
    Log    ${body}[status]
    Log    ${body}[body]
    Wait For Elements State    "Sending e-mail success!"
    Click    "OK"

End Test
    Close Context
    Close Browser

WFA login

这个例子中引用了py文件中的函数

另外在Settings里可以使用Suite Setup和Suite Teardown进行test suite级别的测试数据准备和清理

Test Setup和Suite Teardown进行test级别前置和后置准备。

*** Settings ***
Library    Browser
Library    totp.py
Suite Setup    New Browser    browser=${BROWSER}    headless=${HEADLESS}
Test Setup    New Context
Test Teardown    Close Context
Suite Teardown    Close Browser

*** Variables ***
${BROWSER}    chromium
${HEADLESS}    False

*** Test Cases ***
Login with MFA
    New Page    https://seleniumbase.io/realworld/login
    Fill Text    id=username    demo_user
    Fill Text    id=password    secret_pass
    ${totp}    Get Totp    GAXG2MTEOR3DMMDG
    Fill Text    id=totpcode     ${totp}
    Click    "Sign in"
    Get Text  h1  ==  Welcome!

import pyotp

def get_totp(secret):
    totp = pyotp.TOTP(secret)
    return totp.now()

Restful Booker

*** Settings ***
Library    RequestsLibrary
Library    Collections
Suite Setup    Authenticate as Admin

*** Test Cases ***
Get Bookings from Restful Booker
    ${body}    Create Dictionary    firstname=John
    ${response}    GET    https://restful-booker.herokuapp.com/booking    ${body}
    Status Should Be    200
    Log List    ${response.json()}
    FOR  ${booking}  IN  @{response.json()}
        ${response}    GET    https://restful-booker.herokuapp.com/booking/${booking}[bookingid]
        TRY
            Log    ${response.json()}
        EXCEPT
            Log    Cannot retrieve JSON due to invalid data
        END
    END

Create a Booking at Restful Booker
    ${booking_dates}    Create Dictionary    checkin=2022-12-31    checkout=2023-01-01
    ${body}    Create Dictionary    firstname=Hans    lastname=Gruber    totalprice=200    depositpaid=false    bookingdates=${booking_dates}
    ${response}    POST    url=https://restful-booker.herokuapp.com/booking    json=${body}
    ${id}    Set Variable    ${response.json()}[bookingid]
    Set Suite Variable    ${id}
    ${response}    GET    https://restful-booker.herokuapp.com/booking/${id}
    Log    ${response.json()}
    Should Be Equal    ${response.json()}[lastname]    Gruber
    Should Be Equal    ${response.json()}[firstname]    Hans
    Should Be Equal As Numbers    ${response.json()}[totalprice]    200
    Dictionary Should Contain Value     ${response.json()}    Gruber

Delete Booking
    ${header}    Create Dictionary    Cookie=token\=${token}
    ${response}    DELETE    url=https://restful-booker.herokuapp.com/booking/${id}    headers=${header}
    Status Should Be    201    ${response}

*** Keywords ***
Authenticate as Admin
    ${body}    Create Dictionary    username=admin    password=password123
    ${response}    POST    url=https://restful-booker.herokuapp.com/auth    json=${body}
    Log    ${response.json()}
    ${token}    Set Variable    ${response.json()}[token]
    Log    ${token}
    Set Suite Variable    ${token}

todo MVC

这是一个BDD的例子

*** Settings ***
Library    Browser
Library    String
Suite Setup    New Browser    browser=${BROWSER}    headless=${HEADLESS}
Test Setup    New Context    viewport={'width': 1920, 'height': 1080}
Test Teardown    Close Context
Suite Teardown    Close Browser

*** Variables ***
${BROWSER}    chromium
${HEADLESS}    False

*** Test Cases ***
Add Two ToDos And Check Items
    [Documentation]    Checks if ToDos can be added and ToDo count increases
    [Tags]    Add ToDo
    Given ToDo App is open
    When I Add A New ToDo "Learn Robot Framework"
    And I Add A New ToDo "Write Test Cases"
    Then Open ToDos should show "2 items left"

Add Two ToDos And Check Wrong Number Of Items
    [Documentation]    Checks if ToDos can be added and ToDo count increases
    [Tags]    Add ToDo
    Given ToDo App is open
    When I Add A New ToDo "Learn Robot Framework"
    And I Add A New ToDo "Write Test Cases"
    Then Open ToDos should show "1 items left"

Add ToDo And Mark Same ToDo
    [Tags]    Mark ToDo
    Given ToDo App is open
    When I Add A New ToDo "Learn Robot Framework"
    And I Mark ToDo "Learn Robot Framework"
    Then Open ToDos should show "0 items left"

Check If Marked ToDos are removed
    Given ToDo App is open
    And I Added Two ToDos
    When I Mark One ToDo
    Then Open ToDos should show "1 item left"

Split ToDos
    Given ToDo App is open
    When I Add New ToDos "Learn Robot Framework&Write Test Cases&Sleep"
    Then Open ToDos should show "3 items left"

Add A Lot Of Todos
    Given ToDo App is open
    When I Add "100" ToDos
    Then Open ToDos should show "100 items left"

Add A Lot Of Todos With WHILE
    Given ToDo App is open
    When I Add "100" ToDos With WHILE Loop
    Then Open ToDos should show "100 items left"

*** Keywords ***
ToDo App is open
    New Page    https://todomvc.com/examples/react/

I Add A New ToDo "${todo}"   
    Fill Text  .new-todo  ${todo}
    Press Keys  .new-todo  Enter

I Add New ToDos "${todo}"
    IF  "&" in $todo
        @{todos}    Split String    ${todo}    separator=&
        FOR  ${item}  IN  @{todos}
            Fill Text  .new-todo  ${item}
            Press Keys  .new-todo  Enter 
        END
    ELSE
        Fill Text  .new-todo  ${todo}
        Press Keys  .new-todo  Enter
    END
    
Open ToDos should show "${text}"
    Get Text    span.todo-count    ==    ${text}

I Mark ToDo "${todo}"
    Click    "${todo}" >> .. >> input.toggle

I Added Two ToDos
    I Add A New ToDo "Learn Robot Framework"
    I Add A New ToDo "Write Test Cases"

I Mark One ToDo
    Click    li:first-child >> input.toggle

I Add "${count}" ToDos
    FOR    ${index}    IN RANGE    ${count}
        I Add A New ToDo "My ToDo Number ${index}"    
    END

I Add "${count}" ToDos With WHILE Loop
    ${x}=    Set Variable    ${0}
    WHILE  ${x} < ${count}
        ${x}=    Evaluate    ${x} + 1
        I Add A New ToDo "My ToDo Number ${x}"
    END
    

风格指南

风格指南 |机器人框架 (robotframework.org)

Sections

*** Comments ***


*** Settings ***


*** Variables ***


*** Test Cases ***


*** Keywords ***

 Settings

*** Settings ***
Documentation
Metadata

Library    BuiltIn
Library    3rd Party
Library    Custom
Resource
Variables

Suite Setup
Suite Teardown
Test Setup
Test Teardown
Test Template
Test Timeout

Test Tags

Variables

*** Variables ***
${VARIABLE}  This is a Variable
${COMPOSITE VARIABLES}  ${VARIABLE} with other variables.

Test Cases

Test Case
    [Documentation]
    [Tags]
    [Timeout]
    [Setup]
    [Template]
    Static Variable Assignments
    Keyword Calls
    Verification Keyword Call
    [Teardown]

Keyword

Keyword
    [Documentation]
    [Tags]
    [Arguments]
    [Timeout]
    [Setup]
    Static Variable Assignments
    Keyword Calls
    [Teardown]

扩展RF

可以写Python库

Static Library

静态库中RF的关键字被定义为python的方法。

Static Library With a Class

class DemoLibrary:
    def __init__(self, *args, **kwargs):
        print(f"Sample Library initialized with args: {args} and kwargs: {kwargs}")
 
    def my_keyword(self, *args, **kwargs):
        print(f"Keyword got args: {args} and kwargs: {kwargs}")
        return "Hello World"
*** Settings ***
Library    DemoLibrary.py

*** Test Cases ***
Use a Keyword with multiple arguments
    My Keyword    Argument 1    Argument 2    Named Argument=One Value

Static Library withouth a Class

将关键字定义在python方法中

import base64

def encode_as_base64(string):
    """
    Encode string as base64.
    """
    return base64.b64encode(string.encode())

def decode_from_base64(string):
    """
    Decode string from base64.
    """
    return base64.b64decode(string).decode()
*** Settings ***
Library    LibraryWithoutClass.py

*** Test Cases ***
Use Custom Keywords
    ${base64}    Encode As Base64    This is a Test String
    Log    ${base64}
    ${decoded}    Decode From Base64    ${base64}
    Log    ${decoded}

Decorators 

可以使用装饰@@keyword和@not_keyword将方法装饰为关键字。

from robot.api.deco import keyword, not_keyword


@keyword('Login via user panel')
def login(username, password):
      # ...

@not_keyword
def this_is_not_keyword():
    pass
from robot.api.deco import keyword


@keyword(tags=['tag1', 'tag2'])
def login(username, password):
    # ...

@keyword('Custom name', ['tags', 'here'])
def another_example():
    # ...

@keyword(types={'count': int, 'case_insensitive': bool})
def example_keyword(count, case_insensitive=True):
    if case_insensitive:
        # ...

@keyword(types=[int, bool])
def example_keyword(count, case_insensitive=True):
    if case_insensitive:
        # ...

BDD

BDD (Behavior Driven Development) | ROBOT FRAMEWORK

变量

*** Variables *** Section

定义在这个部分的变量可以用于同一个文件中的所有的test cases和关键字中。

定义在这个部分的变量是suite变量。

如果一个resource或者robot文件中有variables部分被导入到test suite中,则这些变量也成为suite变量。

*** Variables ***
${my_var}     my_value
@{my_list}    Apple    Banana    Orange
&{my_dict}    name=my_value1    password=my_value2

*** Test Cases ***
Test Case 1
    Log    ${my_var}
    Log    ${my_list}
    Log    ${my_dict}
    FOR    ${item}    IN    @{my_list}
        Log    ${item}
    END
    Log    ${my_dict}[name]
    Log    ${my_dict}[password]
    FOR   ${key}    ${value}    IN    &{my_dict}
        Log Many    ${key}    ${value}
    END
    My Keyword

*** Keywords ***
My Keyword
    Log Many    ${my_var}    ${my_list}    ${my_dict}    

在测试用例和关键字中设置变量

除了 *** 变量 *** 部分,还可以在测试用例和关键字中动态设置变量。 变量由关键字的返回值设置。 有一些关键字显式设置变量值,例如

  • 设置变量
  • 设置测试变量
  • 设置套件变量
  • 设置全局变量

它们可用于设置变量的值更改变量的范围

变量有不同的级别。

*** Test Cases ***

Test Case 1
    ${my_local_var}    Set Variable    Hello World      #用例级别的变量
    Log    ${my_local_var}    # Pass: Logs the value of the variable
    Set Suite Variable    ${my_suite_var}    I'm a suite variable  #套件级别变量
    Set Global Variable    ${my_global_var}    I'm a global variable  #全局变量

Test Case 2
    Log    ${my_local_var}    # Fails: 这个变量的范围仅存在Test Case1中
    Log    ${my_suite_var}    # Pass: Variable exists for the scope of the whole suite
    Log    ${my_global_var}   # Pass: Variable exists for the scope of the whole test run

Test Case 3
    My Keyword
    Log    ${my_keyword_var}    # Fails: 变量的范围为关键字My Keyword中
    Log    ${my_test_var}    # Pass: Variable  exists in the scope of the test case

*** Keywords ***
My Keyword
    ${my_keyword_var}    Set Variable    Hello Keyword
    Log    ${my_keyword_var}    # Pass: Logs the value of the variable
    Set Test Variable    ${my_test_var}    I'm a test case variable

何时使用 $ 和 @ 以及 & 和 %?​

变量名称包括

  • 变量类型标识符(例如 、 、 、$@&%)
  • 大括号{}
  • 变量名称(例如 , , ,my_varmy_listmy_dictmy_var2)

变量类型标识符用于定义变量的类型。

  • $用于标量变量。
  • @用于列表变量。
  • &用于字典变量。
  • %用于环境变量。

标量变量、列表变量和字典有什么区别?
标量变量只能包含一个值
一个列表变量可以包含多个值
一个字典变量可以包含多个键值对

但是,为什么我们可以用语法${my_list}和语法@{my_list}来访问列表变量呢?my_list

${my_list}访问整个 List 对象。它是一个容器,包含列表中的所有项目。 您可以使用它来访问整个列表变量,或者使用语法 访问列表的特定项。my_listmy_list${my_list}[index]

@{my_list}访问 list 变量 的项。这就像列表变量被解压缩,所有项目都可以作为单独的变量使用。my_listmy_list

*** Settings ***
Library    Collections
*** Variables ***
@{my_list}    Apple    Banana    Orange

*** Test Cases ***
Test Case 1
    Log    ${my_list}   # Pass: 打印整个列表对象 ['Apple', 'Banana', 'Orange']
    Log Many    @{my_list}   # Pass: Logs the items of the list object 分别返回Apple Banana Orange
    Log Many    ${my_list}   # Pass: 打印整个列表对象
    Log List    ${my_list}   # Pass: 打印整个列表对象
    Log    ${my_list}[0]    # Pass: 打印列表对象的第一个元素
    Log    @{my_list}[0]    # Fail: @{my_list} 不是列表对象,不存在index
    Log    @{my_list}       # Fail: The second argument of the Log keyword `level` only allows the values `TRACE`, `DEBUG`, `INFO`, `WARN`, `ERROR`, `NONE`.
                            # The value `Banana` for the argument `level` is not allowed.
    Log    ${my_list}[0]    ${my_list}[1]   ${my_list}[2]   # Fail: Same as above
    FOR    ${item}    IN    @{my_list}  # Pass: Iterates over the items of the list object
        Log    ${item}                  # Pass: 返回列表对象的元素
    END

每当您想要访问列表变量的容器时,都必须使用语法${my_list}
当您要将列表变量分解为其项时,您必须使用语法@{my_list} .

这就像一个装有瓶子的啤酒箱。
使用${beer_crate}该语法,您可以访问整个啤酒箱。
使用语法@{beer_crate},您可以得到瓶子。
使用语法[index],您可以在板条箱内获得一个特定的瓶子。${beer_crate}

变量文件

可以从外部文件加载变量,如 Python的py或yaml文件。
对于 Yaml 文件,pyyaml是必需的。

pip install pyyaml

可以在py文件中创建简单的变量、列表或字典,甚至是复杂的对象,如类。 

PythonVariables.py

class TestEnv:
    ip = '123.4.5.6'
    user = 'robot'
    roles = ['admin', 'user']

my_var = 'Hello World'
my_list = ["Apple", "Banana", "Cherry"]
my_dict = {'name': 'John', 'age': 36}

DynamicVariables.py

import os
import random
import time
import math

USER = os.getlogin()                # current login name
RANDOM_INT = random.randint(0, 10)  # random integer in range [0,10]
CURRENT_TIME = time.asctime()       # timestamp like 'Thu Apr  6 12:45:21 2006'
if time.localtime()[3] > 12:
    AFTERNOON = True
else:
    AFTERNOON = False

def get_area(diameter):
    radius = diameter / 2
    area = math.pi * radius * radius
    return area

AREA1 = get_area(1)
AREA2 = get_area(2)

.yaml或.yml文件解释为字典

YamlVariables.yml

# These are scalars:
base_url: https://qaserver.mycompany.com:8080
admin_user: iAmAdMiN
admin_password: eieioscoobydoo1234
# Now, a list:
yaml_list:
     - Item 1
     - Item two
     - 3
# Finally, a dictionary:
yaml_dict:
     key_1: A string
     key_2: 1 # an int

*** Settings ***
Variables    PythonVariables.py
Variables    YamlVariables.yaml
Variables    DynamicVariables.py

*** Test Cases ***
Access Python Variables
    Log   ${TestEnv.ip}
    Log    ${TestEnv.roles}
    Log Many   @{TestEnv.roles}
    Log    ${my_var}
    Log Many   @{my_list}
    Log Many   &{my_dict}
    FOR    ${item}    IN    @{my_list}
        Log    ${item}
    END

Access Yaml Variables
    Log        ${base_url}
    Log Many   @{yaml_list}
    Log        ${yaml_dict}
    Log        ${yaml_dict}[key_1]

Access Dynamic Variables
    Log   ${USER}
    Log   ${RANDOM_INT}
    Log   ${CURRENT_TIME}
    Log   ${AFTERNOON}
    Log   ${AREA1}
    Log   ${AREA2}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1571517.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Day82:服务攻防-开发组件安全Solr搜索Shiro身份Log4j日志本地CVE环境复现

目录 J2EE-组件Solr-本地demo&CVE 命令执行&#xff08;CVE-2019-17558&#xff09; 远程命令执行漏洞(CVE-2019-0193) Apache Solr 文件读取&SSRF (CVE-2021-27905) J2EE-组件Shiro-本地demo&CVE CVE_2016_4437 Shiro-550Shiro-721(RCE) CVE-2020-11989(身…

macU盘在电脑上读不出来 u盘mac读不出来怎么办 macu盘不能写入

对于Mac用户来说&#xff0c;使用U盘是很常见的操作&#xff0c;但有时候可能会遇到Mac电脑无法读取U盘的情况&#xff0c;这时候就需要使用一些特定的工具软件来帮助我们解决问题。本文就来告诉大家macU盘在电脑上读不出来是怎么回事&#xff0c;u盘mac读不出来怎么办。 一、m…

Java 中 Spring Boot 框架下的 Email 开发

Email 开发 1. 核心依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-mail</artifactId> </dependency><dependency><groupId>org.springframework.boot</groupId><…

ubuntu安装sublime3并设置中文

安装Sublime Text 3 在Ubuntu上安装Sublime Text 3可以通过以下步骤进行&#xff1a; 打开终端。 导入Sublime Text 3的GPG密钥&#xff1a; wget -qO- https://download.sublimetext.com/sublimehq-pub.gpg | sudo apt-key add - 添加Sublime Text 3的存储库&#xff1a; …

Spring Boot 相关知识和工具类

写在前面 此文是对后端开发框架Spring Boot快速入门一文的知识点补充与完善&#xff0c;如果是新手小白建议两篇文章一起食用,上面那篇文章为主&#xff0c;本文为辅&#xff0c;以达到最佳效果&#xff0c;大佬随意。 http 五种与后端的交互方法 Get:主要用于请求数据。当客…

vue2+elementUi的两个el-date-picker日期组件进行联动

vue2elementUi的两个el-date-picker日期组件进行联动 <template><el-form><el-form-item label"起始日期"><el-date-picker v-model"form.startTime" change"startTimeChange" :picker-options"startTimePickerOption…

Map源码解析

基本介绍 其实HashMap底层是个什么东西我们之前也讲过, 就是一个哈希桶(差不多可以看成一个数组), 然后每一个节点又连接着链表/红黑树之类的, 下面让我们看一看具体在源码上是怎样实现的: 常量及其它 -> static final int DEFAULT_INITIAL_CAPACITY 1 << 4; //这个…

解决JavaWeb中IDEA2023新版本无法创建Servlet的问题

出现问题&#xff1a;IDEA右键创建Servlet时&#xff0c;找不到选项 原因分析&#xff1a;IDEA的2023版的已经不支持Servlet了&#xff0c;如果还要使用的话&#xff0c;需要自己创建模板使用 创建模板 右击设置&#xff0c;选择&#xff08;File and Code Templates&#x…

Oracle APEX 23.2版本 使用应用程序工作副本进行协作开发

现状描述&#xff1a; 当前APEX协作开发都是在同一应用程序下进行的&#xff0c;这样做有可能因同一时间对同一数据进行操作造成锁表或其他问题&#xff0c;Oracle APEX23.2版本迭代后新增了部分功能&#xff0c;可以创建应用程序的工作副本来修复错误、添加功能&#xff0c;然…

后端开发框架Spring Boot快速入门

写在前面 推荐将本文与Spring Boot 相关知识和工具类一文结合起来看&#xff0c;本文为主&#xff0c;上面那篇文章为辅&#xff0c;一起食用&#xff0c;以达到最佳效果&#xff0c;当然&#xff0c;大佬随意。 IDEA创建Spring Boot工程 关于Spring Boot框架项目&#xff0…

Win10 下 Vision Mamba(Vim-main)的环境配置(libcuda.so文件无法找到,windows系统运行失败)

目录 1、下载NVIDIA 驱动程序、cuda11.8、cudnn8.6.0 2、在Anaconda中创建环境并激活 3、下载gpu版本的torch 4、配置环境所需要的包 5、安装causal_conv1d和mamba-1p1p1 安装causal_conv1d 安装mamba-1p1p1 6、运行main.py失败 请直接拉到最后查看运行失败的原因&am…

虚幻UE5数字孪生蓝图开发教程

一、背景 这几年&#xff0c;智慧城市/智慧交通/智慧水利等飞速发展&#xff0c;骑士特意为大家做了一个这块的学习路线。 二、这是学习大纲 1.给虚幻UE5初学者准备的智慧城市/数字孪生蓝图开发教程 https://www.bilibili.com/video/BV1894y1u78G 2.UE5数字孪生蓝图开发教学…

【stm32】I2C通信协议

【stm32】I2C通信协议 概念及原理 如果我们想要读写寄存器来控制硬件电路&#xff0c;就至少需要定义两个字节数据 一个字节是我们要读写哪个寄存器&#xff0c;也就是指定寄存器的地址 另一个字节就是这个地址下存储寄存器的内容 写入内容就是控制电路&#xff0c;读出内容就…

Arcgis Pro地理配准

目录 一、目的 二、配准 1、找到配准工具 2、添加控制点 3、选择控制点 4、添加更多控制点 5、配准完成、保存 三、附录 1、查看控制点或删除控制点 2、效果不好怎么办 一、目的 下面我们将两张地图进行配准&#xff0c;其中一张有地理位置&#xff0c;而另外一张没…

​​​​​​​【人工智能】手写数字识别

手写数字识别 实验背景 数据集介绍 MNIST数据集包含了一系列的手写数字图像&#xff0c;包括0到9的数字。每张图像都是灰度图像&#xff0c;尺寸为28x28像素。数据集共包含60000张训练图像和10000张测试图像。 MNIST数据集的目标是通过训练一个模型&#xff0c;使其能够正确地识…

NPW(监控片的)的要点精讲

半导体的生产过程已经历经数十年的发展&#xff0c;其中主要有两个大的发展趋势&#xff0c;第一&#xff0c;晶圆尺寸越做越大&#xff0c;到目前已有超过70%的产能是12寸晶圆&#xff0c;不过18寸晶圆产业链推进缓慢&#xff1b;第二&#xff0c;电子器件的关键尺寸越做越小&…

LCD屏幕mmap显示

目录 前言 一.LCD显示 二.LCD颜色显示 2.1 直接显示 2.2 mmap映射显示 前言 mmap是一种内存映射文件的方法&#xff0c;它允许将文件或其它对象映射到进程的地址空间。 使用mmap映射函数进行映射显示&#xff0c;与屏幕普通直接显示相比有很大的优势 一.LCD显示基础 像素、分辨…

mac 切换 jdk

查看 mac 上都有哪些版本 /usr/libexec/java_home -V看准版本切换 按前缀切换 比如 export JAVA_HOME/usr/libexec/java_home -v 1.8这样会随机一个 1.8 的 如果想再确定一个比如 openjdk export JAVA_HOME/usr/libexec/java_home -v 1.8.0_292这个方式是临时的&#xff0c…

图像处理入门 3(how to get the pixel pitch / 如何获得单个像素的尺寸)

在这里一节里面&#xff0c;将记录如何获得一个相机传感器中单个像素点的尺寸&#xff0c;为了实现不同相机照片之间的匹配。 如果我们知道了相机传感器的尺寸和分辨率的大小&#xff0c;自然就可以求出单个像素的大小。 在这里插入图片描述&#xff1a; 如何获得相机传感器的…

vue创建项目下载动态路由v-for mounted websocket :style :class store使用说明

在Vue中创建一个项目&#xff0c;并整合动态路由、v-for、mounted生命周期钩子、WebSocket、:style、:class以及Vuex的store&#xff0c;涉及到多个Vue核心特性的使用。下面我将简要说明如何逐步整合这些特性。 1. 创建Vue项目 使用Vue CLI创建项目&#xff1a; 2. 配置动态路…