基于Selenium的测试程序优化

简介: 顾翔老师开发的bugreport2script开源了,希望大家多提建议。文件在https://github.com/xianggu625/bug2testscript,主文件是:zentao.py 。bugreport是禅道,script是python3+selenium 3,按照规则在禅道上书写的bugreport可由zentao.py程序生成py测试脚本。

Selenium代码的优化


1.异常优化

考虑以下情形。


def testLogin(){
  #从Excel文件中读入测试数据,比如:Jerry/123456
  #继续后续测试
}
def teardown(){
  #从数据库表中删除的读入的数据,比如:Jerry/123456
  ...
}


比如测试程序在继续后续测试的时候出现了一个异常,比如元素没有找到,系统会自动退出,而不去执行teardown方法,也就是说数据库中的数据没有得到清除,这样如果下一次测试同样的case,采用同样的测试数据就会使测试程序发生脏数据异常,为了解决这个问题我们通过使用Python的try-catch来捕获异常,并且将所有的方法封装在一个类中。我们在util.py中封装一个class类。


(1)封装定位API

代码1:封装定位API。


def find_element_by_id(self,driver,mystr):
    try:
      return driver.find_element_by_id(mystr)
    except NoSuchElementException:
      print("find_element_by_id 没有发现元素"+mystr)


这样如果系统通过by_id方式找不到某个元素,测试程序会抛出“find_element_by_id 没有发现元素"+mystr(mystr即定位的id号)”信息,然后继续下面的程序。调用的时候采用下面的方法。


def setUp(self):
     d = drivers()
     self.driver=d.driver
     self.fd=findby()
     self.fd.implicitly_wait(self.driver,5)
def test_XXX():
self.fd.find_element_by_id(self.driver,"kw").clear()


当然其他的定位方式也同样适用。


(2)封装操作API

代码2:封装操作API。


def send_keys(self,elenment,send_string):
        try:
             elenment.send_keys(send_string)
        except:
              print("send_keys操作失败")


当执行send_keys发生异常,系统抛出“send_keys操作失败”信息,然后继续下面的程序。调用的时候采用下面的方法。


self.fd.send_keys(self.fd.find_element_by_id(self.driver,"kw"),inputstring)


2.Retry优化

UI自动化测试程序的最大问题之一在于由于网络不稳定,从而造成页面元素不是不存在,而是还没有被调出来(虽然Selenium提供了现式等待和隐式等待,实际工程中会发现这两个方法是有缺陷的,并且好些浏览器根本就不支持)。在这里进行如下的优化。


代码3:Retry优化。


def find_element_by_id(self,driver,mystr):
                try:
                        return driver.find_element_by_id(mystr)
                except NoSuchElementException:
                        for i in range(2):
                                try:
                                        time.sleep(2000)
                                        return driver.find_element_by_id(mystr)
                                except NoSuchElementException:
                                        print("尝试第"+str(i+1)+"次失败")
                        print("尝试第3次失败")
                        print("find_element_by_id 没有发现元素"+mystr)


当程序找不到元素的时候,等待2秒钟,继续获取,如果还是没有取到继续等待,在这里设置了两次的等待机会,如果没有报异常信息。


3.对页面的封装

def test_Add_Addess(self):
username='cindy'
password='123456'
#登录
self.clear(self.find_element_by_id(driver,"id_username"))
self.send_keys(self.find_element_by_id(driver,"id_username"),username)
self.clear(self.find_element_by_id(driver,"id_password"))
self.send_keys(self.find_element_by_id(driver,"id_password"),password)
self.submit(self.find_element_by_class_name(driver,"form-signin"))
#在登录首页找到用户名
self.fd.click(self.fd.find_element_by_link_text(self.driver, username))
#进入用户信息列表
self.fd.click(self.fd.find_element_by_id(self.driver,"add_address"))
#进入添加送货地址信息页面,添加收货信息
self.fd.clear(self.fd.find_element_by_name(self.driver,"address"))
self.fd.send_keys(self.fd.find_element_by_name(self.driver,"address"),"北京清华")
self.fd.clear(self.fd.find_element_by_name(self.driver,"phone"))
self.fd.send_keys(self.fd.find_element_by_name(self.driver,"phone"),"13699876655")
self.fd.click(self.fd.find_element_by_xpath(self.driver,"/html/body/div/form/button"))
#验证加入的信息
self.assertIsNotNone(self.fd.find_element_by_link_text(self.driver,"删除"))
#测试完毕,清场操作
self.fd.click(self.fd.find_element_by_link_text(self.driver,"删除"))


