Robot
pyATS

pyATS & RobotFramework

RobotFramework is an open source, Python-based test automation framework that is commonly used for acceptance test automation using English-like keyword-driven tests. pyATS and RobotFramework can be easily integrated to gain the following features:

  • running RobotFramework scripts directly within Easypy, saving runtime logs under runinfo directory, and aggregating results into Easypy report.
  • leverage pyATS infrastructure and libraries within RobotFramework scripts.
RobotFramework is installed as a component under pyATS, with the pyats[full] package install.


Step 1 - Verify Package Install

Verify the RobotFramework package and associated pyATS packages are installed in your virtualenv.


pip freeze | grep robot

    genie.libs.robot==25.4
    pyats.robot==25.4
    robotframework==7.3

You can verify the specific RobotFramework version also by using the command line for Robot, robot:


robot --version

    Robot Framework 7.3 (Python 3.11.9 on linux)

Step 2 - Create Robot File

In VSCode, using the code keyword in the Terminal window, open a new file to create a Robot file:


touch /home/pod14/workspace/nxapilab/tests/pyats.robot
code-server -r /home/pod14/workspace/nxapilab/tests/pyats.robot


Step 3 - Populate the Settings Section of the Robot File

There is a huge community of contributors around the tool which users can leverage to extend it's use cases for various needs. External libraries can be installed based on the user's needs or new custom libraries can be created with ease.

Test libraries are normally imported using the Library keyword in the Setting section and having the library name in the subsequent column. To use pyATS and pyATS Genie keywords in your Robot testcase script, you import ats.robot.pyATSRobot, genie.libs.robot.GenieRobot, and genie.libs.robot.GenieRobotApis.

Respective keywords that are available from each pyATS library can be located here:

A Suite Setup is executed before running any of the suite's test cases or child test suites, and a Suite Teardown is executed after them. The Suite Setup you will implement uses the testbed yaml file you created and used in your Python-based pyATS script by using the use testbed pyATS keyword. It connects to all devices using the pyATS connect to all devices keyword, and then finally calls a user custom keyword, Set Fabric Env that you will add to the Robot file in the next step.


*** Settings ***

Library        ats.robot.pyATSRobot
Library        genie.libs.robot.GenieRobot
Library        genie.libs.robot.GenieRobotApis

# Load topology/testbed yaml file
Suite Setup    Run Keywords
...            use testbed "%{TESTBED}"  AND
...            connect to all devices  AND
...            Set Fabric Env

# Disconnect sessions from all devices
Suite Teardown    Run Keywords
...               disconnect from all devices



Step 4 - Populate the Keywords Section of the Robot File

The Keywords section is used to create new keywords by combining existing keywords together. These keywords are called user keywords to differentiate them from existing library keywords that are implemented in test libraries, again, such as the pyATS library keywords you imported in the previous step.

In the Keywords section, you will add the following keywords for use in Suite Setup and the Testcases section covered in the next step:

  • Set Fabric Env: This keyword is leveraged in the Suite Setup to select the correct testbed yaml file. To this point in the lab you have created the testbed yaml for your staging (development) fabric, but later in the lab, you will create the testbed yaml for your prod fabric.
  • Get BGP L2VPN Summary From Device: This keyword simply is a "getter" keyword that gets the data from the device and is to be used in other keywords, such as the subsequent verify keywords.
  • Verify BGP ASN For All Devices: This keyword calls the Get BGP L2VPN Summary From Device user keyword and verifies the expected BGP ASN based on user input.
  • Verify BGP Neighbor Count: This keyword calls the Get BGP L2VPN Summary From Device user keyword and verifies the expected number of BGP neighbors based on user input.

Within each of these user keywords, keywords from Robot's core library are used to perform the validation checks. These include setting variables with Set Variable, FOR loops, Run Keyword If...Else, and comparision checks with keywords such as Should Be Equal As Numbers.


*** Keywords ***

Set Fabric Env
    ${is_prod}=  Evaluate  "prod" in """%{TESTBED}"""
    ${is_staging}=  Evaluate  "staging" in """%{TESTBED}"""
    @{DEVICE_LIST}=  Run Keyword If  ${is_prod}    Create list  prod-spine1  prod-leaf1  prod-leaf2
    ...  ELSE  Create list  staging-spine1  staging-leaf1  staging-leaf2
    Set Suite Variable  ${DEVICE_LIST}

