(六⼗⼆)⾃动化测试项⽬实战(最终篇)
随笔记录⽅便⾃⼰和同路⼈查阅。
#------------------------------------------------我是可耻的分割线-------------------------------------------
⾃动化测试⽤例设计
对于测试⼈员来说,不管是进⾏功能测试、⾃动化测试还是性能测试都需要编写测试⽤例,测试⽤例的好坏往往能准确地体现测试⼈员的经验、能⼒以及对项⽬需求的理解深度。所以,在正式开展⾃动化测试⼯作之前,我们有必要聊聊⾃动化测试⽤例的⼀些特点,以及如何编写⾃动化测试⽤例。
⼿动测试⽤例与⾃动化测试⽤例
⼿⼯测试⽤例针对功能测试⼈员的,⽽⾃动化测试⽤例则是针对⾃动化测试框架或⼯具的;前者是功能测试⽤例⼈员通过⼿⼯⽅式进⾏⽤例解析,后者是应⽤脚本技术进⾏⽤例解析。两者各⾃最⼤的特点在于,前者具有较好的异常处理能⼒,能够基于测试⽤例,制造各种不同的逻辑判断,⽽且⼈⼯测试步步跟踪,能够细致地定位问题;⽽后者是完全按照测试⽤例的步骤进⾏测试,只能在已知的步骤与场景中发现问题,⽽且往往因为⽹络问题或功能的微⼩变化导致⽤例执⾏异常,⾃动化的执⾏也很难发现新的bug。
⼿⼯测试⽤例与⾃动化测试⽤例对⽐如下。
1. ⼿⼯测试⽤例特点:
* 较好的异常处理能⼒,能通过⼈为的逻辑判断校验当前步骤的功能是否正确实现。
* ⼈⼯执⾏⽤例具有⼀定的步骤跳跃性。
* ⼈⼯测试步步跟踪,能够细致地定位问题。
* 主要⽤来发现功能缺陷。
1. ⾃动糊测试⽤例特点
* 执⾏对象是脚本,任何⼀个判断都需要编码定义。
* ⽤例步骤之间关联性强。
* 主要⽤来保证产品主体功能正确和完整,让测试⼈员从繁琐重复的⼯作中解脱出来。
* ⽬前⾃动化测试阶段定位在冒烟测试和回归测试。
通过对⽐我们可以看到,⼿⼯测试⽤例与⾃动化测试⽤例之间存在较⼤的差异,所以,不能直接把⼿⼯测试⽤例“翻译”成⾃动化测试脚本。
通过它们之间的特点对⽐也可清晰地认识到,⾃动化测试不能完全地代替⼿⼯测试,⾃动化测试的⽬的仅仅在于让测试⼈员从繁琐重复的测试过程中解脱出来,把更多的时间和精⼒放到更有价值的测试中,例如探索性测试。⽽⾃动化测试更多的是⽤来进⾏冒烟测试和回归测试。
1. ⾃动化测试⽤例选型注意事项:
1)不是所有的⼿⼯⽤例都要转为⾃动化测试⽤例。
2)考虑到脚本开发的成本,不要选择流程太复杂的⽤例。如果有必要,可以考虑把流程拆分成多个⽤例来实现脚本。
3)选择的⽤例最好可以构建成场景。例如,⼀个功能模块,分多个⽤例,多个⽤例使⽤同⼀个场景。这样的好处在于⽅便构建关键字测试模型。
4)选择的⽤例可以带有⽬的性。例如,这部分⽤例作为冒烟测试,那部分⽤例作为回归测试等,当然,会存在重叠的关系。如果当前⽤例不能满⾜需求,那么唯有修改⽤例来适应脚本和需求。
5)选取的⽤例可以是你认为是重复执⾏,很繁琐的部分。例如,字段验证、提⽰信息验证这类,这部分适⽤于回归测试。
6)选取的⽤例可以是主体流程,这部分适⽤于冒烟测试。
7)⾃动化测试也可以⽤来做配置检查、数据库检查。这些可能超越了⼿⼯⽤例,但也算⽤例扩展的⼀部分,项⽬负责⼈也可以有选择地增加。
8)平时在⼿⼯测试时,如果需要构建⼀些复杂的数据或重复⼀些简单的机械式动作,则告诉⾃动化脚本,让它来帮你,或许你的效率会因此⽽得到提⾼。
测试类型
1. 测试静态内容
静态内容测试是最简单的测试,⽤于验证静态的、不变化的UI元素的存在性。例如:
* 每个页⾯都有其预期的页⾯标题吗?这可以⽤来验证链接指向⼀个预期的页⾯。
* 应⽤程序的主页包含⼀个应该在页⾯顶部的图⾯吗?
* ⽹站的每⼀个页⾯是否都包含⼀个页脚区域来显⽰公司的联系⽅式、隐私政策以及商标信息?
* 每⼀页的标题⽂本都使⽤的<h1>标签吗?每个页⾯都有正确的头部⽂本吗?
你可能需要(也可能不需要)对页⾯内容进⾏⾃动化测试。如果你的页⾯内容是不易受到影响,则⼿⼯
对内容进⾏测试就⾜够了。假设你的应⽤⽂件的位置被移动了,则内容测试就⾮常有价值。
1. 测试连接
Web站点的⼀个常见错误为失效的链接或链接指向⽆效页。链接测试涉及各个链接和验证预期的页⾯是否存在。如果静态链接不经常更改,则⼿动测试就⾜够了。但是,如果你的⽹页设计师经常改链接,或者⽂件不时被重定向,则链接测试应该事先⾃动化。
1. 功能测试
在你的应⽤程序中,需要测试应⽤的特点功能,需要⼀些类型的⽤户输⼊,并返回某种种类型的结果。通常⼀个功能测试将涉及多个页⾯,⼀个基于表单的输⼊页⾯,其中包含若⼲输⼊字段提交和取消操作,以及⼀个或多个响应页⾯。⽤户输⼊可以通过⽂本输⼊域、复选框、下拉列表,或任何其他浏览器所⽀持的输⼊。
功能测试通常是需要⾃动化测试的最复杂的测试类型,但通常也是最最重要的。典型的测试是登录、注册⽹站账户、⽤户账户操作、账户设置变化、复杂的数据检索操作,等等。功能测试通常对应着你的应⽤程序的描述应⽤特性或设计的使⽤场景。
1. 测试动态元素
通常⼀个⽹页元素都有⼀个唯⼀的标识符,⽤于唯⼀地定位该⽹页中的元素。通常情况下,唯⼀标识符⽤HTML标记的“id”属性或“name”属性来实现。
这些标识符可以是⼀个静态的(既不变得)字符串常量,也可以是动态⽣成值,在每个页⾯实例上都是变化的。例如,有些Web服务器可能在⼀个页⾯实例上命名所显⽰的⽂件为doc3861,⽽在其他页⾯实例上显⽰为doc6148,这个取决于⽤户在检索的“⽂档”。验证⽂件是否存在的测试脚本可能⽆法到不变的识别码来定位该⽂件。通常情况下,具有变化的标识符的动态元素存在于基于⽤户操作的结果页⾯上,然⽽,显然这取决于Web应⽤程序。
1. Ajax的测试
Ajax是⼀种⽀持以动态改变⽤户界⾯元素的技术。页⾯元素可以动态更改,单不需要浏览器重新载⼊页⾯,如动画、RSS源、其他实时数据更新等。Ajax有⽆数更新⽹页上元素的⽅法。最简单的⽅法是在Ajax驱动的应⽤程序中,数据可以从应⽤服务器检索,然后显⽰在页⾯上,⽽不需要重新加载整个页⾯,只有⼀下部分的页⾯,或者只有元素本⾝被重新加载。
⾃动化测试⽤例编写原则
在编写⾃动化测试⽤例过程中应该遵循以下原则:
1)⼀个⽤例为⼀个完整的场景,从⽤户登录系统到最终退出并关闭浏览器。
2)⼀个⽤例只验证⼀个功能点,不要试图在⽤户登录系统后把所有的功能都验证⼀遍。
3)尽可能少的编写逆向逻辑⽤例。⼀⽅⾯因为逆向逻辑的⽤例很多(例如,⼿机号输错有⼏⼗种情况);另⼀⽅⾯⾃动化脚本本⾝⽐较脆弱,复杂的逆向逻辑⽤例实现起来较为⿇烦且容易出错。
4)⽤例与⽤例之间尽量避免产⽣依赖。
5)⼀条⽤例完成测试之后需要对测试场景进⾏还远,以免影响其他⽤例的执⾏。
BBS社区项⽬实战
本篇以⼀个BBS社区项⽬为例,BBS社区属于互联⽹⽐较典型的应⽤,主要有登录、个⼈中⼼、发帖、查看帖⼦、搜索、签到等功能。
准备⼯作
1. 项⽬开发是个循序渐进的过程
需要向读者说明的是,我接下来要介绍的这个⾃动化测试项⽬,并⾮项⽬的最初的形态,其间经历了多
次代码迭代与结构的重构,并且仅仅只符合当前的项⽬需求。为什么要强调这些呢?
相信我们都知道⼀个只有⼏条测试⽤例的项⽬和有⼀个⼏百条测试⽤例的项⽬结构肯定不⼀样的。对于只有⼏条测试⽤例的项⽬,我不需要考虑太多结构⽅⾯的问题,甚⾄只⽤线性模型来编写⽤例,其维护成本也不会太⾼;但是,当⽤例达到⼏百条时就不得不考虑各种问题,例
如,如何降低测试代码的冗余、对代码进⾏抽象与分层、采⽤哪种设计模式,等等。
⾃动化测试的开发,是个不断调整代码与结构的过程,也许第⼀天你编写了⼆⼗条⽤例,到第⼆天的时候,你需要花三分之⼀的时间对昨天的部分代码进⾏调整或忠狗。只有三分之⼆的时间⽤于编写新的⽤例。类、⽅法和函数的命名也是需要考究的⽅⾯,既要尽量保持简洁,⼜要见名知意,代码的编写更是如此,如何写出简洁优雅的代码是对我们变成功底的考验。遗憾的是⽆法带着读者去复盘这样⼀个过程。其实,这个过程也必须由读者⾃⼰在不断实践中积累和总结。
1. 选择合适的IDE
⼯欲善其事,必先利其器,再开始开发⾃动化项⽬之前,我们有必要先来聊⼀聊Python有哪些IDE。当然关于IDE的讨论⼀直属于热门话题,这个不是要分辨个孰优孰劣,这⾥只是想告诉读者不同的编程阶段应选择适合⾃⼰的IDE。
Python IDLE:如果读者初学Python,并且不精通其他变成语⾔及IDE,则建议从这个IED⼊⼿,它⾃带的Shell模式可以帮助我们快速连
写Python语法,笔者初学Python时⽤了半年。
UliPad:轻量级的Python IDE,有国内⽤户基于wsPython开发,代码着⾊及⾃动补全功能很不错,配置也相对⽐较简单。
Sublime:通⽤型轻量级IED,⽀持多种变成语⾔。有许多功能强⼤的快捷键(Ctrl+d),如果平时需要在多种编程语⾔间切换,name这将是不错的选择。这也是笔者最常⽤的IDE之⼀。
PyCharm:Python 重量级IDE,功能强⼤,⾃动检测语法,可以帮助我们写出更规范的Python代码。对于处⼥座的开发者来说是个不错的选择。
ajax实例 文件浏览Eclipse + pydev:Eclipse也属于重量级IDE。相信学习Java语⾔的同学⼀般都会选择此IDE,配置pydev插件后同样可以⽤来编写Python程序,对于熟悉Eclipse的同学是个不错的选择。
Vim与Emacs:⼀直是程序员⼤神⼝中的神器,学习成本很⾼。
通过简单介绍,相信读者已经到了适合⾃⼰的IED,下⾯就跟着笔者⼀起动⼿开发⾃动化项⽬吧。
项⽬结构介绍
⾃动化测试项⽬结构如下图:
下⾯逐级介绍此⽬录与⽂件的作⽤:
  1.mztestpro测试项⽬
