求知 文章 文库 Lib 视频 iPerson 课程 认证 咨询 工具 讲座 Modeler   Code  
会员   
 
  
 
 
     
   
分享到
expect自动化测试脚本
 
火龙果软件    发布于 2013-11-18
 

TCL/EXPECT自动化测试脚本实例一 --- telnet到目标机器

这是一个简单的TCL/EXPECT脚本,完成telnet到远程设备的功能。通过这个例子,大家可以看到使用TCL/EXPECT脚本构造测试程序,是非常简洁的。

从今天开始,陆续把我所写的一些自动测试脚本贴上来,希望对初学者有所帮助。由于目前没有找好合适的服务器存放代码,所以代码先贴在blog的正文中,以后再提供完整的代码下载。

我的自动化测试脚本运行在debian linux下,使用/usr/bin/expect进行解释执行。为了简化处理,把一些常用的功能编写成函数,放在commonLib.exp文件中,其它脚本文件可以使用source commonLib.exp命令引用这些函数。

下面的函数完成telenet到目标机器并login。从其实现上大家可以看到tcl/expect编写测试脚本的简洁。

这个函数带有三个参数,分别是目标机器的IP地址ipaddr,登录用户名user和登录密码,telenet的端口号采用默认的23端口。

函数中使用了三个全局变量,g_prompt,g_usrPrompt和g_pwdPrompt,分别表示登录后的命令提示符,提示用户名输入的提示符,以及提示密码输入的提示符,这三个全局变量定义在global.exp中。之所以采用全局变量,是因为这些值使用比较广泛,但在不同设备中都不相同。使用全局变量可以方便修改。

代码如下:

# telnet login routine
#
# @PARAMS
# ipaddr - remote device ip address
# user   - user name to login in
# passwd - login password
#
# @RETURN
# spawn_id if login success, otherwise 0
#************************************************
proc login {ipaddr user passwd} {
    global g_prompt g_usrPrompt g_pwdPrompt
    spawn telnet $ipaddr
    expect {
        "$g_usrPrompt" {
            exp_send "$user\r\n"
            exp_continue
        }
        "$g_pwdPrompt" {
            exp_send "$passwd\r\n"
            exp_continue
        }
        -ex "$g_prompt" {
            dbgLog "Login Successful\n"
            return $spawn_id
        }
        timeout {
            send_user "timeout"
            return 0
        }
    }
}

TCL/EXPECT自动化测试脚本实例二 --- 主程

现在介绍一下测试主程序: test.exp。

为了方便加入新的测试项目,主程序采用了一种灵活的机制,它根据需要通过source命令调用相应的子测试程序。这样一来,每个测试点都可以单独放到一个文件中,然后被主程序引用。

先看一下代码:

#! /usr/bin/expect --
# $Id$
# Usage:
#    ./test [-uuser] [-ppassward] [-iip_address]  test_001 ...
# or ./test [-uuser] [-ppassward] [-iip_address] [-ccommand_file] cmd
# or ./test [-uuser] [-ppassward] [-iip_address] [-sscript_file] script
source global.exp
source commonLib.exp
# initialize variables
set cmdFile ""
set tList $argv
set execScript ""
# process options
set endOptIndex -1
foreach arg $argv {
    if {![string match "-\[a-zA-Z]*" $arg]} {
        break
    }
    # inc end option index
    incr endOptIndex
    # get option flag and option value
    set optFlg [string range $arg 1 1]
    set optVal [string range $arg 2 end]
    dbgLog "$optFlg $optVal"
    if {$optVal == ""} {
        dbgLog "option value is null: -$optFlg"
        return -1
    }
    switch $optFlg {
        "u" {
            set g_user $optVal
            dbgLog "user: $g_user"
        }
        "p" {
            set g_passwd $optVal
            dbgLog "password: $g_passwd"
        }
        "i" {
            set g_devip $optVal
            dbgLog "devip: $g_devip"
        }
        "c" {
            set cmdFile $optVal
            dbgLog "cmdFile: $cmdFile"
        }
        "s" {
            set execScript $optVal
            dbgLog "execScript: $execScript"
        }
        default {
            puts "unknown option: -$optFlg"
            return -1
        }
    } ;# end switch
} ;# end foreach
# remove options from list
if {$endOptIndex != -1} {
    set tList [lreplace $argv 0 $endOptIndex]
}
dbgLog "tList is: $tList"
# create log dir
if { ![file exist "log"] || ![file isdirectory "log"] } {
    puts "please create directory \"log\""
    return -1
}
# read current time
set clicks [clock clicks]
set tstr [clock format $clicks -format "%y%m%d%I%M%S"]
# open log file
log_file "log/vLog$tstr.log"
# open brief log file
set g_bLogFd [open "log/bLog.log" w]
# start testing
foreach tItem $tList {
    switch $tItem {
        "sys_001" { ;# test group sys_001
            source snmp.exp
        }
        "cmd" { ;# exec cmd file
            source tCmd.exp
        }
        "script" { ;# exec script file
            if {$execScript == ""} {
                puts "Please specify script name using -s option"
                return -1
            }
            source $execScript
        }
        default {
            puts "do you want to test \"$tItem\"\?"
        }
    }
}
close $g_bLogFd

