pytest自动化之脚本实现和优化

【记录自己的实现过程,和结果无关】

初始实现:

# coding:utf-8
"""
author:@zhouxuan
file:conftest.py
"""
from selenium import webdriver
import pytest
from selenium.webdriver.support.wait import WebDriverWait
import time
from selenium.webdriver.remote.webdriver import By
@pytest.fixture(scope='function')
def login_baidu(request):
    dr = webdriver.Chrome()
    dr.get('http://www.baidu.com')
    dr.maximize_window()
    time.sleep(4)
    WebDriverWait(dr, 2).until(lambda x: x.find_element_by_xpath('//*[@id="u1"]/a[7]').is_displayed())
    dr.find_element(By.XPATH,'//*[@id="u1"]/a[7]').click()
    "判断默认展示的是扫码登录还是用户名登录"
    try:
        WebDriverWait(dr, 2).until(lambda x: x.find_element_by_xpath('//p[@title="用户名登录"][not(@style)]').is_displayed())
        b=1
    except:
        b=2  #默认登录方式未扫码
    if b==1:
        dr.find_element("xpath",'//p[@title="用户名登录"]').click()
    dr.find_element(By.NAME,"userName").send_keys('******')
    dr.find_element(By.NAME,"password").send_keys('*****')
    dr.find_element(By.ID,"TANGRAM__PSP_10__submit").click()
    time.sleep(20)   #手工识别
    print('one')
    yield dr
    dr.quit()
    # def quit():
    #     print ('run')
    #     dr.quit()
    # request.addfinalizer(quit)

用例脚本test_baidu.py

# coding:utf-8
"""
author:@
"""
import pytest
from selenium.webdriver.remote.webdriver import By
from selenium.webdriver.common.keys import Keys
from test_finance import pri_packaging
import time

class Test_baidu():
    def test_search(self,login_baidu):
        """
        :param login_baidu: 搜索
        :return:
        """
        dr=login_baidu
        dr.find_element(By.ID,"kw").send_keys('aaa',Keys.ENTER)
    def test_setting(self,login_baidu):
        """
        :param login_baidu: 搜索设置
        :return:
        """
        dr=login_baidu
        dr.find_element(By.XPATH,'//*[@id="s_usersetting_top"]/span').click() #点击设置
        dr.find_element(By.XPATH,'//*[@id="wrapper"]/div[5]/a[1]').click()   #搜索设置
        pri_packaging.wait_element_appear(dr,value='//*[@id="s1_2"]')
        dr.find_element(By.XPATH,'//*[@id="s1_2"]').click()   #搜索框提示不显示
        time.sleep(5)

if __name__ == '__main__':
    pytest.main(['-s','test_baidu.py'])

可以看出新增了py文件pri_packaging,我是用来封装一些常用的方法,这样写起来更加简单

# coding:utf-8
"""
author:zhouxuan
2019/12/30 10:57
PyCharm 封装常用的方法
"""
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.remote.webdriver import By


def wait_element_appear(driver,timeout=10,by=By.XPATH,value=None):
    WebDriverWait(driver, timeout, 1,).until(lambda x: x.find_element(by,value).is_displayed())

执行完毕

============================= test session starts =============================
platform win32 -- Python 3.6.8, pytest-5.0.0, py-1.5.4, pluggy-0.13.1
rootdir: D:\django_project\p3_tongtool, inifile: pytest.ini
plugins: allure-pytest-2.8.6, html-2.0.1, metadata-1.8.0, rerunfailures-8.0
collected 2 items

test_baidu.py one
.one
.

========================== 2 passed in 73.88 seconds ==========================

可以看出,用例脚本的可读性还是偏差,接下来我们就准备把用例脚本写成类似伪代码,增加可读性

优化思路:

1、增加脚本可读性(为公司维护脚本人员和新手考虑)

2、脚本相关数据和业务分离

3、常用的方法抽离出来,做成公共函数,方便重复调用。