Get BGP L2VPN Summary From Device
    [Arguments]  ${device}
    ${output}=  nxapi method nxapi cli  device=${device}  action=send  commands=show bgp l2vpn evpn summary  message_format=json_rpc  command_type=cli  alias=rest
    Log  ${output.json()}
    RETURN  ${output.json()}

Verify BGP ASN For All Devices
    [Arguments]  ${device_list}  ${expected_bgp_asn}
    FOR  ${device}  IN  @{device_list}
        ${output}=  Get BGP L2VPN Summary From Device    device=${device}
        ${bgp_asn}=  Set Variable  ${output}[result][body][TABLE_vrf][ROW_vrf][vrf-local-as]
        Should Be Equal As Numbers  ${bgp_asn}  ${expected_bgp_asn}
    END

Verify BGP Neighbor Count
    [Arguments]  ${device_list}  ${expected_bgp_nbr_count}
    FOR  ${device}  IN  @{device_list}
        ${output}=  Get BGP L2VPN Summary From Device    device=${device}
        ${bgp_nbrs}=  Set Variable  ${output}[result][body][TABLE_vrf][ROW_vrf][TABLE_af][ROW_af][TABLE_saf][ROW_saf][TABLE_neighbor][ROW_neighbor]
        ${type string}=    Evaluate     type($bgp_nbrs).__name__
        ${bgp_nbr_count}=  Run Keyword If  ${type string} == list  Get length  ${bgp_nbrs}
        ...  ELSE  Set Variable  1
        Should Be Equal As Numbers  ${bgp_nbr_count}  ${expected_bgp_nbr_count}
    END



Step 5 - Populate the Test Cases Section of the Robot File

Test cases are constructed in the Test Cases sections. Keywords can be imported from test libraries, resource files, or created in the keyword section of the test case file itself as you have done above for simplicity. As you grow your own keyword repositories, then it would be best practice to explore creating your own libraries or resource files to import.


*** Test Cases ***

VERIFY ALL DEVICE'S EXPECTED LOCAL BGP ASN via NX-API CLI JSON-RPC
    Verify BGP ASN For All Devices    device_list=${DEVICE_LIST}    expected_bgp_asn=65001

VERIFY SPINE DEVICE(S) EXPECTED NEIGHBOR COUNT via NX-API CLI JSON-RPC
    Verify BGP Neighbor Count    device_list=${DEVICE_LIST[:1]}    expected_bgp_nbr_count=2

VERIFY LEAF DEVICE(S) EXPECTED NEIGHBOR COUNT via NX-API CLI JSON-RPC
    Verify BGP Neighbor Count    device_list=${DEVICE_LIST[1:2]}    expected_bgp_nbr_count=1

After successfully populating pyats.robot with the above sections, save your pyats.robot file using Ctrl+s on the Windows keyboard or by clicking File then Save.

Warning

Be sure to save your file! Not saving will result in your code not executing.


Step 6 - Execute pyATS Robot Script

The Robot script will be executed using the pyATS EasyPy execution method for additional functionality as noted in the previous section.


pyats run robot pyats.robot --testbed-file staging-testbed.yaml --archive-dir=${PWD}/results --no-archive-subdir --no-mai