在程序开始,通过source导入两个文件,其中global.exp中主要存放了一些全局变量的定义,因为这些全局变量对每台测试设备可能各不相同,所以把它们提取出来。commonLib.exp文件中存放着一些通用子程序,可供各测试程序调用。我们前面介绍过的login子程序,就放在此文件中。

接下来,分析命令行参数,首先提取出所有的选项参数,目前支持的命令行选项包括:

-u :此选项用来更改登录的用户名

-p :此选项用来更改登录的密码

-i :此选项用来更改telnet的IP地址

-c :此选项用来指明批处理文件的文件名,用法在后面描述

-s :此选项用来指明脚本文件的文件名,用法在后面描述

最后,命令行参数中所有非选项的部分,都被做为测试项,分别对这些测试项进行测试。

例如测试项test_001,会使用source命令调用snmp.exp脚本,进行snmp community方面的测试。

可以根据需要自行添加测试项目。

有两个特别的测试项名称,分别为cmd和script。

cmd测试项,会调用cmd.exp脚本,这个脚本在后面介绍,它的主要功能是执行一个文本文件里的所有命令。文本文件名由-c选项提供。

script测试项,它会调用source命令,执行$execScript脚本。可以使用-s选项为$execScript变量赋值。

这个测试脚本提供了两种日志,一种是详细的日志(vLog*),包括了telnet的所有交互过程;另外一种是简单的日志,只包含程序中使用errLog输出的信息。日志文件被放在子目录log中,其文件名中包含了脚本执行的时间,方便查找。

本脚本中使用dbgLog,以及以后将用到的errLog,都是定义在commonLib.exp文件中的子函数,代码如下:

# debug output routine

#
# @PARAMS
# arg - variable length arguments
#************************************************
proc dbgLog arg {
    global g_dbgFlag
    if {$g_dbgFlag} {
        puts $arg
    }
}
#************************************************
# error output routine
#
# @PARAMS
# arg - variable length arguments
#************************************************
proc errLog arg {
    global g_bLogFd
    global g_dbgFlag
    if {$g_dbgFlag} {
        puts $arg
    }
    if { $g_bLogFd != 0 } {
        puts $g_bLogFd $arg
    }
}

TCL/EXPECT自动化测试脚本实例三 --- 全局变量

global.exp文件的内容,只是定义一些全局变量,供其它文件使用

下面是global.exp文件的内容,只是定义一些全局变量,供其它文件使用。

# $Id$
# global variables
set g_dbgFlag   1;# Debug flag
set g_bLogFd    0;# Error Log FD
set g_devip     "192.168.1.222" ;# Default device IP address
set g_prompt    "$" ;# CLI prompt
set g_user      "root"           ;# login account name
set g_passwd    "root"           ;# login password
set g_usrPrompt "*ogin:"         ;# login prompt
set g_pwdPrompt "*assword:"      ;# login password prompt

TCL/EXPECT自动化测试脚本实例四 --- 批命令执行

在测试过程中,在具体测试某一个功能点时,往往需要为此进行大量的配置。为了简化测试过程,我们可以把所有的配置命令放在一个文本文件中,然后使用测试脚本来执行这些命令。这里讲的脚本,就可以用来执行指定的命令文件。此脚本被上一篇中介绍的test.exp调用。

在测试过程中,在具体测试某一个功能点时,往往需要为此进行大量的配置。为了简化测试过程,我们可以把所有的配置命令放在一个文本文件中,然后使用测试脚本来执行这些命令。这样就不需要再手工进行配置了,费时费力。

基于如上考虑,编写了下面的脚本tCmd.exp。这个脚本被我们前面介绍过的test.exp脚本调用。

# $Id$
# This file is used to execute specific commands list in a file
proc execCmdFile {cmdFile} {
    global g_dbgFlag g_prompt
    # enable debug
    set g_dbgFlag 1
    # login
    set spawn_id [login $g_devip $g_user $g_passwd]
    if {$spawn_id == 0} {
        errLog "login $g_devip failed"
        return 0
    }
    # open cmdFile
    set cmdFd [open $cmdFile r]
    while true {
        # get a line
        if {![getLine $cmdFd line]} {
            dbgLog "reached eof"
            break
        }
        # split the line
        set ln [split $line ","]
        set cmd [string trim [lindex $ln 0]]
        set out [string trim [lindex $ln 1]]
        if {$cmd == ""} continue
        if {$out == ""} set out $g_prompt
        # send cmd line
        exp_send "$cmd\n"
        dbgLog "send $cmd"
        # expect output
        dbgLog "expect $out"
        expect {
            timeout {
                errLog "TIMEOUT: while exec \"$cmd\""
                continue
            }
            -ex "$out" {
                continue
            }
        } ;# end expect
    }
    # close cmdFile
    close $cmdFd
}
# if no cmdFile, use default
if {$cmdFile == ""} {
    set cmdFile "cmdFile.txt"
}
execCmdFile $cmdFile