被测对象是一个电子商务网站,要测试在用户界面添加一条收货信息。所以必须先登录,登录完毕后点击当前用户名的超链,然后进入用户信息界面,接下来点击新建用户收货地址按钮,进入新建页面,建立完毕进行断言,最后为了以后仍旧可以进行这个测试用例,进行清除操作。由此可见,如果一个测试业务比较长,按照这样的写法可读性是比较差的,并不便于维护,因此采用目前比较流行的基于页面的封装方法。


先对登录页面进行封装,代码如下。


代码4:测试添加用户购物配送地址功能。


#通用信息
class Util:
    def __init__(self,driver):
        self.driver = driver
    def logout(self):
        findby.click(self.driver,findby.find_element_by_link_text(self,self.driver,"退出"))
        findby.quit(self,self.driver)
#登录页面
class LoginPage:
    def __init__(self,driver):
        self.driver = driver
#登录操作
    def login(self,username,password):
        findby.clear(self.driver,findby.find_element_by_id(self,self.driver,"id_username"))#清空用户输入框
        findby.send_keys(self.driver,findby.find_element_by_id(self,self.driver,"id_username"),username)#输入用户名
        findby.clear(self.driver,findby.find_element_by_id(self,self.driver,"id_password")) #清空密码输入框
        findby.send_keys(self.driver,findby.find_element_by_id(self,self.driver,"id_password"),password)#输入密码
        findby.submit(self.driver,findby.find_element_by_class_name(self,self.driver,"form-signin"))#提交表单


产品页面封装如下。


#产品页面
class ProductPage:
    def __init__(self,driver):
        self.driver = driver
    #进入用户信息页面
    def click_username(self,username):
        findby.click(self.driver,findby.find_element_by_link_text(self,self.driver,username))#


点击登录用户名链接


登录用户详情页面封装如下。


#登录用户详情页面
class UserPage:
    def __init__(self,driver):
        self.driver = driver
    #添加购物配送地址信息
    def click_add_address_button(self):
        findby.click(self.driver,findby.find_element_by_id(self,self.driver,"add_address"))
    #验证地址信息
    def check_address(self):
        return findby.find_element_by_link_text(self,self.driver,"删除")
    #删除地址信息
    def delete_address(self):
        delete_button = findby.find_element_by_link_text(self,self.driver,"删除")
        findby.click(self.driver,delete_button)


添加地址页面封装如下。


#地址
class AddressPage:
    def __init__(self,driver):
        self.driver = driver
    #添加新地址
    def create_address(self,addess,phone):
        findby.clear(self.driver,findby.find_element_by_name(self,self.driver,"address"))#清空地址栏
        findby.send_keys(self.driver,findby.find_element_by_name(self,self.driver,"address"),addess)#输入地址信息
        findby.clear(self.driver,findby.find_element_by_name(self,self.driver,"phone"))##清空电话栏
        findby.send_keys(self.driver,findby.find_element_by_name(self,self.driver,"phone"),phone)#输入电话信息
        findby.submit(self.driver,findby.find_element_by_xpath(self,self.driver,"/html/body/div/form/button"))#提交表单


这样,验证添加购物地址的测试代码如下。


#coding:utf-8
from selenium import webdriver
from selenium.webdriver.support.ui import WebDriverWait
import unittest,time
from util import drivers,findby
from page import Util,LoginPage,ProductPage,UserPage,AddressPage,CartPage
class CheckEBusiness(unittest.TestCase):
    def setUp(self):
        driver = drivers().driver
        fd = findby()
        self.util = Util(driver)
        self.loginpage = LoginPage(driver)
        self.producepage = ProductPage(driver)
        self.userpage = UserPage(driver)
        self.addresspage = AddressPage(driver)
        self.cartpage = CartPage(driver)
        fd.implicitly_wait(driver,5)
        fd.get(driver,"http://127.0.0.1:8000")
        self.username = "cindy"
        self.password = "123456"
        self.adddress = "首体南路3号"
        self.phone = "13681732596"
    def test_Add_Addess(self):
        self.loginpage.login(self.username,self.password)
        self.producepage.click_username(self.username)
        self.userpage.click_add_address_button()
        self.addresspage.create_address(self.adddress,self.phone)
        self.assertIsNotNone(self,self.userpage.check_address())
        self.userpage.delete_address()
