灌水 震惊!! 路由器与 Robot Framework 七型的爱🙄

小黑子 · 2024年06月10日 · 最后由 糯米团 回复于 2024年06月14日 · 5719 次阅读

一、本文的采访

1. Pekka:水文的起因是什么?

小黑子:就是看到几个好为人 "师" 的评论ಠ_ಠ ,对 RF 与路由器之间的关系很好奇,想了解 RF 是路由器的唯一,还是只是备胎 ಥ ͡ ͜ʖ ͡ಥ

2. Pekka:说 RF 是过时的工具,我感应到有些人很激动,你分析下原因?

小黑子:分为两类人。

第一类是入行早的,在 robot Framework 上有大量的时间投资和经验,甚至还有相关著作的,在听到别人说它过时了,可能会感到自己的工作和技能被贬低。所以你可以看到,明明是在说工具过时,他们却一直在争辩技术没有过时一说。

第二类是新生代的测试,一般都是在第一份工作的老项目里有稍微接触过一点,他们肯定是体验过这个工具的不尽人意之处,也在后续其他公司看到了更好的模式和更好的工具,但是本着前大佬们选用这个工具,肯定是有他们不知道的缘由的自我 PUA 心理,形成了一种崇拜,对该工具的批评可能会被视为对自己所属群体或社区的批评,然后引发他们群体认同感的反应。

如同坤坤在上面 “鸡你太美”,下面的粉丝却如听仙乐耳暂明。

3. Pekka:传统企业真大多用的是 RF 吗?

小黑子: 这一行忘了一件事,早期 功能验证、自动化测试、性能测试 是三个岗位,那就造成自动化测试工程师选用测试工具时,得考虑非编程背景的功能测试人员,在那个时候,RF 无疑是最好的选择。像路由器测试这种岗位,招功能测试的要求侧重点是懂网络协议,招自动化测试侧重点是测试工具使用和基础编程能力,得益于 RF 的工具特性,这帮自动化的工作内容是天天在排错、维护用例、解决灵活性不足的问题🤣。且这种企业的版本迭代速度不快,公司出生得早又死得慢,所以很多自动化项目一直沿用下来,新人不敢乱改,老人需要吃老本,所以 RF 在这类企业中存活下来。

4. Pekka:你用过 RF 吗?

小黑子: 刚入行时用过,感觉不好用后也几乎没去深入学过。这里放两个用例可以自行体会下,新生代的测试应该 没有人会想不开 去选用 RF 作为落地自动化的工具吧,还有 RF 记得注意空格🤣

用例是:搜索 “robot framework”,然后在睡眠 5 秒后关闭浏览器

*** Settings ***
Library    SeleniumLibrary

*** Variables ***
${URL}    https://www.baidu.com
${SEARCH_TERM}    robot framework
${IMPLICIT_WAIT}    10

*** Test Cases ***
打开百度搜索
    Open Browser    ${URL}    chrome
    Set Selenium Implicit Wait    ${IMPLICIT_WAIT}
    Input Text    id=kw    ${SEARCH_TERM}
    Click Button    id=su
    Sleep    5
    Close Browser

import time
import pytest
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.common.exceptions import TimeoutException
import logging

# 配置日志,仅记录错误级别及以上的日志
logging.basicConfig(level=logging.ERROR)
logger = logging.getLogger(__name__)

@pytest.fixture(scope="function")
def browser():
    # 初始化浏览器
    driver = webdriver.Chrome()  # ChromeDriver路径
    yield driver
    # 关闭浏览器
    driver.quit()

def wait_for_element(driver, by, value, timeout=10):
    """等待元素出现并返回元素对象"""
    try:
        element = WebDriverWait(driver, timeout).until(
            EC.presence_of_element_located((by, value))
        )
        return element
    except TimeoutException:
        logger.error(f"元素 {value}{timeout} 秒内未加载完成")
        raise

def test_baidu_search(browser):
    url = 'https://www.baidu.com'
    search_term = 'robot framework'
    search_box_id = 'kw'
    search_button_id = 'su'

    # 打开百度首页
    browser.get(url)

    # 等待搜索框加载并出现
    search_box = wait_for_element(browser, By.ID, search_box_id)

    # 在搜索框中输入搜索词
    search_box.send_keys(search_term)

    # 等待搜索按钮加载并出现
    search_button = wait_for_element(browser, By.ID, search_button_id)

    # 点击搜索按钮
    search_button.click()

    # 睡眠5秒
    time.sleep(5)