有了这个脚本,我们可以使用"./test.exp -cinterface.txt cmd"来执行interface.txt中的命令。

TCL/EXPECT自动化测试脚本实例五 --- 由文件中读取一行

这个函数由文件中读取一行,跳过空行和注释行。

代码见下,比较简单,就不再分析了。调用实例见前面的文章。

# get a line from file, skip blank lines and
# comment lines, return the reading line in
# parameter 'line'.
#
# @PARAMS
# fd     - file fd
# line   - var used to return the line
#
# @RETURN
# return 1 if read successfully, otherwise 0
#************************************************
proc getLine {fd line} {
    upvar $line ln
    # read a line from fd
    while {[set lineLen [gets $fd ln]] >= 0} {
        # blank line
        if { $lineLen == 0 } continue
        # trim whitespace
        set ln [string trim $ln]
        if { [string length $ln] == 0 } continue
        # skip comment
        if { [string index $ln 0] == "#" } continue
        # success
        return 1
    }
    return 0
}

TCL/EXPECT自动化测试脚本实例六 --- SNMP community长度测试

本文通过一个测试SNMP community最大长度的脚本,介绍自动测试SNMP agent的方法。

下面通过一个测试SNMP community最大长度的脚本,介绍一下net-snmp工具。

net-snmp是一组基于命令行的snmp manager工具,可以在命令行下进行snmp get, snmp set, snmp walk等操作,支持snmp v1/v2c/v3。原来的名字叫做ucd-snmp,也已经被移植到windows NT上。

它的主页在http://net-snmp.sourceforge.net/

由于它可以在命令行下进行SNMP操作,所以可以和TCL/expect很好的结合,完成自动化测试的功能。

下面的脚本(snmp.exp),不断的增加SNMP community,长度从1到256,每增加一个community,就调用snmp-get来进行SNMP get操作,如果get成功,说明此community有效;反之,就说明community已经超出了设备支持的最大长度。

这个脚本使用前面讲到的test.exp调用,调用方法是:

./test.exp -ssnmp.exp script

对它稍加修改,也可以直接在命令行中调用,此处不再赘述。

代码如下:

# $Id$
proc snmpCommTest {comm} {
    global g_devip
    spawn snmpget -c $comm -v 2c -r 2 $g_devip system.sysUpTime.0
    expect {
        "system.sysUpTime.0*" {
            return 1
        }
        "*Timeout*" {
            return 0
        }
    }
    return 1
}
set spawn_id [login $g_devip $g_user $g_passwd]
if {$spawn_id == 0} {
    errLog "login error\n"
    return 0
}
set cmdCommAdd "create snmp community %s rw\n"
set cmdCommDel "delete snmp community %s\n"
set cmdHostAdd "create snmp host ip 192.168.1.2 community %s\n"
set cmdHostDel "delete snmp host ip 192.168.1.2 community %s\n"
set comm ""
for {set i 1} {$i < 256} {incr i} {
    set comm "a$comm"
    set cmd [format $cmdCommAdd $comm]
    exp_send $cmd
    expect {
        "Error*" {
            errLog "create comm len $i error"
            continue
        }
        timeout {
            errLog "create comm len $i timeout"
            continue
        }
        "Entry Created"
    }
    set cmd [format $cmdHostAdd $comm]
    exp_send $cmd
    expect {
        "Error*" {
            errLog "create host error"
            continue
        }
        timeout {
            errLog "create host timeout"
            continue
        }
        "Entry Created"
    }
    set rc [snmpCommTest $comm]
    if {$rc == 0} {
        errLog "community len $i failed"
    }
    set cmd [format $cmdHostDel $comm]
    exp_send $cmd
    expect "Entry Deleted"
    set cmd [format $cmdCommDel $comm]
    exp_send $cmd
    expect "Entry Deleted"
}
相关文章

微服务测试之单元测试
一篇图文带你了解白盒测试用例设计方法
全面的质量保障体系之回归测试策略
人工智能自动化测试探索
相关文档

自动化接口测试实践之路
jenkins持续集成测试
性能测试诊断分析与优化
性能测试实例
相关课程

持续集成测试最佳实践
自动化测试体系建设与最佳实践
测试架构的构建与应用实践
DevOps时代的测试技术与最佳实践
 
分享到
 
 
     


LoadRunner性能测试基础
软件测试结果分析和质量报告
面向对象软件测试技术研究
设计测试用例的四条原则
功能测试中故障模型的建立
性能测试综述
更多...   


性能测试方法与技术
测试过程与团队管理
LoadRunner进行性能测试
WEB应用的软件测试
手机软件测试
白盒测试方法与技术


某博彩行业 数据库自动化测试
IT服务商 Web安全测试
IT服务商 自动化测试框架
海航股份 单元测试、重构
测试需求分析与测试用例分析
互联网web测试方法与实践
基于Selenium的Web自动化测试
更多...