Use Bash shell scripts for function testing

Functional testing is a critical part of software development - that have been loaded into the Linux Bash can help you easily complete functional test. In this article, Angel Rivera explains how to use the Bash shell script to perform functional testing Linux applications through the command line. Because this script depends on the return code of the command line, so you can not apply this method GUI applications

Functional testing is a stage in the development cycle, at this stage will test your software application to ensure that the software functions as expected, and error code correctly handles. This work is usually at the end of a single module unit test, to test the entire system before the product load / stress conditions performed.

There are many testing tools on the market that help provide functional testing capabilities. However, we must first get them, and then install, configure, which will take up your valuable time and energy. Bash can help you to remove these tedious things which can speed up the testing process.

The advantage of using Bash shell scripts for function testing are:

  • Bash shell script has been installed and configured on a Linux system. You do not have to spend time preparing it.
  • You can use a text editor such as vi provided by Linux to create and modify Bash shell scripts. You do not need to create a test program to obtain specialized tools.
  • If you already know how to develop Bourne or Korn shell script, how to use it for the Bash shell script is enough. For you, the learning curve no longer exists.
  • Bash shell provides a number of programming constructs to develop scripts from the very simple to moderately complex.

Suggestions for the script transplanted from Korn to Bash

If there is an existing Korn shell scripts, and want to transplant them to Bash, we need to consider the following:

  • Korn's "print" command can not be used in Bash; and instead use the "echo" command.
  • You need to be the first line of the script:
    #!/usr/bin/ksh
    modified to:
    #!/bin/bash




Back to top


Creating Bash shell scripts for function testing

These basic steps and recommendations apply to many running on a Linux client / server applications.

  1. A prerequisite for running scripts and record the main steps
  2. The operation is divided into logical groups
  3. Developing implementation steps are based on the general scheme
  4. Provide comments and instructions in each shell script
  5. Make an initial backup to create a baseline
  6. Check the input parameters and environment variables
  7. Attempts to provide "usuage" Feedback
  8. Try to provide a "quiet" mode of operation
  9. When an error occurs, the function terminates a script
  10. If possible, provide the function can perform a single task
  11. When the display output being generated, capture the output of each script
  12. Within each script, capture the return code of each line command
  13. Calculate the number of failed transactions
  14. In the output file, an error message is highlighted for easy identification
  15. If possible, "real time" Makefile
  16. Provide feedback during the execution of the script
  17. It provides a summary of the script's execution
  18. It provides an easy explanation of the output file
  19. If possible, provide cleanup script and return to the baseline method

The following describes in detail every piece of advice as well as scripts for description of the problem. To download this script, see later in this article reference section.

1. Record a prerequisite for running scripts and the main steps of
recording, in particular, there is the title of a single file readme main idea (eg "README-testing.txt") recording function testing is very important to include, as a prerequisite, server and client settings, the entire (or detailed) script steps to follow, how to check the script of success / failure, how to perform cleanup and restart the test.

2. The operation is divided into logical groups
if only a very small number of performed operations, they can all be placed in a simple shell scripts.

However, if the need to do a lot of some quantity, it is preferable to set them into logical, for example, some of the operations in a file server and client in operation on another file. By this method, an appropriate division of the particles to perform testing and maintenance tests.

3. Develop step based on a general scheme
once the decision to drop groups, steps need to be considered according to the general operation scheme. This idea is to simulate real-life case of the end-user. As a general principle, just focus on testing the use of 80% to 20% of the most common function call.

For example, suppose an application requires three test groups arranged in a particular order. Each test set can be placed with a self-describing file name (if possible) file, and use the sequence number to identify each help file, for example:

1.  fvt-setup-1:    To perform initial setup.
2.  fvt-server-2:   To perform server commands.
3.  fvt-client-3:   To perform client commands.
4.  fvt-cleanup:    To cleanup the temporary files, 
                        in order to prepare for the repetition
                        of the above test cases.

4. Provide comments and instructions in each shell script
to provide relevant comments and descriptions is a good coding habits in the header file for each shell script. In this case, when another tester run the script, testers will be able to clearly understand the scope of each test script, all the prerequisites and warnings.

The following is a sample script "test-bucket-1" in the Bash.