if __name__ == "__main__":
    pytest.main()

5. Pekka:那你觉得 RF 没有使用价值了吗?

小黑子: 我保留意见,反正我不用🤣,这种问题没有答案,总有人会试图证明一个不好用的工具好用在哪里。我趋利避害,哪个更好用就用哪个,不好用的那个就是过时

6. Pekka:我看原话是 “交换机、防火墙、路由器等硬件设备”,你怎么只提路由器?

小黑子:以复杂度来说,路由器比防火墙和交换机更复杂 。以自动化需求来说,路由器和防火墙通常更频繁地需要自动化。但这里的防火墙指的是企业级的防火墙设备,所以选用了较为常见的路由器🤣

7. Pekka:你测试过路由器?

小黑子:完全没有,但测试一个新的项目只需要做到知道 ‘测啥’ 和 ‘咋测’ 就可以开展测试,这里可以查查资料了解🤣:

  • 功能

    • 配置类:端口配置、接口配置、中继板卡配置、自身信息配置
    • 状态信息类:端口状态、板卡状态、连接状态、CPU、内存、流量计数、时钟同步、告警信息
    • 协议组网类:IPv4、IPv6、动态路由协议 OSPF、ISIS、BGP、MPLS、ARP、组播协议、各个协议的一致性、路由选路策略
    • 安全类:Psec 支持、访问控制、安全审计与事件管理、系统日志与操作日志、数据加密、抗重放、抗攻击、流量限速
  • 性能

    • RFC 2544 标准:吞吐量、时延、丢包率、背靠背、时延抖动、错包统计
    • 传输层、会话层、表示层和应用层模拟各种实际业务场景的流量:在线视频直播业务、视频点播业务、视频监控业务、语音通话业务、文件传输业务
  • 稳定性

    • 长期运行稳定性:测试设备在长时间运行(如数天或数周)时的稳定性,包括系统是否会出现崩溃、死锁、内存泄漏等问题。
    • 丢包率和时延变化:监测设备在持续负载或高负载下的数据传输情况,评估丢包率和时延的变化情况,以确定设备在各种负载条件下的性能稳定性。
    • 异常流量处理:测试设备在面对突发流量、异常流量或大规模攻击时的表现,包括设备是否能够正确识别和处理异常流量,以及是否能够保持正常的数据传输。
  • 管理控制

    • 远程登录、本地管理、在线升级、网管的支持能力

8. Pekka:那路由器的自动化只能用 RF 完成吗?

小黑子:其实这点我也蛮奇怪的,为什么有人会有这个想法?🤣,甚至还拿它做为 RF 不过时的证据🤣。

  • 路由器配置类测试:

    • 路由器大部分配置类的测试用例都可以转换为自动化用例,路由器有本地的 web 接口,只要能支持 http 协议请求,就能对配置项进行增删改查,配置的结果也会有响应让你做断言🤣。
    • 路由器支持 ssh 远程登录管理,通过登录路由器的后台执行命令行,实现对配置项的增删改查🤣
  • 性能类测试:

    • 长时间稳定性的测试:只需要连接上路由器的网络,然后通过自动化工具如 selenium 等,做上网、下载、看视频、组网播放等操作就行。然后通过查询日志是否有重启或者卡死等记录即可
    • 网络性能测试:搞路由器的公司都会整 Xena Networks 测试仪和 IXIA 测试仪,这两个高性能网络测试设备都提供了 Python API

综上所述,路由器的自动化跟 RF 完全就不是什么绑定的关系,任何一个能支持大量第三方库的测试工具都能做路由器的自动化🤣

9. Pekka:真的吗? 那你用 pytest 写写看?

小黑子: 首先准备测试环境
用华为的 ensp 仿真,搭一个最简单的网络 cloud+ 路由器,虚机里的路由器跟我在同一个网段,我就能在本地电脑远程访问和配置

路由器设置指令

###配置路由器
sys
sysname AR3260
interface GigabitEthernet0/0/0
ip address 192.168.5.66 255.255.255.0
quit

###配置AAA模式和ssh用户信息
aaa
local-user admin password cipher Huawei@123
local-user admin privilege level 15
local-user admin service-type ssh
quit