BBS:⽤于存放BBS项⽬的测试⽤例、测试报告和测试数据等。
driver:⽤于存放浏览器驱动。如selenium-server-standalone-2.47.0.jar、、等。在执⾏测试前根据执⾏场景将浏览器驱动复制到系统环境变量path⽬录下。
package:⽤于存放⾃动化所⽤到的扩展包。例如,HTMLTestRunner.py属于⼀个单独模块,并且对其做了修改,所以,在执⾏测试前需要将它复制到Python的Lib⽬录下。
run_bbs_test.py:项⽬主程序。⽤来运⾏社区(BBS)⾃动化⽤例。
start.bat:⽤于启动Selenium Server,默认启动driver⽬录下的selenium-server-standalone-2.47.0.jar。
⾃动化测试项⽬说明⽂档.docx:介绍当前项⽬的架构、配置和使⽤说明。
  2.bbs⽬录
data:该⽬录⽤来存放测试相关的数据。
report:⽤于存放HTML测试报告。其下⾯创建了image⽬录⽤于存放测试过程中的截图。
test_case:测试⽤例⽬录,⽤于存放测试⽤例及相关模块。
  3.test_case⽬录
models:该⽬录下存放了⼀些公共的配置函数及公共类。
page_obj:该⽬录⽤于存放测试⽤例的页⾯对象(Page Object)。根据⾃定义规则,以“*Page.py”命名的⽂件为封装的页⾯对象⽂件。“*_sta.py”:测试⽤例⽂件。根据测试⽂件匹配规则,以“*_sta.py”命名的⽂件将被当做⾃动化测试⽤例执⾏。
编写公共模块
⾸先定义驱动⽂件
..\mztestpro\BBS\test_case\models\driver.py
# !/usr/bin/env python
# -*- coding: UTF-8 –*-
__author__ = 'Mr.Li'
from selenium.webdriver import Remote
from selenium import webdriver
#启动浏览器驱动
def browser():
#driver = webdriver.Chrome()
host = '127.0.0.1:44444'#运⾏主机:端⼝号(本机默认:127.0.0.1:44444)
dc = {'browserName':'chrome'}#指定浏览器('chrome','firefox')
driver = Remote(command_executor='' + host + '/wd/hub',
desired_capabilities=dc)
return driver
if__name__ == '__main__':
dr = browser()
<('www.baidu')
dr.quit()
定义浏览器驱动函数browser(),该函数可以进⾏设置,根据我们的需求,配置测试⽤例在不同的主机及浏览器下运⾏。如果不知道如何配置,可以看前⾯关于Selenium Grid2的⽂章。
⾃定义测试框架:
..\mztestpro\BBS\test_case\models\myunit.py
# !/usr/bin/env python
# -*- coding: UTF-8 –*-
__author__ = 'Mr.Li'
from .driver import browser
import unittest
class MyTest(unittest.TestCase):
def setUp(self):
self.driver = browser()
self.driver.implicitly_wait(10)
self.driver.maximize_window()
def tearDown(self):
self.driver.quit()
定义MyTest()类⽤于继承unittest.TestCase类,因为笔者创建的所有测试类中setUp()与tearDown()⽅法所做的事情相同,所以,将他们抽象为MyTest()类,好处就是在编写测试⽤例时不再考虑这两个⽅法的实现。
定义截图函数:
..\mztestpro\BBS\test_case\models\function.py
# !/usr/bin/env python
# -*- coding: UTF-8 –*-
__author__ = 'Mr.Li'
from selenium import webdriver
import os
#截图函数
def insert_img(driver,file_name):
base_dir = os.path.dirname(os.path.dirname(os.path.dirname(__file__)))
file_path = base_dir + "/report/image/" + file_name
<_screenshot_as_file(file_path)
print('in the insert_img')
if__name__ == '__main__':
driver = webdriver.Chrome()
<('www.baidu')
insert_img(driver,'baidu.png')
driver.quit()
创建截图函数insert_img(),为了保持⾃动化项⽬的移植性,采⽤相对路径的⽅式将测试截图保存到.\report\image\⽬录中。
编写Page Object
关于Page Object设计模式,在前⾯⽂章关于“⾃动化测试⾼级应⽤”篇中有过介绍,这⾥我们将使⽤该设计模式来编写测试⽤例。
⾸先创建基础Page基础类:
..\mztestpro\BBS\test_case\page_obj\base.py
# !/usr/bin/env python
# -*- coding: UTF-8 –*-
__author__ = 'Mr.Li'
class Page(object):
'''
页⾯基础类,⽤于所有页⾯的继承

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。