#!/bin/bash
#
# Name: test-bucket-1
#
# Purpose:
#    Performs the test-bucket number 1 for Product X.
#    (Actually, this is a sample shell script, 
#     which invokes some system commands 
#     to illustrate how to construct a Bash script) 
#
# Notes:
# 1) The environment variable TEST_VAR must be set 
#    (as an example).
# 2) To invoke this shell script and redirect standard 
#    output and standard error to a file (such as 
#    test-bucket-1.out) do the following (the -s flag 
#    is "silent mode" to avoid prompts to the user):
#
#    ./test-bucket-1  -s  2>&1  | tee test-bucket-1.out
#
# Return codes:
#  0 = All commands were successful
#  1 = At least one command failed, see the output file 
#      and search for the keyword "ERROR".
#
########################################################

5. do an initial backup to create a baseline
, you may need to perform a functional test several times. The first time you run it, may find the script or process some errors. Thus, in order to avoid re-created from scratch server environment and waste a lot of time - especially if it comes to the database - you might want to make a backup before testing.

After running functional tests, you can restore the server from backup, but also ready for the next round of testing.

6. Check the input parameters and environment variables
best check what input parameters and check the environment variables are set correctly. If you have questions, display cause of the problem and fix, and then terminate the script.

When the tests are prepared to run the script, but this time without the proper environment variable settings script calls, but the discovery in a timely manner, to terminate the script, and that testers will be very grateful. No one likes to wait for the script to perform for a long time only to find that the variable is not set correctly.

# --------------------------------------------
# Main routine for performing the test bucket
# --------------------------------------------
CALLER=`basename $0`         # The Caller name
SILENT="no"                  # User wants prompts
let "errorCounter = 0"
# ----------------------------------
# Handle keyword parameters (flags).
# ----------------------------------
# For more sophisticated usage of getopt in Linux, 
# see the samples file: /usr/lib/getopt/parse.bash
TEMP=`getopt hs $*`
if [ $? != 0 ]
then
 echo "$CALLER: Unknown flag(s)"
  usage
fi 
# Note quotes around `$TEMP': they are essential! 
eval set -- "$TEMP"
while true                   
 do
  case "$1" in
   -h) usage "HELP";    shift;; # Help requested
   -s) SILENT="yes";    shift;; # Prompt not needed
   --) shift ; break ;; 
   *) echo "Internal error!" ; exit 1 ;;
  esac
 done
# ------------------------------------------------
# The following environment variables must be set
# ------------------------------------------------
if [ -z "$TEST_VAR" ]
then
  echo "Environment variable TEST_VAR is not set."
  usage
fi 

Description of this script is as follows:

  • Use statements CALLER=`basename $0`can get the name of the script is running. In this case, no hard-coded script name in the script. So when copying the script, new script derived reduce the workload.
  • When you call the script, the statement TEMP=`getopt hs $*`used to obtain the input variables (such as -h representative to help, -s behalf quiet mode).
  • 语句 [ -z "$X" ]echo "The environment variable X is not set." 以及 usage 都是用于检测字符串是否为空 (-z),如果为空,随后就执行 echo 语句以显示未设置字符串并调用下面要讨论的 "usage" 函数。
  • 若脚本未使用标志,可以使用变量 "$#",它可以返回正在传递到脚本的变量数量。

7. 尝试提供“usage”反馈
脚本中使用 "usage" 语句是个好主意,它用来说明如何使用脚本。

# ----------------------------
# Subroutine to echo the usage
# ----------------------------
usage()
{
 echo "USAGE: $CALLER [-h] [-s]"
 echo "WHERE: -h = help       "
 echo "       -s = silent (no prompts)"
 echo "PREREQUISITES:"
 echo "* The environment variable TEST_VAR must be set,"
 echo "* such as: "
 echo "   export TEST_VAR=1"
 echo "$CALLER: exiting now with rc=1."
  exit 1
}

调用脚本时,使用“-h”标志可以调用 "usage" 语句,如下所示:
./test-bucket-1 -h

8. 尝试使用“安静”的运行模式
您或许想让脚本有两种运行模式:

  • 在 "verbose" 模式(您也许想将此作为缺省值)中提示用户输入值,或者只需按下 Enter 继续运行。
  • 在 "silent" 模式中将不提示用户输入数据。

下列摘录说明了在安静模式下运用所调用标志 "-s" 来运行脚本:

# -------------------------------------------------
# Everything seems OK, prompt for confirmation
# -------------------------------------------------
if [ "$SILENT" = "yes" ]
then
 RESPONSE="y"
else
 echo "The $CALLER will be performed."
 echo "Do you wish to proceed [y or n]? "
 read RESPONSE                  # Wait for response
 [ -z "$RESPONSE" ] && RESPONSE="n"
