使用shell脚本进行功能测试.docx
《使用shell脚本进行功能测试.docx》由会员分享,可在线阅读,更多相关《使用shell脚本进行功能测试.docx(16页珍藏版)》请在冰豆网上搜索。
使用shell脚本进行功能测试
使用Bashshell脚本进行功能测试
功能测试是软件开发的一个关键部分--而已经装入Linux的Bash可以帮您轻而易举地完成功能测试。
在本文中,AngelRivera将说明如何运用Bashshell脚本通过行命令来执行Linux应用程序的功能测试。
由于此脚本依赖于命令行的返回码,因而您不能将这种方法运用于GUI应用程序
功能测试是开发周期的一个阶段,在这个阶段中将测试软件应用程序以确保软件的函数如预期的那样,同时能正确处理代码中错误。
此项工作通常在单个模块的单元测试结束之后,在负载/重压条件下整个产品的系统测试之前进行的。
市场上有许多测试工具提供了有助于功能测试的功能。
然而,首先要获取它们,然后再安装、配置,这将占用您宝贵的时间和精力。
Bash可以帮您免去这些烦琐的事从而可以加快测试的进程。
使用Bashshell脚本进行功能测试的优点在于:
Bashshell脚本已经在Linux系统中安装和配置好了。
不必再花时间准备它。
可以使用由Linux提供的文本编辑器如vi创建和修改Bashshell脚本。
不需要再为创建测试程序而获取专门的工具。
如果已经知道了如何开发Bourne或Kornshell脚本,那对于如何运用Bashshell脚本已经足够了。
对您来说,学习曲线已不存在了。
Bashshell提供了大量的编程构造用于开发从非常简单到中等复杂的脚本。
将脚本从Korn移植到Bash时的建议
如果已有现成的Kornshell脚本,而想要将它们移植到Bash,就需要考虑下列情况:
Korn的"print"命令在Bash中不能使用;而是改为使用"echo"命令。
需要将脚本的第一行:
#!
/usr/bin/ksh
修改成:
#!
/bin/bash
创建Bashshell脚本进行功能测试
这些基本的步骤和建议适用于许多在Linux上运行的客户机/服务器应用程序。
记录运行脚本的先决条件和主要步骤
将操作分成若干个逻辑组
基于一般方案制定执行步骤
在每个shell脚本中提供注释和说明
做一个初始备份以创建基准线
检查输入参数和环境变量
尝试提供"usuage"反馈
尝试提供一个"安静"的运行模式
当出现错误时,提供一个函数终止脚本
如可能,提供可以执行单个任务的函数
当显示正在生成的输出时,捕获每个脚本的输出
在每个脚本内,捕获每个行命令的返回码
计算失败事务的次数
在输出文件中,突出显示错误消息,以便于标识
如有可能,"实时"生成文件
在执行脚本的过程中提供反馈
提供脚本执行的摘要
提供一个容易解释的输出文件
如有可能,提供清除脚本及返回基准线的方法
下面详细讲述了每一条建议以及用于说明问题的脚本。
若要下载此脚本,请参阅本文后面的参考资料部分。
1.记录运行脚本的先决条件和主要步骤
记录,尤其是以有自述标题的单个文件(例如"README-testing.txt")记录功能测试的主要想法是很重要的,包括,如先决条件、服务器和客户机的设置、脚本遵循的整个(或详细的)步骤、如何检查脚本的成功/失败、如何执行清除和重新启动测试。
2.将操作分成若干个逻辑组
如果仅仅执行数量非常少的操作,可以将它们全部放在一个简单的shell脚本中。
但是,如果需要执行一些数量很多的操作,那最好是将它们分成若干个逻辑集合,例如将一些服务器操作放在一个文件而将客户机操作放在在另一个文件中。
通过这种方法,划分适当的颗粒度来执行测试和维护测试。
3.基于一般方案制定执行步骤
一旦决定对操作进行分组,需要根据一般方案考虑执行操作的步骤。
此想法是模拟实际生活中最终用户的情形。
作为一个总体原则,只需集中测试80%最常调用函数的20%用法即可。
例如,假设应用程序要求3个测试组以某个特定的顺序排列。
每个测试组可以放在一个带有自我描述文件名(如果可能)的文件中,并用号码来帮助识别每个文件的顺序,例如:
1.fvt-setup-1:
Toperforminitialsetup.
2.fvt-server-2:
Toperformservercommands.
3.fvt-client-3:
Toperformclientcommands.
4.fvt-cleanup:
Tocleanupthetemporaryfiles,
inordertopreparefortherepetition
oftheabovetestcases.
4.在每个shell脚本中提供注释和说明
在每个shell脚本的头文件中提供相关的注释和说明是一个良好的编码习惯。
这样的话,当另一个测试者运行该脚本时,测试者就能清楚地了解每个脚本中测试的范围、所有先决条件和警告。
下面是一个Bash脚本"test-bucket-1"的示例。
#!
/bin/bash
#
#Name:
test-bucket-1
#
#Purpose:
#Performsthetest-bucketnumber1forProductX.
#(Actually,thisisasampleshellscript,
#whichinvokessomesystemcommands
#toillustratehowtoconstructaBashscript)
#
#Notes:
#1)TheenvironmentvariableTEST_VARmustbeset
#(asanexample).
#2)Toinvokethisshellscriptandredirectstandard
#outputandstandarderrortoafile(suchas
#test-bucket-1.out)dothefollowing(the-sflag
#is"silentmode"toavoidpromptstotheuser):
#
#./test-bucket-1-s2>&1|teetest-bucket-1.out
#
#Returncodes:
#0=Allcommandsweresuccessful
#1=Atleastonecommandfailed,seetheoutputfile
#andsearchforthekeyword"ERROR".
#
########################################################
5.做一个初始备份以创建基准线
您可能需要多次执行功能测试。
第一次运行它时,也许会找到脚本或进程中的一些错误。
因而,为了避免因从头重新创建服务器环境而浪费大量时间--特别是如果涉及到数据库--您在测试之前或许想做个备份。
在运行完功能测试之后,就可以从备份中恢复服务器了,同时也为下一轮测试做好了准备。
6.检查输入参数和环境变量
最好校验一下输入参数,并检查环境变量是否设置正确。
如果有问题,显示问题的原因及其修复方法,然后终止脚本。
当测试者准备运行脚本,而此时如果没有正确设置脚本所调用的环境变量,但由于发现及时,终止了脚本,那测试者会相当感谢。
没有人喜欢等待脚本执行了很久却发现没有正确设置变量。
#--------------------------------------------
#Mainroutineforperformingthetestbucket
#--------------------------------------------
CALLER=`basename$0`#TheCallername
SILENT="no"#Userwantsprompts
let"errorCounter=0"
#----------------------------------
#Handlekeywordparameters(flags).
#----------------------------------
#FormoresophisticatedusageofgetoptinLinux,
#seethesamplesfile:
/usr/lib/getopt/parse.bash
TEMP=`getopths$*`
if[$?
!
=0]
then
echo"$CALLER:
Unknownflag(s)"
usage
fi
#Notequotesaround`$TEMP':
theyareessential!
evalset--"$TEMP"
whiletrue
do
case"$1"in
-h)usage"HELP";shift;;#Helprequested
-s)SILENT="yes";shift;;#Promptnotneeded
--)shift;break;;
*)echo"Internalerror!
";exit1;;
esac
done
#------------------------------------------------
#Thefollowingenvironmentvariablesmustbeset
#------------------------------------------------
if[-z"$TEST_VAR"]
then
echo"EnvironmentvariableTEST_VARisnotset."
usage
fi
关于此脚本的说明如下:
使用语句CALLER=`basename$0`可以得到正在运行的脚本名称。
这样的话,无须在脚本中硬编码脚本名称。
因此当复制脚本时,采用新派生的脚本可以减少工作量。
调用脚本时,语句TEMP=`getopths$*`用于得到输入变量(例如-h代表帮助,-s代表安静模式)。
语句[-z"$X"]和echo"TheenvironmentvariableXisnotset."以及usage都是用于检测字符串是否为空(-z),如果为空,随后就执行echo语句以显示未设置字符串并调用下面要讨论的"usage"函数。
若脚本未使用标志,可以使用变量"$#",它可以返回正在传递到脚本的变量数量。
7.尝试提供"usage"反馈
脚本中使用"usage"语句是个好主意,它用来说明如何使用脚本。
#----------------------------
#Subroutinetoechotheusage
#----------------------------
usage()
{
echo"USAGE:
$CALLER[-h][-s]"
echo"WHERE:
-h=help"
echo"-s=silent(noprompts)"
echo"PREREQUISITES:
"
echo"*TheenvironmentvariableTEST_VARmustbeset,"
echo"*suchas:
"
echo"exportTEST_VAR=1"
echo"$CALLER:
exitingnowwithrc=1."
exit1
}
调用脚本时,使用"-h"标志可以调用"usage"语句,如下所示:
./test-bucket-1-h
8.尝试使用"安静"的运行模式
您或许想让脚本有两种运行模式:
在"verbose"模式(您也许想将此作为缺省值)中提示用户输入值,或者只需按下Enter继续运行。
在"silent"模式中将不提示用户输入数据。
下列摘录说明了在安静模式下运用所调用标志"-s"来运行脚本:
#-------------------------------------------------
#EverythingseemsOK,promptforconfirmation
#-------------------------------------------------
if["$SILENT"="yes"]
then
RESPONSE="y"
else
echo"The$CALLERwillbeperformed."
echo"Doyouwishtoproceed[yorn]?
"
readRESPONSE#Waitforresponse
[-z"$RESPONSE"]&&RESPONSE="n"
fi
case"$RESPONSE"in
[yY]|[yY][eE]|[yY][eE][sS])
;;
*)
echo"$CALLERterminatedwithrc=1."
exit1
;;
esac
9.当出现错误时,提供一个函数终止脚本
遇到严重错误时,提供一个中心函数以终止运行的脚本不失为一个好主意。
此函数还可提供附加的说明,用于指导在此情况下应做些什么:
#----------------------------------
#Subroutinetoterminateabnormally
#----------------------------------
terminate()
{
echo"Theexecutionof$CALLERwasnotsuccessful."
echo"$CALLERterminated,exitingnowwithrc=1."
dateTest=`date`
echo"Endoftestingat:
$dateTest"
echo""
exit1
}
10.如有可能,提供可以执行简单任务的函数
例如,不使用许多很长的行命令,如:
#--------------------------------------------------
echo""
echo"CreatingAccesslists..."
#--------------------------------------------------
Access-create-componentDevelopment-loginted-authorityplead-verbose
if[$?
-ne0]
then
echo"ERRORfoundinAccess-create-componentDevelopment-loginted
-authorityplead"
let"errorCounter=errorCounter+1"
fi
Access-create-componentDevelopment-loginpat-authoritygeneral-verbose
if[$?
-ne0]
then
echo"ERRORfoundinAccess-create-componentDevelopment-loginpat
-authoritygeneral"
let"errorCounter=errorCounter+1"
fi
Access-create-componentDevelopment-loginjim-authoritygeneral-verbose
if[$?
-ne0]
then
echo"ERRORfoundinAccess-create-componentDevelopment-loginjim
-authoritygeneral"
let"errorCounter=errorCounter+1"
fi
......而是创建一个如下所示的函数,此函数也可以处理返回码,如果有必要,还可以增加错误计数器:
CreateAccess()
{
Access-create-component$1-login$2-authority$3-verbose
if[$?
-ne0]
then
echo"ERRORfoundinAccess-create-component$1-login$2-authority$3"
let"errorCounter=errorCounter+1"
fi
}
......然后,以易读和易扩展的方式调用此函数:
#-------------------------------------------
echo""
echo"CreatingAccesslists..."
#-------------------------------------------
CreateAccessDevelopmenttedprojectlead
CreateAccessDevelopmentpatgeneral
CreateAccessDevelopmentjimgeneral
11.当显示正在生成的输出时,捕获每个脚本的输出
如果脚本不能自动地将输出发送到文件的话,可以利用Bashshell的一些函数来捕获所执行脚本的输出,如:
./test-bucket-1-s2>&1|teetest-bucket-1.out
让我们来分析上面的命令:
"2>&1"命令:
使用"2>&1"将标准错误重定向到标准输出。
字符串"2>&1"表明任何错误都应送到标准输出,即UNIX/Linux下2的文件标识代表标准错误,而1的文件标识代表标准输出。
如果不用此字符串,那么所捕捉到的仅仅是正确的信息,错误信息会被忽略。
管道"|"和"tee"命令:
UNIX/Linux进程和简单的管道概念很相似。
既然这样,可以做一个管道将期望脚本的输出作为管道的输入。
下一个要决定的是如何处理管道所输出的内容。
在这种情况下,我们会将它捕获到输出文件中,在此示例中将之称为"test-bucket-1.out"。
但是,除了要捕获到输出结果外,我们还想监视脚本运行时产生的输出。
为达到此目的,我们连接允许两件事同时进行的"tee"(T-形管道):
将输出结果放在文件中同时将输出结果显示在屏幕上。
其管道类似于:
process-->T--->outputfile
|
V
screen
如果只想捕获输出结果而不想在屏幕上看到输出结果,那可以忽略多余的管道:
./test-bucket-1-s2>&1>test-bucket-1.out
假若这样,相类似的管道如下:
process-->outputfile
12.在每个脚本内,捕获每个行命令所返回码
决定功能测试成功还是失败的一种方法是计算已失败行命令的数量,即返回码不是0。
变量"$?
"提供最近所调用命令的返回码;在下面的示例中,它提供了执行"ls"命令的返回码。
#-------------------------------------------
#Thecommandsarecalledinasubroutine
#sothatreturncodecanbe
#checkedforpossibleerrors.
#-------------------------------------------
ListFile()
{
echo"ls-al$1"
ls-al$1
if[$?
-ne0]
then
echo"ERRORfoundin:
ls-al$1"
let"errorCounter=errorCounter+1"
fi
}
13.记录失败事务的次数
在功能测试中决定其成功或失败的一个方法是计算返回值不是0的行命令数量。
但是,从我个人的经验而言,我习惯于在我的Bashshell脚本中仅使用字符串而不是整数。
在我所参考的手册中没有清楚地说明如何使用整数,这就是我为什么想在此就关于如何使用整数和计算错误(行命令失败)数量的方面多展开讲的原因:
首先,需要按如下方式对计数器变量进行初始化:
let"errorCounter=0"
然后,发出行命令并使用$?
变量捕获返回码。
如果返回码不是0,那么计数器增加1(见蓝色粗体语句):
ListFile()
{
echo"ls-al$1"
ls-al$1
if[$?
-ne0]
then
echo"ERRORfoundin:
ls-al$1"
let"errorCounter=errorCounter+1"
fi
}
顺便说一下,与其它变量一样,可以使用"echo"显示整数变量。
14.在输出文件中,为了容易标识,突出显示错误消息
当遇到错误(或失败的事务)时,除了错误计数器的数量会增加外,最好标识出此处有错。
较理想的做法是,字符串有一个如ERROR或与之相似的子串(见蓝色粗体的语句),这个子串允许测试者很快地在输出文件中查找到错误。
此输出文件可能很大,而且它对于迅速找到错误非常重要。
ListFile()
{
echo"ls-al$1"
ls-al$1
if[$?
-ne0]
then
echo"ERRORfoundin:
ls-al$1"
let"errorCounter=errorCounter+1"
fi
}
15.如有可能,"实时"生成文件
在某些情况下,有必要处理应用程序使用的文件。
可以使用现有文件,也可以在脚本中添加语句来创建文件。
如果要使用的文件很长,那最好将其作为独立的实体。
如果文件很小而且内容简单或不相关(重要的一点是文本文件而不考虑它的内容),那就可以决定"实时"创建这些临时文件。
下面几行代码显示如何"实时"创建临时文件:
cd$HOME/fvt
echo"Creatingfilesofttar.c"
echo"S