自动化测试框架Robot Framework入门

什么是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 baiduOpen Browser    url=https://www.baidu.com    browser=edgeInput Text    //input[@id="kw"]    周杰伦Click Element    //input[@id="su"]Sleep    5Close 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.comQuick Get Request With Parameters Test${response}=    GET  https://www.google.com/search  params=query=ciao  expected_status=200Quick Get A JSON Body Test${response}=    GET  https://jsonplaceholder.typicode.com/posts/1Should 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 CarOpen Insurance ApplicationEnter Vehicle Data for AutomobileEnter Insurant DataEnter Product DataSelect Price OptionSend QuoteEnd Test*** Keywords ***
Open Insurance ApplicationNew Browser    browser=${BROWSER}    headless=${HEADLESS}New Context    locale=en-GBNew Page    http://sampleapp.tricentis.com/Enter Vehicle Data for AutomobileClick    div.main-navigation >> "Automobile"Select Options By    id=make    text    AudiFill Text    id=engineperformance    110Fill Text    id=dateofmanufacture    06/12/1980Select Options By    id=numberofseats    text    5Select Options By    id=fuel    text    Petrol    Fill Text    id=listprice    30000Fill Text    id=licenseplatenumber    DMK1234Fill Text    id=annualmileage   10000 Click    section[style="display: block;"] >> text=Next »Enter Insurant Data[Arguments]    ${firstname}=Max    ${lastname}=MustermannFill Text    id=firstname    MaxFill Text    id=lastname    MustermannFill Text    id=birthdate    01/31/1980Check Checkbox    *css=label >> id=gendermaleFill Text    id=streetaddress    Test StreetSelect Options By    id=country    text    GermanyFill Text    id=zipcode    40123Fill Text    id=city    EssenSelect Options By    id=occupation    text    EmployeeClick    text=Cliff DivingClick    section[style="display: block;"] >> text=Next »Enter Product DataFill Text    id=startdate    06/01/2023Select Options By    id=insurancesum    text    7.000.000,00Select Options By    id=meritrating    text    Bonus 1Select Options By    id=damageinsurance    text    No CoverageCheck Checkbox    *css=label >> id=EuroProtectionSelect Options By    id=courtesycar    text    YesClick    section[style="display: block;"] >> text=Next »Select Price Option[Arguments]    ${price_option}=SilverClick    *css=label >> css=[value=${price_option}]Click    section[style="display: block;"] >> text=Next »Send QuoteFill Text    "E-Mail" >> .. >> input    max.mustermann@example.comFill Text    "Phone" >> .. >> input    0049201123456Fill Text    "Username" >> .. >> input    max.mustermannFill 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=10Click    "« Send »"${body}=    Wait For    ${promise}Log    ${body}[status]Log    ${body}[body]Wait For Elements State    "Sending e-mail success!"Click    "OK"End TestClose ContextClose 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 MFANew Page    https://seleniumbase.io/realworld/loginFill Text    id=username    demo_userFill Text    id=password    secret_pass${totp}    Get Totp    GAXG2MTEOR3DMMDGFill Text    id=totpcode     ${totp}Click    "Sign in"Get Text  h1  ==  Welcome!

 