### 启用VTY接口上的SSH服务
user-interface vty 0 4
authentication-mode aaa
protocol inbound ssh
quit

###启用 SSH 服务,并配置相关参数。
ssh user admin authentication-type password
stelnet server enable

save

一、功能类用例:主要是配置类或者一些日常巡检指令,具体的方式是通过 SSH 登录路由器,发送路由器指令进行配置操作
这里写个 demo

import paramiko
import time 
import pytest 

# 配置信息:路由器
hostName = '192.168.5.66'
port = 22
userName = 'admin'
passWord = 'Huawei@123'


@pytest.fixture(scope='module')
def ssh_client():
    #创建SSH客户端
    client = paramiko.SSHClient()
    client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
    try:
      # look_for_keys参数需要设置为False,以防止程序自动搜索和添加SSH密钥,然后一直连接不上
      client.connect(hostName, port, userName, passWord,look_for_keys=False)
      ssh_shell = client.invoke_shell()
      yield ssh_shell,client
    finally:
      # 关闭SSH连接
      client.close()

def execute_command(ssh_shell, command, delay=1):
    ssh_shell.send(command + '\n')
    time.sleep(delay)
    output = ''
    while ssh_shell.recv_ready():
        output += ssh_shell.recv(65535).decode('utf-8')
    return output

# 1 . 检查设备版本
def test_check_device_version(ssh_client):
    ssh_shell, client = ssh_client
    command = 'display version'
    output = execute_command(ssh_shell, command)
    assert 'Huawei AR3260' in output, "设备版本检查失败"

 #  2 . 检查网络
def test_ping_to_internet(ssh_client):
  ssh_shell,client = ssh_client
  command = "ping -c 1 8.8.8.8"
  output = execute_command(ssh_shell,command)
  assert "ttl" in output.lower(), f"{command}测试失败"

# 3. 检查IP配置
def test_check_ip_config(ssh_client):
    ssh_shell, client = ssh_client
    command = 'display ip interface brief'
    output = execute_command(ssh_shell, command)
    assert '192.168.5.66/24' in output, "IP配置异常"


if __name__ == "__main__":
    pytest.main(["-vs", __file__])

这里截图证明下,真的可以访问的,没有骗各位🤣


二、检查 WiFi 性能也是没问题的,借助 ipref3,自己根据需要添加场景和加入到 pytest 里

import subprocess
import json
import time

def run_iperf3(server, port=5201):
    command = [r'D:\ipref3\iperf3.exe', '-c', server, '-p', str(port), '-J']
    try:
        start_time = time.time() 
        result = subprocess.run(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, check=True)
        end_time = time.time()  # 记录结束时间
        output = result.stdout.decode('utf-8')
        json_output = json.loads(output)
        return json_output, start_time, end_time
    except subprocess.CalledProcessError as e:
        print(f"指令 '{e.cmd}' 退出状态 {e.returncode}.")
        print(f"stderr: {e.stderr.decode('utf-8')}")
        return None

# demo
server_ip = "192.168.5.47"  # 替换为实际的服务器 IP 地址
result, start_time, end_time = run_iperf3(server_ip)
if result:
    # 
    start_timestamp = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(start_time))
    end_timestamp = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(end_time))
  # 计算平均带宽,并保留小数点后两位
    avg_bandwidth = round(result.get('end', {}).get('sum_received', {}).get('bits_per_second', 0) / 1e6, 2)

    print(f"测试开始时间: {start_timestamp}")
    print(f"平均带宽: {avg_bandwidth} Mbps")
    print(f"测试结束时间: {end_timestamp}")
else:
    print("iperf3 测试失败。")

运行结果

服务端

三、模拟 DHCP 请求拿 IP 地址

from scapy.all import *


client_mac1 = RandMAC()
ifaces = 'Realtek PCIe GbE Family Controller'

# 定义一个函数来发送DHCP Discover消息
def send_dhcp_discover():
    # 创建DHCP Discover消息
    print("发送 DHCP Discover 信息...")
    xid_random=random.randint(1,999999999)
    dhcp_discover = Ether(src=client_mac1,dst="ff:ff:ff:ff:ff:ff") / \
                    IP(src="0.0.0.0", dst="255.255.255.255") / \
                    UDP(dport=67,sport=68) / \
                    BOOTP(xid = xid_random ,chaddr=mac2str(client_mac1)) / \
                    DHCP(options=[("message-type", "discover"), "end"])

    # 发送DHCP Discover消息

    sendp(dhcp_discover,iface=ifaces)