fi 
case "$RESPONSE" in
 [yY]|[yY][eE]|[yY][eE][sS])
 ;;
 *)
  echo "$CALLER terminated with rc=1."
  exit 1
 ;;
esac

9. 当出现错误时,提供一个函数终止脚本
遇到严重错误时,提供一个中心函数以终止运行的脚本不失为一个好主意。此函数还可提供附加的说明,用于指导在此情况下应做些什么:

# ----------------------------------
# Subroutine to terminate abnormally
# ----------------------------------
terminate()
{
 echo "The execution of $CALLER was not successful."
 echo "$CALLER terminated, exiting now with rc=1."
 dateTest=`date`
 echo "End of testing at: $dateTest"
 echo ""
  exit 1
}

10. 如有可能,提供可以执行简单任务的函数
例如,不使用许多很长的行命令,如:

# --------------------------------------------------
echo ""
echo "Creating Access lists..."
# --------------------------------------------------
 Access -create -component Development -login ted -authority plead -verbose
  if [ $? -ne 0 ] 
  then 
  echo "ERROR found in Access -create -component Development -login ted 
    -authority plead"
     let "errorCounter = errorCounter + 1" 
 fi
 Access -create -component Development -login pat -authority general -verbose
  if [ $? -ne 0 ] 
  then 
  echo "ERROR found in Access -create -component Development -login pat 
    -authority general"
     let "errorCounter = errorCounter + 1" 
 fi
 Access -create -component Development -login jim -authority general -verbose
  if [ $? -ne 0 ] 
  then 
  echo "ERROR found in Access -create -component Development -login jim 
    -authority general"
     let "errorCounter = errorCounter + 1" 
 fi

……而是创建一个如下所示的函数,此函数也可以处理返回码,如果有必要,还可以增加错误计数器:

CreateAccess()
{
 Access -create -component $1 -login $2 -authority $3 -verbose
  if [ $? -ne 0 ] 
  then 
  echo "ERROR found in Access -create -component $1 -login $2 -authority $3"
     let "errorCounter = errorCounter + 1" 
 fi
}

……然后,以易读和易扩展的方式调用此函数:

# ------------------------------------------- 
echo ""
echo "Creating Access lists..."
# ------------------------------------------- 
CreateAccess Development ted    projectlead
CreateAccess Development pat    general
CreateAccess Development jim    general

11. 当显示正在生成的输出时,捕获每个脚本的输出
如果脚本不能自动地将输出发送到文件的话,可以利用 Bash shell 的一些函数来捕获所执行脚本的输出,如:

./test-bucket-1  -s  2>&1  | tee test-bucket-1.out

让我们来分析上面的命令:

  • "2>&1" 命令:

    使用 "2>&1" 将标准错误重定向到标准输出。字符串 "2>&1" 表明任何错误都应送到标准输出,即 UNIX/Linux 下 2 的文件标识代表标准错误,而 1 的文件标识代表标准输出。如果不用此字符串,那么所捕捉到的仅仅是正确的信息,错误信息会被忽略。

  • 管道 "|" 和 "tee" 命令:

    UNIX/Linux 进程和简单的管道概念很相似。既然这样,可以做一个管道将期望脚本的输出作为管道的输入。下一个要决定的是如何处理管道所输出的内容。在这种情况下,我们会将它捕获到输出文件中,在此示例中将之称为 "test-bucket-1.out"。

    但是,除了要捕获到输出结果外,我们还想监视脚本运行时产生的输出。为达到此目的,我们连接允许两件事同时进行的 "tee" (T- 形管道):将输出结果放在文件中同时将输出结果显示在屏幕上。其管道类似于:

    process --> T ---> output file
                 |
                 V
               screen
    

    如果 想捕获输出结果而不想在屏幕上看到输出结果,那可以忽略多余的管道: ./test-bucket-1 -s 2>&1 > test-bucket-1.out

    假若这样,相类似的管道如下:

    process --> output file

12. 在每个脚本内,捕获每个行命令所返回码
决定功能测试成功还是失败的一种方法是计算已失败行命令的数量,即返回码不是 0。变量 "$?" 提供最近所调用命令的返回码;在下面的示例中,它提供了执行 "ls" 命令的返回码。

# -------------------------------------------
# The commands are called in a subroutine 
# so that return code can be
# checked for possible errors.
# -------------------------------------------
ListFile()
{ 
 echo "ls -al $1"
 ls -al $1
  if [ $? -ne 0 ] 
  then 
  echo "ERROR found in: ls -al $1"
     let "errorCounter = errorCounter + 1" 
fi 
} 

