+ 首页>>技能>>实用技巧>>内容

技能让我们把”反复重启”这项测试做得更加优雅一些367次围观

今天想跟大家分享一个话题,关于这个话题的实践,其实做起来非常容易,但是由于我们常常在硬件测试环节中看到这样的一项测试,也常常看到某些暴力低效的测试方法带给我们的痛苦……现在,我们急需改造和优化这样的测试方法,SO,跟着我,让我们通过一些简单的改造让这项测试变得更加有趣和优雅。

让我们把

DeviceReboot

我们为什么会有这样的测试需求?

通信产品的日常测试中,我们常常需要验证设备的稳定性和业务模块启动的相关性能参数,这样的一些性能参数可能包括:我们的设备规定在正常重启完毕后的两分钟内得把业务进程模块XX-THREAD(这里仅仅指代一个名称,THREAD本身不代表线程或者进程)成功拉起来,然后能够经历反复重启之后仍然保持这样一个稳定的性能状态。

明确测试需求

首先,我们通过仔细的分析之后,已经在纸上画出一些测试需求,让我们来阐述一下:

  • 我们如何控制设备的重启?
  • 我们如何知道此时设备已经重启了?而不是采用一种很暴力的wait方法?
  • 我们如何将业务模块的进程快照捕获下来?
  • 批量设备的验证如何解决?

OK,看到这里,大家是不是开始手痒了?别看这仅仅是一项小小的”反复重启”测试项,其实等待我们去做的事情非常具有挑战性。紧接着,让我们开始着手解决这个事情。亦或是,你已经想到了什么?

开始解决-古老方法

其实,我在部门工作中就常常看见同事们尝试去解决这样的事情,他们的做法通常是这样的,找一款ssh/telnet的客户端工具,然后尝试用UI自动化工具在客户端上进行连接->发送重启命令等这样的一系列事情,那么,这样的方法,究竟可不可以帮我们解决这样的问题呢?其实,真正实践下来发现,这个古老的方法勉强是可行的,但是弊端非常明显:

    1. ssh/telnet的客户端本身不稳定,通过UI自动化测试工具再去驱动他们,不稳定性可想而知。
    经常会在中途自动断开,但是测试工程师们对这样的场景恢复似乎一点办法都没有,甚至绝望。

    2. 该方法嗅探设备当前状态的过程是一种极其不灵活的方式,由于始终处于”被动”的状态,自动化脚本需要主动去探测设备的状态,中间会由此浪费很多时间。

    3.对于批量设备的验证,这种方法几乎就没有用武之地了。

终于来了!优雅的方法

OK,说到优雅,我们得从选择语言和工具开始,首先我们选择优雅的Python作为我们此次折腾的主要语言,因为Python有支持telnet/ssh设备的telnetlib和paramiko/fabric模块,解决这样的任务对于Python来讲实在是太舒畅了,其次,我们还会用到最经典的多线程协作模式-消费者/生产者。

OK,那么,我将在这里准备两个线程:

1. 一个线程专门负责去嗅探设备的当前状态,嗅探工作将通过connect实例的timeout参数去主动设置一个超时时间,这样我们可以直接避免”死等”的情况。
2.另外一个线程负责捕获业务进程状态,设置规定的重启时间,然后通过简单的进程快照捕获来判断进程是否被成功拉起来,最后进行简单的日志记录。

完整代码:

# -*- coding:utf-8 -*-
 
# About
__author__ = 'archer'
__version__ = "1.0.0"
 
'''
设备重启长拷验证
优雅方法
'''
 
from threading import Condition, Thread
from time import sleep as wait
import telnetlib
import os.path as LOGPATH
import time
 
# condition需要全局共享,以保证线程之间顺利工作
condition = Condition()
# telnet实例
devicecon = telnetlib.Telnet()
 
# 设备默认状态为关闭
devicestate = False
 
#日志记录时间戳格式
LOGTIMEFORMAT='%Y-%m-%d %X'
 
# 设备通知线程
class DeviceNotify(Thread):
 
    def run(self):
 
        global devicestate
 
        while True:
 
            # 拿锁
            condition.acquire()
            # 如果设备处于开启状态,则通知DeviceDoReboot
            if devicestate:
                condition.notify()
                condition.release()
            else:
                print "[Thread-Notify]正在检测设备状态,请稍后......"
                try:
 
                   devicecon.open('172.16.121.162',port='23',timeout=6000)
 
                except:
 
                    print("------>Error 设备连接已超时,请检查环境!")
 
                # 操作等待时间
                wait(5)
 
                # 将设备置为开并释放锁
                devicestate = True
                condition.release()
 
 