开始重构上面的用例。在顶级目录下面创建文件夹conf  config.ini用于存储数据   config.py 系统变量

conf
--config.ini
--config.py

 

config.ini

​
[test_baidu]
${var1}=//*[@id="s1_2"]
搜索关键字=aaa
设置=//*[@id="s_usersetting_top"]/span
搜索设置=//*[@id="wrapper"]/div[5]/a[1]
加载搜索框tab=${var1}
搜索框提示设置不显示=${var1}

​

config.py

import  os

ROOT_DIR=os.path.dirname(os.path.dirname(__file__))
# ui对象库config.ini文件所在目录
CONF_PATH = os.path.join(ROOT_DIR, 'conf', 'config.ini')

接下来要解析config.ini,我这里存储的时候,主要是用按键的名称=识别路径来存储的。 结合脚本中的格式是

find_element(By.XPATH,“//*[@id="s_usersetting_top"]/span”).click(),这样,前面的中文就可以是我们的伪代码了,显示在用例中,方便阅读。最后的替换为 click_obj(driver,baidu_config.split_content('设置')) 。具体的转换过程是

1、先封装find_element_by_xpath(“//*[@id="s_usersetting_top"]/span”).click(),

def click_obj(driver,k_list):
    by,value=k_list
    paraser_by(by)
    driver.find_element(eval(by),value).click()



def paraser_by(by):
    if by == 'By.XPATH':
        by = By.XPATH
    elif by == 'By.ID':
        by = By.ID
    elif by == 'By.NAME':
        by = By.NAME
    return by

从上面来看,我们就只需要给出一个list 里面包含[By.XPATH,//*[@id="s_usersetting_top"]/span].参考个人的风格,我喜欢用xpath来定位元素,所以默认就直接用了xpath,如果是其他的,就在ini文件中搜索设置=By.ID>>//*[@id="wrapper"]/div[5]/a[1]这样写,通过解析,来识别出来。具体对应的脚本

from configobj import ConfigObj
from conf.config import CONF_PATH
class parseConfig():
    def __init__(self,section):
        self.file=CONF_PATH
        self.section= section
        self.configfile=ConfigObj(self.file,encoding='utf-8')
    def get_all_sections(self):
        #获取所有的section
        return self.configfile.sections
    def get_all_options(self):
        #获取指定的section内容
        return self.configfile[self.section]
    def split_content(self,option):
        #拆解对应的数据
        section = self.section
        try:
            xpath_result = self.configfile[section][option] 
            if '$' in xpath_result:
                xpath_result=self.configfile[section][xpath_result] #对变量${name}解析,替换成真正的值
            if '>>' in xpath_result:
                return xpath_result.split('>>')
            else:
                return ['By.XPATH',xpath_result]  #默认xpath格式
        except Exception as  e:
            print ('error',e)

其中的split_content就是用来实现上述功能的。这样返回的就是我们需要的XPATH,以及对象元素的xpath了。

最后脚本就变成了

    def test_setting(self,login_baidu):
        """
        :param login_baidu: 搜索设置
        :return:

        """
        baidu_config=parseConfig('test_baidu')  #实例化解析类
        driver=login_baidu
        click_obj(driver,baidu_config.split_content('设置'))
        click_obj(driver,baidu_config.split_content('搜索设置'))
        waiting_obj(driver,baidu_config.split_content('加载搜索框tab'))
        click_obj(driver, baidu_config.split_content('搜索框提示设置不显示'))

这样,我们从每个名称就知道具体的操作步骤了,点击设置-点击搜索设置-等待加载tab-设置搜索框不显示。

最后就说道维护。只要业务流程没有变,测试脚本就不需要来修改了,就只需要维护测试的相关数据就可以了。这里就是只需要维护ini文件即可。后续,我们将讲述到一个脚本,对应多组测试数据时候,如果来做参数化和维护的

最后的脚本其实还可以做下优化,把解析ini的放到公共函数(click_obj,write_obj)中去,这样可读性会更加好。下一偏将给出实际案例。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值