import pyotpdef 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    200Log List    ${response.json()}FOR  ${booking}  IN  @{response.json()}${response}    GET    https://restful-booker.herokuapp.com/booking/${booking}[bookingid]TRYLog    ${response.json()}EXCEPTLog    Cannot retrieve JSON due to invalid dataENDENDCreate 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]    GruberShould Be Equal    ${response.json()}[firstname]    HansShould Be Equal As Numbers    ${response.json()}[totalprice]    200Dictionary Should Contain Value     ${response.json()}    GruberDelete 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 ToDoGiven ToDo App is openWhen 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 ToDoGiven ToDo App is openWhen 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 ToDoGiven ToDo App is openWhen 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 removedGiven ToDo App is openAnd I Added Two ToDosWhen I Mark One ToDoThen Open ToDos should show "1 item left"Split ToDosGiven ToDo App is openWhen I Add New ToDos "Learn Robot Framework&Write Test Cases&Sleep"Then Open ToDos should show "3 items left"Add A Lot Of TodosGiven ToDo App is openWhen I Add "100" ToDosThen Open ToDos should show "100 items left"Add A Lot Of Todos With WHILEGiven ToDo App is openWhen I Add "100" ToDos With WHILE LoopThen Open ToDos should show "100 items left"*** Keywords ***
ToDo App is openNew Page    https://todomvc.com/examples/react/I Add A New ToDo "${todo}"   Fill Text  .new-todo  ${todo}Press Keys  .new-todo  EnterI 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 ENDELSEFill Text  .new-todo  ${todo}Press Keys  .new-todo  EnterENDOpen ToDos should show "${text}"Get Text    span.todo-count    ==    ${text}I Mark ToDo "${todo}"Click    "${todo}" >> .. >> input.toggleI Added Two ToDosI Add A New ToDo "Learn Robot Framework"I Add A New ToDo "Write Test Cases"I Mark One ToDoClick    li:first-child >> input.toggleI Add "${count}" ToDosFOR    ${index}    IN RANGE    ${count}I Add A New ToDo "My ToDo Number ${index}"    ENDI Add "${count}" ToDos With WHILE Loop${x}=    Set Variable    ${0}WHILE  ${x} < ${count}${x}=    Evaluate    ${x} + 1I Add A New ToDo "My ToDo Number ${x}"END

风格指南

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

Sections

*** Comments ****** Settings ****** Variables ****** Test Cases ****** Keywords ***

 Settings

*** Settings ***
Documentation
MetadataLibrary    BuiltIn
Library    3rd Party
Library    Custom
Resource
VariablesSuite Setup
Suite Teardown
Test Setup
Test Teardown
Test Template
Test TimeoutTest 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 AssignmentsKeyword CallsVerification Keyword Call[Teardown]

Keyword

Keyword[Documentation][Tags][Arguments][Timeout][Setup]Static Variable AssignmentsKeyword 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 argumentsMy Keyword    Argument 1    Argument 2    Named Argument=One Value

Static Library withouth a Class

将关键字定义在python方法中