You will have to scroll up on the Terminal some, but your Robot script execution should look like the below. Notice the test cases are toward the top and they should show as PASS. Additionally, there is the same EasyPy reporting to show a summary and detail view of the test execution steps.

    2025-06-04T17:22:54: %EASYPY-INFO: --------------------------------------------------------------------------------
    2025-06-04T17:22:54: %EASYPY-INFO: Job finished. Wrapping up...
    2025-06-04T17:22:55: %EASYPY-INFO: Creating archive file: /home/pod14/workspace/nxapilab/tests/results/pyats.2025Jun04_17:22:18.152807.zip
    2025-06-04T17:22:55: %EASYPY-INFO: +------------------------------------------------------------------------------+
    2025-06-04T17:22:55: %EASYPY-INFO: |                                Easypy Report                                 |
    2025-06-04T17:22:55: %EASYPY-INFO: +------------------------------------------------------------------------------+
    2025-06-04T17:22:55: %EASYPY-INFO: pyATS Instance   : /home/pod14/.pyenv/versions/3.11.9/envs/nxapilab
    2025-06-04T17:22:55: %EASYPY-INFO: Python Version   : cpython-3.11.9 (64bit)
    2025-06-04T17:22:55: %EASYPY-INFO: CLI Arguments    : /home/pod14/.pyenv/versions/nxapilab/bin/pyats run robot pyats.robot --testbed-file staging-testbed.yaml --archive-dir=/home/pod14/workspace/nxapilab/tests/results --no-archive-subdir --no-mai
    2025-06-04T17:22:55: %EASYPY-INFO: User             : pod14
    2025-06-04T17:22:55: %EASYPY-INFO: Host Server      : ubuntu-code-server-template
    2025-06-04T17:22:55: %EASYPY-INFO: Host OS Version  : Ubuntu 22.04 jammy (x86_64)
    2025-06-04T17:22:55: %EASYPY-INFO: 
    2025-06-04T17:22:55: %EASYPY-INFO: Job Information
    2025-06-04T17:22:55: %EASYPY-INFO:     Name         : pyats
    2025-06-04T17:22:55: %EASYPY-INFO:     Result       : PASSED
    2025-06-04T17:22:55: %EASYPY-INFO:     Start time   : 2025-06-04 17:22:23.520118+00:00
    2025-06-04T17:22:55: %EASYPY-INFO:     Stop time    : 2025-06-04 17:22:54.537611+00:00
    2025-06-04T17:22:55: %EASYPY-INFO:     Elapsed time : 0:00:32
    2025-06-04T17:22:55: %EASYPY-INFO:     Archive      : /home/pod14/workspace/nxapilab/tests/results/pyats.2025Jun04_17:22:18.152807.zip
    2025-06-04T17:22:55: %EASYPY-INFO: 
    2025-06-04T17:22:55: %EASYPY-INFO: Total Tasks    : 1 
    2025-06-04T17:22:55: %EASYPY-INFO: 
    2025-06-04T17:22:55: %EASYPY-INFO: Overall Stats
    2025-06-04T17:22:55: %EASYPY-INFO:     Passed     : 3
    2025-06-04T17:22:55: %EASYPY-INFO:     Passx      : 0
    2025-06-04T17:22:55: %EASYPY-INFO:     Failed     : 0
    2025-06-04T17:22:55: %EASYPY-INFO:     Aborted    : 0
    2025-06-04T17:22:55: %EASYPY-INFO:     Blocked    : 0
    2025-06-04T17:22:55: %EASYPY-INFO:     Skipped    : 0
    2025-06-04T17:22:55: %EASYPY-INFO:     Errored    : 0
    2025-06-04T17:22:55: %EASYPY-INFO: 
    2025-06-04T17:22:55: %EASYPY-INFO:     TOTAL      : 3
    2025-06-04T17:22:55: %EASYPY-INFO: 
    2025-06-04T17:22:55: %EASYPY-INFO: Success Rate   : 100.00 %
    2025-06-04T17:22:55: %EASYPY-INFO: 
    2025-06-04T17:22:55: %EASYPY-INFO: Section Stats
    2025-06-04T17:22:55: %EASYPY-INFO:     Passed     : 3
    2025-06-04T17:22:55: %EASYPY-INFO:     Passx      : 0
    2025-06-04T17:22:55: %EASYPY-INFO:     Failed     : 0
    2025-06-04T17:22:55: %EASYPY-INFO:     Aborted    : 0
    2025-06-04T17:22:55: %EASYPY-INFO:     Blocked    : 0
    2025-06-04T17:22:55: %EASYPY-INFO:     Skipped    : 0
    2025-06-04T17:22:55: %EASYPY-INFO:     Errored    : 0
    2025-06-04T17:22:55: %EASYPY-INFO: 
    2025-06-04T17:22:55: %EASYPY-INFO:     TOTAL      : 3
    2025-06-04T17:22:55: %EASYPY-INFO: 
    2025-06-04T17:22:55: %EASYPY-INFO: Section Success Rate   : 100.00 %
    2025-06-04T17:22:55: %EASYPY-INFO: 
    2025-06-04T17:22:55: %EASYPY-INFO: +------------------------------------------------------------------------------+
    2025-06-04T17:22:55: %EASYPY-INFO: |                             Task Result Summary                              |
    2025-06-04T17:22:55: %EASYPY-INFO: +------------------------------------------------------------------------------+
    2025-06-04T17:22:55: %EASYPY-INFO: Task-1: pyats                                                             PASSED
    2025-06-04T17:22:55: %EASYPY-INFO: Task-1: pyats.VERIFY ALL DEVICE'S EXPECTED LOCAL BGP ASN via NX-API...    PASSED
    2025-06-04T17:22:55: %EASYPY-INFO: Task-1: pyats.VERIFY SPINE DEVICE(S) EXPECTED NEIGHBOR COUNT via NX...    PASSED
    2025-06-04T17:22:55: %EASYPY-INFO: Task-1: pyats.VERIFY LEAF DEVICE(S) EXPECTED NEIGHBOR COUNT via NX-...    PASSED
    2025-06-04T17:22:55: %EASYPY-INFO: 
    2025-06-04T17:22:55: %EASYPY-INFO: +------------------------------------------------------------------------------+
    2025-06-04T17:22:55: %EASYPY-INFO: |                             Task Result Details                              |
    2025-06-04T17:22:55: %EASYPY-INFO: +------------------------------------------------------------------------------+
    2025-06-04T17:22:55: %EASYPY-INFO: Task-1: pyats                                                             PASSED
    2025-06-04T17:22:55: %EASYPY-INFO: |-- VERIFY ALL DEVICE'S EXPECTED LOCAL BGP ASN via NX-API CLI JSON-RPC    PASSED
    2025-06-04T17:22:55: %EASYPY-INFO: |   `-- 1_Verify BGP ASN For All Devices                                  PASSED
    2025-06-04T17:22:55: %EASYPY-INFO: |       |-- 2_${device}    IN    @{device_list}                           PASSED
    2025-06-04T17:22:55: %EASYPY-INFO: |       |-- 3_${device} = staging-spine1                                  PASSED
    2025-06-04T17:22:55: %EASYPY-INFO: |       |-- 4_Get BGP L2VPN Summary From Device                           PASSED
    2025-06-04T17:22:55: %EASYPY-INFO: |       |-- 5_Nxapi Method Nxapi Cli                                      PASSED
    2025-06-04T17:22:55: %EASYPY-INFO: |       |-- 6_Log                                                         PASSED
    2025-06-04T17:22:55: %EASYPY-INFO: |       |-- 7_                                                            PASSED
    2025-06-04T17:22:55: %EASYPY-INFO: |       |-- 8_Set Variable                                                PASSED
    2025-06-04T17:22:55: %EASYPY-INFO: |       |-- 9_Should Be Equal As Numbers                                  PASSED
    2025-06-04T17:22:55: %EASYPY-INFO: |       |-- 10_${device} = staging-leaf1                                  PASSED
    2025-06-04T17:22:55: %EASYPY-INFO: |       |-- 11_Get BGP L2VPN Summary From Device                          PASSED
    2025-06-04T17:22:55: %EASYPY-INFO: |       |-- 12_Nxapi Method Nxapi Cli                                     PASSED
    2025-06-04T17:22:55: %EASYPY-INFO: |       |-- 13_Log                                                        PASSED
    2025-06-04T17:22:55: %EASYPY-INFO: |       |-- 14_                                                           PASSED
    2025-06-04T17:22:55: %EASYPY-INFO: |       |-- 15_Set Variable                                               PASSED
    2025-06-04T17:22:55: %EASYPY-INFO: |       |-- 16_Should Be Equal As Numbers                                 PASSED
    2025-06-04T17:22:55: %EASYPY-INFO: |       |-- 17_${device} = staging-leaf2                                  PASSED
    2025-06-04T17:22:55: %EASYPY-INFO: |       |-- 18_Get BGP L2VPN Summary From Device                          PASSED
    2025-06-04T17:22:55: %EASYPY-INFO: |       |-- 19_Nxapi Method Nxapi Cli                                     PASSED
    2025-06-04T17:22:55: %EASYPY-INFO: |       |-- 20_Log                                                        PASSED
    2025-06-04T17:22:55: %EASYPY-INFO: |       |-- 21_                                                           PASSED
    2025-06-04T17:22:55: %EASYPY-INFO: |       |-- 22_Set Variable                                               PASSED
    2025-06-04T17:22:55: %EASYPY-INFO: |       `-- 23_Should Be Equal As Numbers                                 PASSED
    2025-06-04T17:22:55: %EASYPY-INFO: |-- VERIFY SPINE DEVICE(S) EXPECTED NEIGHBOR COUNT via NX-API CLI J...    PASSED
    2025-06-04T17:22:55: %EASYPY-INFO: |   `-- 1_Verify BGP Neighbor Count                                       PASSED
    2025-06-04T17:22:55: %EASYPY-INFO: |       |-- 2_${device}    IN    @{device_list}                           PASSED
    2025-06-04T17:22:55: %EASYPY-INFO: |       |-- 3_${device} = staging-spine1                                  PASSED
    2025-06-04T17:22:55: %EASYPY-INFO: |       |-- 4_Get BGP L2VPN Summary From Device                           PASSED
    2025-06-04T17:22:55: %EASYPY-INFO: |       |-- 5_Nxapi Method Nxapi Cli                                      PASSED
    2025-06-04T17:22:55: %EASYPY-INFO: |       |-- 6_Log                                                         PASSED
    2025-06-04T17:22:55: %EASYPY-INFO: |       |-- 7_                                                            PASSED
    2025-06-04T17:22:55: %EASYPY-INFO: |       |-- 8_Set Variable                                                PASSED
    2025-06-04T17:22:55: %EASYPY-INFO: |       |-- 9_Evaluate                                                    PASSED
    2025-06-04T17:22:55: %EASYPY-INFO: |       |-- 10_Run Keyword If                                             PASSED
    2025-06-04T17:22:55: %EASYPY-INFO: |       |-- 11_Get Length                                                 PASSED
    2025-06-04T17:22:55: %EASYPY-INFO: |       `-- 12_Should Be Equal As Numbers                                 PASSED
    2025-06-04T17:22:55: %EASYPY-INFO: `-- VERIFY LEAF DEVICE(S) EXPECTED NEIGHBOR COUNT via NX-API CLI JS...    PASSED
    2025-06-04T17:22:55: %EASYPY-INFO:     `-- 1_Verify BGP Neighbor Count                                       PASSED
    2025-06-04T17:22:55: %EASYPY-INFO:         |-- 2_${device}    IN    @{device_list}                           PASSED
    2025-06-04T17:22:55: %EASYPY-INFO:         |-- 3_${device} = staging-leaf1                                   PASSED
    2025-06-04T17:22:55: %EASYPY-INFO:         |-- 4_Get BGP L2VPN Summary From Device                           PASSED
    2025-06-04T17:22:55: %EASYPY-INFO:         |-- 5_Nxapi Method Nxapi Cli                                      PASSED
    2025-06-04T17:22:55: %EASYPY-INFO:         |-- 6_Log                                                         PASSED
    2025-06-04T17:22:55: %EASYPY-INFO:         |-- 7_                                                            PASSED
    2025-06-04T17:22:55: %EASYPY-INFO:         |-- 8_Set Variable                                                PASSED
    2025-06-04T17:22:55: %EASYPY-INFO:         |-- 9_Evaluate                                                    PASSED
    2025-06-04T17:22:55: %EASYPY-INFO:         |-- 10_Run Keyword If                                             PASSED
    2025-06-04T17:22:55: %EASYPY-INFO:         |-- 11_Set Variable                                               PASSED
    2025-06-04T17:22:55: %EASYPY-INFO:         `-- 12_Should Be Equal As Numbers                                 PASSED
    2025-06-04T17:22:55: %EASYPY-INFO: Done!

Step 7 - Close pyATS Robot File

On the keyword press Ctrl + K + W. This should close all open tabs to clear your workspace for the next section.


Once completed, continue to the next section to get started with NetDevOps. In the next section you will take everything you have been developing and deploying to your staging (development) fabric to Git for source control then to your prod fabric through a devops process and a CI/CD pipleline.