class DeviceDoReboot(Thread):
 
    def run(self):
        global devicestate
        while True:
 
            # 拿锁
            condition.acquire()
 
            # 如果设备处于开启状态,则进行关闭,
            if devicestate:
                print "[Thread-DeviceReboot]设备连接成功,开始捕获业务进程快照......"
 
                #检测模块进程状态,并记录日志
                #登录
                devicecon.read_until("XXXXX login:")
                devicecon.write("admin"+"\r\n")
 
                devicecon.read_until("Password:")
                devicecon.write("XXXXXX"+"\r\n")
 
                devicecon.read_until("#")
                devicecon.write("ps"+"\r\n")
 
                tempsnap=devicecon.read_until("#").decode('gbk')
 
                print tempsnap
 
                #追加log日志
                DeviceRebootLog=open(LOGPATH.abspath(".")+"/DeviceRebootLog.txt",mode="a")
 
                if "XXXXXX thread" in tempsnap:
 
                    DeviceRebootLog.writelines("业务模块重启成功-%s" % time.strftime(LOGTIMEFORMAT,time.localtime())+"\r\n")
 
                else:
 
                    DeviceRebootLog.writelines("业务模块重启失败-%s" % time.strftime(LOGTIMEFORMAT,time.localtime())+"\r\n")
 
                #写完后立即关掉
                DeviceRebootLog.close()
                print "业务模块检测完毕,开始重启设备......"
 
                #等待5s后开始操作
                wait(5)
 
                # 开始发送重启命令
                try:
 
                    #devicecon.read_until("#")
                    devicecon.write("reboot"+"\r\n")
 
                except:
                    pass
 
                # 重启命令发送之后等待30秒,可以手动控制长拷频率
                wait(120)
 
                # 将设备状态置为关闭
                devicestate = False
 
                # 释放
                condition.release()
 
            else:
 
                # 通知DeviceNotify线程
                condition.notify()
                condition.release()
 
 
if __name__ == "__main__":
 
    DeviceNotify().start()
    DeviceDoReboot().start()

通过这样一种简单的设计改造,我们就将获得一个非常高效的测试脚本,瞧,他运行地非常稳定:

让我们把

DeviceReboot

接下来测试人员做什么?

只要在下班前部署好这样的脚本,第二天上班时直接查看日志就可以了,我们已经打好了时间戳为了方便你进行traceback工作。

后续改造/优化

小伙伴们,相比传统的方法,这个方法直接与设备进行连接,而且支持远程部署,快速且稳定,因为他完全规避了UI层带来的风险,正如我上面提到的需求点,我们还能进一步优化这个脚本,您来试一试?

+ 猜你喜欢...

===== 关于 DiggerPlus =====
DiggerPlus是国内新锐测试人垂直内容博客,专注于挖掘测试工具,普及测试技术,专注于测试人能力提升,博客上线后就受到广大测试人的热烈追捧;此外,DiggerPlus深度整合评测资源,揭秘科技数据和真相,让读者更懂科技,更好地把玩科技。 我们始终保持"独立,客观,严谨,优秀"的优良作风,努力为读者带来源源不断的优质内容。想访问更多酷毙的测试人网站?赶紧来DiggerPlus测试人网址导航看看吧!

===== DiggerPlus Team =====
DiggerPlus Team是DiggerPlus官方发起的团队,这是一群热爱科技,热爱测试,喜欢深度挖掘的热血测试人,他们是评测师,测试专家。 我们欢迎优秀的测试人加入DiggerPlus Team。 加入DiggerPlus,可以成为我们的认证Dper,认证Dper拥有DiggerPlus独一无二的专栏并得到个人展示。

===== DiggerPlus 官方读者群 =====
DiggerPlus官方读者群(一)

+ 关于本文作者

Python/C/C++/Javascript程序员,持续学习者,目前专注于前端开发。

的专栏 | 专栏作者 | 访问小A的主页

+ 已有12个评论

开源中国精彩推送

基于开源中国OpenAPI开发
  • Copyright © 2014 DiggerPlus. 93 queries in 2.879 seconds.
    使用合作网站账号快速登录,更多精彩等着您: 开源中国