13. 记录失败事务的次数
在功能测试中决定其成功或失败的一个方法是计算返回值不是 0 的行命令数量。但是,从我个人的经验而言,我习惯于在我的 Bash shell 脚本中仅使用字符串而不是整数。在我所参考的手册中没有清楚地说明如何使用整数,这就是我为什么想在此就关于如何使用整数和计算错误(行命令失败)数量的方面多展开讲的原因:

首先,需要按如下方式对计数器变量进行初始化:

let "errorCounter = 0"

然后,发出行命令并使用 $? 变量捕获返回码。如果返回码不是 0,那么计数器增加 1(见蓝色粗体语句):

ListFile()
{
 echo "ls -al $1"
 ls -al $1
  if [ $? -ne 0 ] 
  then 
  
        echo "ERROR found in: ls -al $1"
  let "errorCounter = errorCounter + 1"
 fi
}
      

顺便说一下,与其它变量一样,可以使用 "echo" 显示整数变量。

14. 在输出文件中,为了容易标识,突出显示错误消息
当遇到错误(或失败的事务)时,除了错误计数器的数量会增加外,最好标识出此处有错。较理想的做法是,字符串有一个如 ERROR 或与之相似的子串(见蓝色粗体的语句),这个子串允许测试者很快地在输出文件中查找到错误。此输出文件可能很大,而且它对于迅速找到错误非常重要。

ListFile()
{
 echo "ls -al $1"
 ls -al $1
  if [ $? -ne 0 ] 
  then 
  
        echo "ERROR found in: ls -al $1"
     let "errorCounter = errorCounter + 1" 
 fi
}
      

15. 如有可能,“实时”生成文件
在某些情况下,有必要处理应用程序使用的文件。可以使用现有文件,也可以在脚本中添加语句来创建文件。如果要使用的文件很长,那最好将其作为独立的实体。如果文件很小而且内容简单或不相关(重要的一点是文本文件而不考虑它的内容),那就可以决定“实时”创建这些临时文件。

下面几行代码显示如何“实时”创建临时文件:

cd $HOME/fvt
echo "Creating file softtar.c"
echo "Subject: This is softtar.c" >  softtar.c
echo "This is line 2 of the file" >> softtar.c

第一个 echo 语句使用单个的 > 强行创建新文件。第二个 echo 语句使用两个 >> 将数据附加到现有文件的后面。顺便说一下,如果该文件不存在,那么会创建一个文件。

16. 在执行脚本的过程中提供反馈
最好在脚本中包含 echo 语句以表明它执行的逻辑进展状况。可以添加一些能迅速表明输出目的的语句。

如果脚本要花费一些时间执行,那或许应在执行脚本的开始和结束的地方打印时间。这样可以计算出所花费的时间。

在脚本样本中,一些提供进展说明的 echo 语句如下所示:

# --------------------------------------------
echo "Subject: Product X, FVT testing"
dateTest=`date`
echo "Begin testing at: $dateTest"
echo ""
echo "Testcase: $CALLER"
echo ""
# --------------------------------------------
# --------------------------------------------
echo ""
echo "Listing files..."
# --------------------------------------------
# The following file should be listed:
ListFile   $HOME/.profile
...
# --------------------------------------------
echo ""
echo "Creating file 1"
# --------------------------------------------

17. 提供脚本执行的摘要
如果正在计算错误或失败事务的次数,那最好表明是否有错误。此方法使得测试者在看到输出文件的最后能迅速地辨认出是否存在错误。

在下面的脚本示例中,代码语句提供了上述脚本的执行摘要:

# --------------
# Exit
# --------------
if [ $errorCounter -ne 0 ]
then
 echo ""
 echo "*** $errorCounter ERRORS found during ***"
 echo "*** the execution of this test case.  ***"
 terminate
else
 echo ""
 echo "*** Yeah! No errors were found during ***"
 echo "*** the execution of this test case. Yeah! ***"
fi 
echo ""
echo "$CALLER complete."
echo ""
dateTest=`date`
echo "End of testing at: $dateTest"
echo ""
exit 0
# end of file

18. 提供一个容易解释的输出文件
在脚本生成的实际输出中提供一些关键信息是非常有用的。那样,测试者就可以很容易地确定正在查看的文件是否与自己所做的相关以及它是否是当前产生的。附加的时间戳记对于是否是当前状态是很重要的。摘要报告对于确定是否有错误也是很有帮助的;如果有错误,那么测试者就必须搜索指定的关键字,例如 ERROR,并确认出个别失败的事务。