if __name__=="__main__":
        unittest.main()


这样测试程序的代码的可读性与可维护性都得到了很好得加强。现在增加“测试购物车功能”的验证。只需在Product类中建立如下两个方法。


代码5:测试添加商品进购物车功能。


#放入购物车
    def put_into_cart(self):
        findby.click(self.driver,findby.find_element_by_link_text(self,self.driver,"放入"))# 点击“放入”链接
    #查看购物车
    def view_cart(self):
        findby.click(self.driver,findby.find_element_by_partial_link_text(self,self.driver,"查看购物车"))# 点击“查看购物车”链接在加入一个Cart(购物车)类。


然后增加一个购物车的类。


#购物车页面
class CartPage:
    def __init__(self,driver):
        self.driver = driver
    #验证购物车中是否存在商品
    def check_goods(self):
        return findby.find_element_by_xpath(self,self.driver,"//*[@id=\"id_count\"]")
    #删除购物车总中的商品
    def delete_goods(self):
        findby.click(self.driver,findby.find_element_by_link_text(self,self.driver,"移除"))


相应的测试代码为。


def test_Add_Goods_into_Cart(self):
        self.loginpage.login(self.username,self.password)
        self.producepage.put_into_cart()
        self.producepage.view_cart()
        self.assertIsNotNone(self.cartpage.check_goods())
        self.cartpage.delete_goods()


最后再来验证一下对商品查询的功能,在Product类中加入。


代码6:测试商品查询功能。


#商品查询
    def search_goods(self,good_name):
        findby.send_keys(self.driver,findby.find_element_by_name(self,self.driver,"good"),good_name)#输入查询内容
        findby.click(self.driver,findby.find_element_by_xpath(self,self.driver,"//*[@id=\"navbar\"]/form/button"))#输入查询内容
        return findby.find_element_by_link_text(self,self.driver,"放入")


而在测试代码中加入如下两行测试语句就可以了。


def test_Search_Goods(self):
        self.loginpage.login(self.username,self.password)
        self.assertIsNotNone(self.producepage.search_goods("茶"))


星云测试

http://www.teststars.cc

奇林软件

http://www.kylinpet.com

联合通测

http://www.quicktesting.net


顾翔凡言:

    困而学之,学而知之,知而不困,不困则不学,不学则不知,不知则又困也,故学无终止。


