公司要求做自动化测试,在交换芯片流片前测试芯片的功能,在palladium上跑综合网表,仿真实现芯片的功能,具体如何实现的就不细说了,不是重点TAT。我目前的工作就是负责能够用脚本SSH远程服务器,执行Linux下执行一些之前写好的测试程序(芯片的配置代码),同时在配置好芯片后,使用脚本控制测试仪,使得测试仪构造报文,发流停流等功能。
由于我们租用的思博伦测试仪版本太老,只支持TCL脚本控制,不支持Python控制。由于之前没有用过TCL,没办法也得把TCL基本语法学一遍啦。不过好在各种编程语言有一定的想通性,稍微看看试试基本语法就能编写一些测试例啦,最主要的是TCL控制思博伦测试仪的一些API比较麻烦,需要慢慢找,不过测试例跑通之后也比较好添加。
得知老板需求之后就去查解决办法啦,当时也比较死脑筋,想着底层只能用TCL控制测试例,SSH等远程功能也就用TCL实现吧。于是找啊,试啊,看着TCL的expect包好像能行,但是用着我们能够适应测试仪版本的TCL版本怎么都不行,折腾了几天没有办法SSH。没办法SSH就没有办法自动化测试,不能自动回归测试例,测试效率就会低很多啊。
后来灵机一动,既然对Python比较熟悉,何不用Python完成这一切呢,远程控制,执行TCL。用了Python感觉进度势如破竹啊,半天就基本能够搞通啦。
虽然遇到点小问题纠结了好久,Python的Tinker里面的TCL控制不了测试仪啊,版本不对啊,折腾了一天,终于通过控制Python版本(32位python2.7版本)实现了调整TCL版本控制思博伦测试仪。
哈哈哈,环境全部搭建好之后自己封装了一些类啊,写了一些函数啊,以及针对我目前的工作环境如何完整得SSH和Telnet执行完一条配置命令。由于我们有测试shaper精度以及抖动的问题,写了个画折线图以及计算平均速度最大速度最小速度的函数。保存速度数据至CSV文件,以及取SSH以及Telnet到的shell的输出的某些字段。
import logging
import telnetlib
import time
class TelnetClient(object):
def __init__(self, host_ip, username, port=23):
self.tn = telnetlib.Telnet()
self.host = host_ip
self.username = username
self.port = port
self._connect()
# telnet登录主机
def _connect(self):
try:
# self.tn = telnetlib.Telnet(host_ip,port=23)
self.tn.open(self.host, self.port)
except:
logging.warning('%s网络连接失败'%self.host)
return False
# 等待login出现后输入用户名,最多等待10秒
self.tn.read_until(b'login: ',timeout=10)
self.tn.write(username.encode('ascii') + b'\n')
# 等待Password出现后输入用户名,最多等待10秒
time.sleep(2)
# 获取登录结果
# read_very_eager()获取到的是的是上次获取之后本次获取之前的所有输出
command_result = self.tn.read_very_eager().decode('ascii')
if 'Login incorrect' not in command_result:
logging.warning('%s登录成功'%self.host)
return True
else:
logging.warning('%s登录失败,用户名错误'%self.host)
return False
# 此函数实现执行传过来的命令,并输出其执行结果
def execute_some_command(self,command):
# 执行命令
self.tn.write(command.encode('ascii')+b'\n')
time.sleep(2)
# 获取命令结果
command_result = self.tn.read_very_eager().decode('ascii')
logging.warning('命令执行结果:\n%s' % command_result)
def sendWithCheck(self, command, print_c = 1, timeout = 400):
self.tn.write(command+'\n')
recv = self.tn.read_until('kd5886>',timeout=timeout)
if print_c: print recv
return recv
def send(self, command, print_c = 1, sleeptime = 60):
self.tn.write(command+'\n')
time.sleep(sleeptime)
command_result = self.tn.read_very_eager()
if print_c : print command_result
return command_result
# 退出telnet
def close(self):
self.tn.write(b"exit\n")
if __name__ == '__main__':
host_ip = '192.168.220.129'
username = 'root'
password = 'abcd1234'
command = 'whoami'
telnet_client = TelnetClient()
class SSHConnection(object):
def __init__(self, host, username, password, port = 22):
self._host = host
self._port = port
self._username = username
self._password = password
self._ssh = None
self._shell = None
self._sftp = None
self._client = None
self._connect() # 建立连接
def _connect(self):
#创建一个ssh的白名单
ssh = paramiko.SSHClient()
know_host = paramiko.AutoAddPolicy()
#加载创建的白名单
ssh.set_missing_host_key_policy(know_host)
ssh.connect(hostname = self._host, port = self._port, username=self._username, password=self._password)
self._ssh = ssh
#执行命令
def exec_command(self, command):
if self._ssh is None:
self._ssh = paramiko.SSHClient()
stdin, stdout, stderr = self._ssh.exec_command(command)
data = stdout.read()
if len(data) > 0:
print(data.strip()) #打印正确结果
return data
err = stderr.read()
if len(err) > 0:
print(err.strip()) #输出错误结果
return err
#发送命令包含尾字符检查
def sendWithCheck(self, command, sleeptime = 1, print_c = 1, timeout = 20):
if self._ssh is None:
self._ssh = paramiko.SSHClient()
if self._shell is None:
self._shell = self._ssh.invoke_shell()
self._shell.settimeout(1000)
self._shell.send(command+'\n')
result = ''
timenow = 0
while True:
time.sleep(sleeptime)
timenow += 1
if timenow > timeout :
if print_c: print result
return result
try:
recv = self._shell.recv(9999)
result = result + recv
str_l = [line for line in result.split()]
if str_l[-1] == 'kd5886>':
if print_c: print result
return result
except:
print 'getting buff...'
#发送命令
def send(self, command, sleeptime = 1, print_c = 1):
if self._ssh is None:
self._ssh = paramiko.SSHClient()
if self._shell is None:
self._shell = self._ssh.invoke_shell()
self._shell.settimeout(1000)
self._shell.send(command+'\n')
result = ''
timenow = 0
time.sleep(sleeptime)
recv = self._shell.recv(9999)
if print_c: print recv
return recv
def close(self):
if self._ssh:
self._ssh.close()
# 折线图
def line_chart(list_t, label, title = 'title', xlabel = 'x', ylabel = 'y', filename = None):
# 数据准备
plt.figure(figsize=(8, 4))
length = len(list_t)
# 使用Matplotlib画折线图
x = np.arange(length)
plt.plot(x, list_t, label = label, linewidth=1, color='b')
plt.title("{}, max={},min={},average={}".format(title,max(list_t),min(list_t),sum(list_t)/len(list_t)))
# 横坐标描述
plt.xlabel(xlabel)
# 纵坐标描述
plt.ylabel(ylabel)
plt.legend()
fig = plt.gcf()
if filename:
fig.savefig(filename)
else:
fig.savefig("c:/wcb/%s"%title)
plt.show()
#port stati packet 时获得txrx count
def get_txrx_count(port, string):
str_l = [line for line in string.split()]
for i in range(len(str_l)):
if str_l[i] == str(55):
return int(str_l[i+1]),int(str_l[i+2])
if str_l[i] == str(port) and str_l[i+3]==str(port+1):
return int(str_l[i+1]),int(str_l[i+2])
#直接获取某个count
def getCountByStr(recvBuff, target):
recvStrList = [line for line in recvBuff.split()]
for i in range(len(recvStrList)):
if recvStrList[i] == target:
return int(recvStrList[i+1])
return None
#taget 为字符串list
def getCountByNStr(recvBuff, target):
recvStrList = [line for line in recvBuff.split()]
lengthT = len(target)
for i in range(len(recvStrList)):
if recvStrList[i:i+lengthT] == target:
return int(recvStrList[i + lengthT])
return None
def savetocsv(list1, filename = 'd:/wcb/test.csv',list2 = None):
df = pd.DataFrame()
df['list1'] = list1
if list2: df['list2'] = list2
df.to_csv(filename, encoding='gbk')
import Tkinter
tcl = Tkinter.Tk()
tcl.evalfile('d:/wcb/case3.tcl')
tcl.tk.eval('package require SpirentTestCenter')
tcl.tk.eval('source d:/wcb/case3.tcl')
tcl.eval("""
array set colorcount {
red 1
green 5
blue 4
white 9
}
""")
print tcl.eval('array names colorcount')
#Tcl的list与Python的Tuple可相互使用
tcl.setvar('list_a',(1,2))
tcl.eval("""
puts [lindex $list_a 1]
set v [list a b [list x y ] "c d e " " f {g h}"]
""")
c = tcl.getvar('v') #('a', 'b', ('x', 'y'), 'c d e ', ' f {g h}')
#从TCL中获取list后将list画成折线图,目前用于shaper分析
tcl.eval('''
set var [list 1 4 5 6 7 8 9 2 34 55]
set num 7
set num [expr $num + 1]
#在列表末尾添加str
lappend var $num
''')
var = tcl.getvar('var')
num = tcl.getvar('num')
print num
print var
print type(var)
print type(var[0])
var = list(map(int, var))
print len(var)
print var
print var[0]
print type(var[0])
line_chart(var,'rxrate',title= 'shaper',xlabel= 'num',ylabel='rate/bps',filename="d:/wcb/rate")
savetocsv(var,'d:/wcb/test_1.csv')
后面就开始自己编写一些自动化测试回归例啦,主要是调TCL代码实现测试仪的一些操作,写完之后回归测试例就只需要跑一遍就行啦,大大节省了时间同时可以利用晚上的时间进行回归。