def send_dhcp_request(client_mac, server_ip,client_chaddr,client_xid,client_yiaddr):
    print("发送 DHCP Request...")
    dhcp_request = Ether(src=client_mac,dst="ff:ff:ff:ff:ff:ff") / \
                   IP(src="0.0.0.0", dst="255.255.255.255") / \
                   UDP(sport=68, dport=67) / \
                   BOOTP(chaddr=client_chaddr, xid=client_xid) / \
                   DHCP(options=[("message-type", "request"), ("server_id", server_ip), ("requested_addr", client_yiaddr), "end"])
    print(f'物理地址{client_mac},申请到的IP{client_yiaddr}')
    # 发送DHCP Request消息
    sendp(dhcp_request, verbose=1,iface=ifaces)

def demo(pkt):
    if pkt["DHCP options"].options[0][1] == 2:
        print("收到DHCP Offer")
        print(pkt[DHCP].options[1][1])
        send_dhcp_request(pkt[Ether].dst,pkt[DHCP].options[1][1],pkt[BOOTP].chaddr, pkt[BOOTP].xid,pkt[BOOTP].yiaddr)
        print("正在分配ip%s" %(pkt[BOOTP].yiaddr))
        if pkt[DHCP].options[0][1]==5:
            print("已经分配ip%s" %(pkt[BOOTP].yiaddr))

send_dhcp_discover()
data = sniff(filter="udp and (port 67 or 68)", count=5,prn=demo,iface='网卡名')

抓包证明下🤣

10. Pekka:你觉得培训机构怎样?

小黑子:
培训机构并非贬义的代名词,早期互联网资料不足时,很多工友都是通过培训机构入的行。但是在 gpt 的时代,其实学什么东西都可以让 AI 进行辅助了。像入门路由器的测试,用 网络资料 +TCP/IP +chatgpt 足以🤣

11. Pekka:你怎么看 “没有过时的技术,只有过时的人”?

小黑子:除了利益是永不过时,其他都是屁🤣。市场的一切选择都是利润二字,不能直接创造经济价值的岗位就更别提自己个体的所谓实力了,应该照照镜子,问下自己是不是有目前风口业务的经验 还有 年不年轻

12. Pekka:你写这个的目的是?

小黑子: 主要是学习下怎么给路由器写自动化,同时不爽 一小部分 通过身份和经验施压新人,打压质疑的现象。人设总是谦虚向上,实际嗅到一丁点质疑,就表现出强烈的反感和抵触,典型的当婊子还想立牌坊🤣

13. Pekka:你这样说,是不是太伤他们了?

小黑子:


共收到 34 条回复 时间 点赞

好评如潮,赞了,怼他丫的

有个别老屁股真特么挺恶心
之前有个帖子被关闭讨论,傻鸟非要补充一下引战人是我

上手使用再发帖,这很好。
上周看过那篇充满争论的帖子,那些 “老师傅” 说话确实有股异味在里面。

我是来学习路由器是怎么测试的

几年前刚毕业实习的时候在某 Top 安全厂商搞数通也是用的 RF,还不是很懂当时。不过现阶段看也没合适的去做数通相关的。

牛逼!

能折腾是一个很大的优点

RF 属于不用自己去维护脚本的话,听起来还行,毕竟能支持接口和 UI 自动化,不考虑执行人员技能提升是还能用着
另外关键字不满足时,其实还是得自己写脚本新增关键字,新人还是别研究了,对自己没提升的

雪怪 回复

五年 RF 用户说一下对 RF 的使用感受:
RF 的优点:

  1. 支持度丰富,我们同时做 mobile 端和 web 端的 UI 自动化, 分别使用 appiumlibrary 和 seleniumlibrary 就能写,而且主要的操作、验证这些都有了自带的关键字可以直接使用。
  2. 天然的关键字驱动的语法,适配 BDD 的用例格式。这在传统行业、外企里面很实用。
  3. 扩展很简单,就是正常的 python 封装方法,然后引入文件之后就能直接使用方法名来调用。
  4. 支持 allure report , 可以跟其他框架使用同样的 report 。