目录
相关文章
|
25天前
|
安全 Linux 测试技术
提升龙蜥内核测试能力!探究持续性模糊测试优化实践
清华大学软件学院对Anolis OS使用靶向模糊测试方法将测试工作引向修改的代码,进而提高对业务代码的测试能力。
|
24天前
|
Web App开发 前端开发 Java
《手把手教你》系列技巧篇(九)-java+ selenium自动化测试-元素定位大法之By name(详细教程)
【4月更文挑战第1天】 这篇教程介绍了如何使用Selenium Webdriver通过name属性来定位网页元素,作为系列教程的一部分,之前讲解了id定位,后续还会有其他六种定位方法。文中以百度搜索为例,详细说明了定位搜索框(name="wd")并输入关键词“北京宏哥”的步骤,包括手动操作流程、编写自动化脚本以及代码实现。此外,还提供了查看和理解Selenium源码的方法,强调了`open implementation`选项用于查看方法的具体实现。整个过程旨在帮助读者学习Selenium的元素定位,并实践自动化测试。
42 0
|
19天前
|
前端开发 Java 测试技术
《手把手教你》系列技巧篇(十二)-java+ selenium自动化测试-元素定位大法之By link text(详细教程)
【4月更文挑战第4天】本文介绍了link text在自动化测试中的应用。Link text是指网页中链接的文字描述,点击可跳转至其他页面。文章列举了8种常用的定位方法,其中着重讲解了link text定位,并通过实例展示了如何使用Java代码实现点击百度首页的“奥运奖牌榜 最新排名”链接,进入相应页面。如果link text不准确,则无法定位到元素,这说明linkText是精准匹配,而非模糊匹配。文章还提到了partial link text作为link text的模糊匹配版本,将在后续内容中介绍。
37 4
|
18天前
|
XML 前端开发 Java
《手把手教你》系列技巧篇(十四)-java+ selenium自动化测试-元素定位大法之By xpath上卷(详细教程)
【4月更文挑战第6天】按宏哥计划,本文继续介绍WebDriver关于元素定位大法,这篇介绍定位倒数二个方法:By xpath。xpath 的定位方法, 非常强大。使用这种方法几乎可以定位到页面上的任意元素。xpath 是XML Path的简称, 由于HTML文档本身就是一个标准的XML页面,所以我们可以使用Xpath 的用法来定位页面元素。XPath 是XML 和Path的缩写,主要用于xml文档中选择文档中节点。基于XML树状文档结构,XPath语言可以用在整棵树中寻找指定的节点。
43 0
|
1天前
|
测试技术 API Python
Appium控件交互策略:优化自动化测试效率的关键方法
该文介绍了如何使用Selenium与APP进行交互,包括点击、输入和状态判断等操作。例如,通过element.click()点击控件,element.send_keys()输入文本,以及element.is_displayed()检查元素是否可见。还展示了如何获取元素属性,如resource-id、text和class,并提供了Python代码示例来定位并操作APP元素,如滑动条的显示、可点击性检测及点击滑动条中心位置。在编写测试脚本时,应注意元素定位和状态验证以确保测试稳定性。
7 1
|
1天前
|
数据采集 前端开发 测试技术
《手把手教你》系列技巧篇(三十一)-java+ selenium自动化测试- Actions的相关操作-番外篇(详解教程)
【4月更文挑战第23天】本文介绍了网页中的滑动验证码的实现原理和自动化测试方法。作者首先提到了网站的反爬虫机制,并表示在本地创建一个没有该机制的网页,然后使用谷歌浏览器进行验证。接着,文章详细讲解了如何使用WebElement的click()方法以及Action类提供的API来模拟鼠标的各种操作,如右击、双击、悬停和拖动。
6 2
|
1天前
|
Java 测试技术 持续交付
深入理解与应用Selenium WebDriver进行自动化测试
【4月更文挑战第25天】 在现代软件开发过程中,自动化测试已成为确保产品质量和加速市场发布的关键步骤。Selenium WebDriver作为业界广泛采用的自动化测试工具之一,提供了一种灵活且高效的方式来模拟用户与Web应用程序交互。本文将探讨Selenium WebDriver的核心概念、架构以及实际应用中的技巧和最佳实践。通过深入分析其工作原理及常见问题解决方案,旨在帮助测试工程师提升测试效率,确保测试结果的准确性和可靠性。
|
2天前
|
Web App开发 数据采集 Java
《手把手教你》系列技巧篇(三十)-java+ selenium自动化测试- Actions的相关操作下篇(详解教程)
【4月更文挑战第22天】本文介绍了在测试过程中可能会用到的两个功能:Actions类中的拖拽操作和划取字段操作。拖拽操作包括基本讲解、项目实战、代码设计和参考代码,涉及到鼠标按住元素并将其拖动到另一个元素上或指定位置。划取字段操作则介绍了如何在一段文字中随机选取一部分,包括项目实战、代码设计和参考代码。此外,文章还提到了滑动验证的实现,并提供了相关的代码示例。
29 2
|
4天前
|
前端开发 测试技术 C++
Python自动化测试面试:unittest、pytest与Selenium详解
【4月更文挑战第19天】本文聚焦Python自动化测试面试,重点讨论unittest、pytest和Selenium三大框架。unittest涉及断言、TestSuite和覆盖率报告;易错点包括测试代码冗余和异常处理。pytest涵盖fixtures、参数化测试和插件系统,要注意避免过度依赖unittest特性。Selenium的核心是WebDriver操作、等待策略和测试报告生成,强调智能等待和元素定位策略。掌握这些关键点将有助于提升面试表现。
18 0
|
6天前
|
Web App开发 JavaScript 前端开发
深入理解自动化测试框架Selenium的设计与实现
【4月更文挑战第20天】 在软件测试领域,自动化测试已成为提升测试效率和确保产品质量的关键手段。Selenium作为一款广泛使用的开源自动化测试框架,其设计精巧且功能强大,为Web应用提供了一种灵活、高效的测试解决方案。本文将深入探讨Selenium的核心架构与实现细节,解析其如何通过模拟用户操作来执行测试用例,以及它如何适应不断变化的Web技术标准。通过对Selenium内部机制的剖析,旨在帮助测试工程师更好地掌握该工具,并在测试实践中发挥其最大效能。