import base64def 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 StringLog    ${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 1Log    ${my_var}Log    ${my_list}Log    ${my_dict}FOR    ${item}    IN    @{my_list}Log    ${item}ENDLog    ${my_dict}[name]Log    ${my_dict}[password]FOR   ${key}    ${value}    IN    &{my_dict}Log Many    ${key}    ${value}ENDMy Keyword*** Keywords ***
My KeywordLog 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 variableSet Suite Variable    ${my_suite_var}    I'm a suite variable  #套件级别变量Set Global Variable    ${my_global_var}    I'm a global variable  #全局变量Test Case 2Log    ${my_local_var}    # Fails: 这个变量的范围仅存在Test Case1中Log    ${my_suite_var}    # Pass: Variable exists for the scope of the whole suiteLog    ${my_global_var}   # Pass: Variable exists for the scope of the whole test runTest Case 3My KeywordLog    ${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 KeywordLog    ${my_keyword_var}    # Pass: Logs the value of the variableSet 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 1Log    ${my_list}   # Pass: 打印整个列表对象 ['Apple', 'Banana', 'Orange']Log Many    @{my_list}   # Pass: Logs the items of the list object 分别返回Apple Banana OrangeLog Many    ${my_list}   # Pass: 打印整个列表对象Log List    ${my_list}   # Pass: 打印整个列表对象Log    ${my_list}[0]    # Pass: 打印列表对象的第一个元素Log    @{my_list}[0]    # Fail: @{my_list} 不是列表对象,不存在indexLog    @{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 aboveFOR    ${item}    IN    @{my_list}  # Pass: Iterates over the items of the list objectLog    ${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 mathUSER = 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 = Falsedef get_area(diameter):radius = diameter / 2area = math.pi * radius * radiusreturn areaAREA1 = 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 stringkey_2: 1 # an int

 

*** Settings ***
Variables    PythonVariables.py
Variables    YamlVariables.yaml
Variables    DynamicVariables.py*** Test Cases ***
Access Python VariablesLog   ${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}ENDAccess Yaml VariablesLog        ${base_url}Log Many   @{yaml_list}Log        ${yaml_dict}Log        ${yaml_dict}[key_1]Access Dynamic VariablesLog   ${USER}Log   ${RANDOM_INT}Log   ${CURRENT_TIME}Log   ${AFTERNOON}Log   ${AREA1}Log   ${AREA2}

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

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

相关文章

Spring Security——04,认证_校验

认证_校验 一、认证过滤器二、配置过滤器三、测试过滤器3.1 登录接口3.2 非登录接口3.3 结果 一键三连有没有捏~~ 一、认证过滤器 创建一个filter包&#xff0c;创建一个过滤器 代码如下&#xff1a; Component public class JwtAuthenticationTokenFilter extends OncePerR…

在集群中使用deepspeed如果端口被占用可以使用deepspeed参数更改

在集群中使用deepspeed如果端口被占用可以使用deepspeed参数更改 这一次G老师不好使了 在集群中使用deepspeed默认的端口号29500被占用&#xff0c;显示更改居然不起作用 G老师给的方法也不好使 #!/bin/bash MASTER_ADDRlocalhost MASTER_PORT29501 # 选择一个未被占用的端…

mysql 运算符 语句 字符集 校队集

mysql 运算符 使用select语句可以输出运算的结果 mysql标识符不区分大小写 算数运算符 1./除法 得到的结果是一个小数 %是整数,省略小数 2、除以0不会报错,得到的结果是 null 3.数宇和字符串做加法运算,并不会拼接 比较运算符 1.mysql里面的=是比较运算符,而不是赋值运算…

lora pingpang系统 4

1 深入了解LoRa技术原理 1.1 LoRa扩频通信原理 1.1.1 模拟无线通信&#xff1a; 模拟无线通信是一种使用模拟信号传输数据的通信方式。这种通信方式已经被数字无线通信所取代&#xff0c;因为数字通信具有更高的效率和可靠性。 天线&#xff1a;从空中接收到的无线电波转换成…

数据结构——图的概念,图的存储结构,图的遍历(dfs,bfs)

目录 1.图的定义和术语 2.案例引入 1.六度空间理论 3.图的类型定义 4.图的存储结构 1.邻接矩阵 1.无向图的邻接矩阵表示法 2.有向图的邻接矩阵表示法 3.网&#xff08;有权图&#xff09;的邻接矩阵表示法 代码示例&#xff1a; 2.采用邻接矩阵表示法创建无向图…

MySQL 表的增删改查

文章目录 一、什么是CRUD&#xff1f;二、新增&#xff08;Create&#xff09;1、单行数据 全列插入2、多行数据 指定列插入3、插入特殊类型 三、查询&#xff08;Retrieve&#xff09;1、全列查询2、指定列查询3、表达式查询4、指定别名5、去重6、排序7、条件查询基本查询&a…

java算法day44 | ● 完全背包 ● 518. 零钱兑换 II ● 377. 组合总和 Ⅳ

完全背包理论基础 完全背包和01背包问题唯一不同的地方就是&#xff0c;每种物品有无限件。 体现在代码中就是对背包的遍历顺序不同。01背包是逆序遍历背包&#xff0c;完全背包是顺序遍历背包。 518. 零钱兑换 II class Solution {public int change(int amount, int[] coin…

IMAP的要点:旅行前需要了解的内容

你是否经常因会议而出差&#xff0c;需要在各种设备上灵活地访问你的电子邮件&#xff1f;如果是的话&#xff0c;你可能会想了解你的电子邮件系统是如何通过使用互联网消息访问协议&#xff08;IMAP&#xff09;来工作的&#xff0c;这样当你不在办公桌前时&#xff0c;你可以…

Java基础 - 代码练习

第一题&#xff1a;集合的运用&#xff08;幸存者&#xff09; public class demo1 {public static void main(String[] args) {ArrayList<Integer> array new ArrayList<>(); //一百个囚犯存放在array集合中Random r new Random();for (int i 0; i < 100; …

SpringCloud - 如何本地调试不会注册到线上环境(Nacos)?

问题描述 有时候我们需要本地调试注册到 Nacos 上&#xff0c;但是会影响线上服务的 Feign 请求打到本地导致不通影响了线上业务。 原因分析 一般最传统的解决方案就是修改本地 bootstrap.yml 的 spring.cloud.nacos.discovery.namespace spring:application:name: app-serv…

jvisualvm 使用教程

之前看过 jvisualvm&#xff0c;但是那个时候对 JVM 并不是很熟悉&#xff0c;后面看了下八股文&#xff0c;看了下 JVM 的相关知识之后&#xff0c;发现多了解点 JVM 的东西&#xff0c;对我们 CRUD 其实是有指导意义的&#xff0c;就比如我们通常会 new 一堆的没有用到的对象…

使用 Spring Email 和 Thymeleaf 技术,向新注册用户发送激活邮件(二)

本篇博客对应“2.2 开发注册功能”小结 对应视频: 开发注册功能 开发注册功能-续 注册功能是相对比较复制的功能&#xff0c;对于一个相对复杂的功能&#xff0c;可以把这个功能进行拆解。把这个功能的流程想清楚&#xff0c;就知道怎么拆解了&#xff1a; 也可以按照请求进行…

[每周一更]-第92期:Go项目中的限流算法

这周五在清明假期内&#xff0c;提前更新文章 很多业务会有限流的场景&#xff0c;比如活动秒杀、社区搜索查询、社区留言功能&#xff1b;保护自身系统和下游系统不被巨型流量冲垮等。 在计算机网络中&#xff0c;限流就是控制网络接口发送或接收请求的速率&#xff0c;它可防…

【算法练习】28:选择排序学习笔记

一、选择排序的算法思想 弄懂选择排序算法&#xff0c;先得知道两个概念&#xff1a;未排序序列&#xff0c;已排序序列。 原理&#xff1a;以升序为例&#xff0c;选择排序算法的思想是&#xff0c;先将整个序列当做未排序的序列&#xff0c;以序列的第一个元素开始。然后从左…

K8S - Deployment 的版本回滚

当前状态 先看deployment rootk8s-master:~# kubectl get deploy -o wide --show-labels NAME READY UP-TO-DATE AVAILABLE AGE CONTAINERS IMAGES …

理解pytorch的广播语义

目录 什么是广播运算 广播的条件 示例 示例1 示例2 示例3 补1 示例4 原位运算 示例5 参与广播运算的两个tensor&#xff0c;必须是从右向左对齐 总结规律 两个tensor可以做广播运算的条件&#xff1a; 两个可以互相广播的tensor运算的步骤&#xff1a; 例子&#x…

【深度学习】深度学习md笔记总结第3篇:TensorFlow介绍,学习目标【附代码文档】

深度学习笔记完整教程&#xff08;附代码资料&#xff09;主要内容讲述&#xff1a;深度学习课程&#xff0c;深度学习介绍要求,目标,学习目标,1.1.1 区别,学习目标,学习目标。TensorFlow介绍&#xff0c;2.4 张量学习目标,2.4.1 张量(Tensor),2.4.2 创建张量的指令,2.4.3 张量…

整数与浮点数在内存中的存储

整数与浮点数在内存中的存储 一&#xff0c;大小端存储二&#xff0c;整数在内存中的存储三&#xff0c;浮点数在内存中的存储3.1浮点数的存储规则3.2浮点数的存储过程3.2.1有效数字M3.2.2指数E3.2.3浮点数存储的特殊情况4&#xff0c;例题讲解 在C语言的编程中&#xff0c;我们…

分布式系统架构中的相关概念

1.1、衡量网站的性能指标 响应时间&#xff1a;指执行一个请求从开始到最后收到响应数据所花费的总体时间。并发数&#xff1a;指系统同时能处理的请求数量。 并发连接数&#xff1a;指的是客户端向服务器发起请求&#xff0c;并建立了TCP连接。每秒钟服务器连接的总TCP数量请…

Python--Django--说明

Django 是基于python 的 Web 开发框架. &nsbp;   Web开发指的是开发基于B/S 架构, 通过前后端的配合, 将后台服务器上的数据在浏览器上展现给前台用户的应用. &nsbp;   在早期, 没有Web框架的时候, 使用 Python CGI 脚本显示数据库中的数据. Web框架致力于解决一些…