RF 的缺点:

  1. 如果直接用 RF 的语法去处理数据、写 for 循环、做判断等等,是很不方便和维护的,对我来说语法很奇怪。 所以我要求对于复杂的处理,都用 python 直接去封装,不要用 RF 去写别扭的逻辑。
  2. debug 不方便。 所以我很少去 debug。
  3. 处理数据不发表,不适合写 API 的用例。 所以 API 我们用的还是 pytest 。

总结: 没有最好的工具,只有最适合的工具。自己能用得顺手就可以了。

怎么能成为下一个 “小黑子”@ 小黑子

你也要成为鸽鸽的粉丝吗

没必要吐槽 RF 和使用 pytest 写脚本证明啥的。
夸张的说 python 现在的支持的库多的几乎没有没不涵盖的,这和什么测试框架没有关系。

刚做自动化时自然会接触 RF,本能就 skip 了,因为也搞过个使用 excel+unittest 做类似关键词驱动的东西玩玩,太不灵活了,哪有写脚本灵活。但对于项目关联角度来说,选择框架还是很有用的,pytest 也是目前最好的选择了。

有的项目已经 7、8 年了,用了目前看来已经 “过时” 的框架,如果这块业务还在运营,大裁员环境下,还有人有多的余力去大改造吗,小改小调是不是还得懂些 “过时” 的框架.

至于 “培训” 嘛,只能说挣钱不寒碜

蛋蛋后

JoyMao 回复

我是对先前那个相关帖子评论区的回复。RF 本来就不值得吐槽,除了老项目,真的很少有人拿去搞事了

目前工作就是测网关路由器的测试,但大部分都是手工测,自动化只有一部分实现了

膜拜大佬,啥时候怼怼那些效能和测试 helloworld 专家老中医😀

小黑子 回复

已经成为了😈

Round 回复

那你这个行业挺稳的,手工越多越稳

我们公司就用的 RF,入职实在受不了那个臃肿的语法,自己写了个框架,RF 只作为调用层和出报告,作为调用 Python 的框架还是挺好用的😏

小黑子 回复

不懂管理员为什么不处理这种涉嫌靠抄袭来给自己公众号引流的账号,而且还在每篇里面挂链接买书呢
PS 后面会不会把这些 “原创合集” 拿去出书卖钱?

Jerry li 回复

因为社区需要内容,所以对于每个账号,只要不是很离谱的内容,一般我们都抱持 “容忍” 的态度。经过大家的投诉,确认 “大话性能” 这一账号多次使用他人内容却没有注明原创来源,我们已经要求规范操作,并加强审核的审慎性。

只是没有标记原创这么简单吗?

  1. 像楼上被翻出来的例子 ,明显从其他地方搬过来的内容却标记了原创,这是在变相鼓励抄袭?
  2. 被发现抄的还是站里面其他小伙伴的精华文章也不被处理,连水友们为社区贡献的内容也不保护?
  3. 明显是靠不停搬运文章来给自己引流,甚至卖书,对站内可能上当受骗的小伙伴的保护呢?
Jerry li 回复

兄弟算了,有些事不上称没四两重,上称了一千斤也打不住,毕竟也是公益社区,管理员们也是用爱发电,不可能有面面俱到的

建议封号

我觉得已经确定是复制的文章,可以要求删了,要不然以后谁愿意认真写了。。。直接爬虫走起

小黑子 回复

好啦好啦,在处理……

大胆质疑,小心求证,文辞犀利,讽刺辛辣,是个生猛的后生!
一边是秀代码摆事实,一边是鸡汤式的 “没有过时的技术,只有过时的人”,高下立判!
楼主很像一位论坛故人,他已经很多日子没动静了,传说是考公上岸了,真是他之幸,论坛之憾。不过,今日有了楼主这样的猛将,堪可弥补那位故人引退之遗憾了。

哈哈,我一度以为是这个是小号,你说的应该是香蕉君头像的号,和我一样的想法

可能我编程能力有限吧,用 pytest 写的框架编写自动化用例,用例管理太不直观了,还是 RF 用例管理好,清晰明了

那篇文章看了,其实就是进这一行早的吃到红利,倚老卖老而已,有本事到现在这时代试试

需要 登录 后方可回复, 如果你还没有账号请点击这里 注册