以下是一段输出文件样本的片段:

Subject: CMVC 2.3.1, FVT testing, Common, Part 1 
Begin testing at: Tue Apr 18 12:50:55 EDT 2000   
                                                 
Database: DB2                                    
Family:   cmpc3db2                               
Testcase: fvt-common-1                           
                                                 
                                                 
Creating Users...                                
User pat was created successfully.               
...
Well done! No errors were found during the 
execution of this test case :)
                                                                           
fvt-common-1 complete.                                                      
                                                                            
End of testing at: Tue Apr 18 12:56:33 EDT 2000

当遇到错误时输出文件最后部分的示例如下所示:

ERROR found in Report -view DefectView
*** 1 ERRORS found during the execution of this test case. ***           
The populate action for the CMVC family was not successful.               
Recreating the family may be necessary before 
running fvt-client-3 again, that is, you must use 'rmdb', 
'rmfamily', 'mkfamily' and 'mkdb -d',       
then issue: fvt-common-1 and optionally, fvt-server-2.                    
fvt-client-3 terminated, exiting now with rc=1.                           
End of testing at: Wed Jan 24 17:06:06 EST 2001

19. 如有可能,提供清除脚本及返回基准线的方法
测试脚本可以生成临时文件;假若这样,最好能让脚本删除所有临时文件。这就会避免由于测试者也许没有删除所有临时文件而引起的错误,更糟糕的是将所需要的文件当作临时文件而删除了。





回页首


运行功能测试的 Bash shell 脚本

本节描述如何运用 Bash shell 脚本进行功能测试。假设您已经执行了在前面部分中所述步骤。

设置必要的环境变量
根据需要在 .profile 中或手工指定下列环境变量。该变量用于说明在脚本中如何处理,所需环境变量的验证必须在脚本执行前定义。

  export TEST_VAR=1

将 Bash shell 脚本复制到正确的目录下
Bash shell 脚本和相关文件需要复制到要进行功能测试的用户标识的目录结构下。

  1. 登录进某个帐户。您应该在主目录下。假设它是 /home/tester。
  2. 为测试案例创建目录: mkdir fvt
  3. 复制 Bash shell 脚本和相关文件。获取压缩文件(请参阅 参考资料 )并将其放在 $HOME 下。然后将其按下列方式解压: unzip trfvtbash.zip
  4. 为了执行这个文件,更改文件的许可权: chmod u+x *
  5. 更改名称以除去文件的后缀: mv test-bucket-1.bash test-bucket-1

运行脚本
执行下列步骤以运行脚本:

  1. 以测试者的用户标识登录
  2. 更改目录至所复制脚本的位置: cd $HOME/fvt
  3. 从 $HOME/fvt 运行脚本: ./test-bucket-1 -s 2>&1 | tee test-bucket-1.out
  4. 看一下输出文件 "test-bucket-1.out" 的尾部并查看摘要报告的结论。


参考资料

  • 您可以参阅本文在 developerWorks 全球站点上的 英文原文.

  • 下载 trfvtbash.zip,它包含本文所引用的样本代码和工具。该工具在以后有可能会更新。

  • 尝试用 Info-ZIP 软件 解开该文件。由于该工具很常用,推荐您最好将解压和压缩工具的目录放至 PATH 中,这样该机器上的所有用户都可以使用这个工具。
    如何解压该文件:
                
    为了查看压缩文件中的内容(实际上并没有解包和解压缩该文件),用:
    unzip -l trfvtbash.zip 命令。
    为了解包和解压缩这个压缩文件,用:
    unzip trfvtbash.zip 命令。


  • 请阅读 Daniel Robbins 发表在 developerWorks 上的有关 bash 编程的系列(包含 3 部分): 第 1 部分第 2 部分第 3 部分

  • 请访问 GNU 的 bash 主页

  • 请查阅 Bash 参考手册


关于作者

Angel Rivera 是一位 VisualAge TeamConnection 技术支持小组的顾问软件工程师,他目前是该小组的负责人。他拥有 Austin 德克萨斯大学电子工程专业的硕士学位和墨西哥 Instituto Tecnologico y de Estudios Superiores de Monterrey 电子系统工程的学士学位。他于 1989 年进入 IBM。可以通过 [email protected] 与他联系。

在写本文的过程中,Angel 感谢 Lee Perlov 在 WebSphere 方面的技术支持。

转载于:https://www.cnblogs.com/licheng/archive/2008/08/05/1261078.html

Guess you like

Origin blog.csdn.net/weixin_34297300/article/details/92631394
Recommended