自动化回归测试实战

自动化回归测试实战

目前遇到的项目模块自动化已经完成的差不多了,俗话说:"好记性不如烂笔头",所以最近整理了项目自动化中遇到的问题以及解决方法。

先说一下,实际当前项目已经使用RF框架完成了一版自动化,但是实际执行该脚本需花费几天的时间;考虑到时间成本,所以后面想改用其他框架提高执行效率。经过多方对比和项目实际情况,最后确定seldom对当前项目比较实用,所以以下是基于seldom进行的自动化测试。

seldom的优势

  • 提供更加简单API编写自动化测试
  • 提供脚手架,快速生成自动化测试项目
  • 全局启动和关闭浏览器,减少浏览器的启动次数
  • 提供支持多种数据文件参数化
  • 支持用例失败/错误重跑
  • 支持生成HTML/XML测试报告
  • 支持HTTP接口测试 (v 2.0)

其他需要了解此框架的其他操作请前往https://github.com/SeldomQA/seldom/tree/master/docs

项目思路

  1. 自动化中一般是使用url地址来进行基本的操作,这样也便于下次直接切换基础url地址进行项目自动化回归验证,所以这里是把url地址使用conf配置文件单独存放,便于统一管理和维护,比如采购申请和采购申请添加页面存放在beta.conf中,使用时则读取beta.conf配置文件中的信息。这里使用ConfigParse读取配置文件,操作代码如下

    # beta.conf配置文件内容如下

[beta]
# 登录url
beta_url = http://172.17.1.10/test
username = yy
password = 123456
audit_username = yyadmin
aduit_username01 = yyadmin001
aduit_username02 = yyadmin002
aduit_username03 = yyadmin003
aduit_username04 = yyadmin004
aduit_username05 = yyadmin005
aduit_username06 = yyadmin006
audit_username07 = yyadmin095
# 采购品目添加url
Procurement_item_url=/a/purchase/catalog/form
# 采购目录列表
pe_list=/a/purchase/catalog/list

# 读取配置文件操作

    os.chdir("E:\\rcm_seldom\\test_dir")

    # 读取配置文件中的url
    config = ConfigParser()
    # 传入读取文件的地址,encoding文件编码格式,中文必须
    with codecs.open('beta.conf', 'r', encoding='utf-8') as f:
        config.read_file(f)
    # 返回所有信息
    #secs = config.sections()
    #beta = config.items("beta", "beta")
    url = config.get("beta", "beta_url")
    print(url)
    before_temp_url = config.get("beta", "Procurement_item_url")
    # audit_username
    audit_username =config.get("beta", "audit_username")
    password = config.get("beta", "password")
    beta_apply_list_temp = config.get("beta", "pe_list")
    before_url = url + before_temp_url
    beta_apply_list = url + beta_apply_list_temp
    print(before_url)
    print(beta_apply_list)
  1. seldom框架中使用了po模式,将page页面元素定位方法和测试用例隔离,如before_apply_common_page.py,代码如下:

# before_apply_common_page.py

# coding=utf-8
from poium import Page, PageElement

class BeforeApplyCommonPage(Page):
    
    # 选择预算指标按钮
    before_budget_target_button = PageElement(xpath="//input[@id='budgetName']")
    # 选中预算指标
    before_budget_target_selected = PageElement(xpath="//table[@id='dataGrid']//tr[3]//td[2]//input[1]")
    # 确认预算指标
    before_budget_target_confirm = PageElement(xpath="//a[@class='layui-layer-btn0']")
    
    # 是否签订合同-否
    before_budget_sign_no = PageElement(xpath="//input[@id='contractFlag2']")
    # 是否签订合同-是
    before_budget_sign_is = PageElement(xpath="//input[@id='contractFlag1']")

    # 申请理由
    before_budget_remarks = PageElement(xpath="//textarea[@id='applyReason']")
    
    # 申请金额
    before_budget_amount = PageElement(xpath="//input[@id='applyAmount0']")

    # 事前申请附件点击按钮
    before_budget_file_button = PageElement(xpath="//form[@id='inputForm']//li[2]//a[1]")
    # 事前申请附件添加按钮
    before_budget_file_submit = PageElement(xpath="//div[contains(@id,'rt_rt')]")
    # 事前申请上传附件

    
    # 事前申请查询收缩按钮
    before_budget_shrink_button = PageElement(xpath="//i[@id='shrinkIco']")
    # 事前申请提交
    before_budget_submit = PageElement(xpath="//body/form/div/input[2]")

    # 事前申请暂存&确认审核&查询确认按钮
    before_budget_save= PageElement(xpath="//input[@id='btnSubmit']")

    # 附件预览
    before_budget_preview = PageElement(xpath="//a[contains(@id,'view')]")

    # 事前申请删除按钮
    # before_budget_modify_button = PageElement(link_text="修改")
    before_budget_modify_button = PageElement(xpath="//table[@id='dataGrid_rightfrozen']//tbody[1]//tr[2]//td[1]//a[1]")
    # 事前申请删除按钮
    # before_budget_del_button = PageElement(link_text="删除")
    before_budget_del_button = PageElement(xpath="///table[@id='dataGrid_rightfrozen']//tbody[1]//tr[2]//td[1]//a[2]")

    # 事前申请确认删除&确认审核
    before_budget_del_confirm = PageElement(xpath="//a[@class='layui-layer-btn0']")

    # 事前申请查询申请事由
    before_budget_apply_reason = PageElement(xpath="//input[@id='applyReason']")

    # 事前申请审核按钮
    # before_budget_audit_button = PageElement(link_text="审批")
   
    before_budget_audit_button = PageElement(xpath="//table[@id='dataGrid_rightfrozen']//tbody[1]//tr[2]//td[1]//a[1]")



    # ----------------------------136服务器页面信息-------------------
    before_is_audit_button = PageElement(xpath="//div[@id='s2id_IS_A']//span[@class='select2-chosen']")
    before_is_audit = PageElement(xpath="//div[@id='select2-drop']//li[2]//div[1]")
    before_is_info_button = PageElement(xpath="//div[@id='s2id_IS_B']//span[@class='select2-chosen']")
    before_is_class_button = PageElement(xpath="//div[@id='s2id_IS_C']//span[@class='select2-chosen']")

而具体的测试用例则在test_before_apply_common.py文件中,此文件直写了具体的测试用例,有保存、提交、修改、删除以及审批常用的方法,这里页面元素信息输入使用了公用方法common_before_contrat,如图

# test_before_apply_common.py

# coding=utf-8
import seldom
import time
import random
import string
import os
from seldom import Seldom
from poium import Page, PageElement, PageSelect
from faker import Faker
from configparser import ConfigParser
import codecs
import sys
from .before_apply_common_page import BeforeApplyCommonPage
# import before_apply_common_page
#存放c.py所在的绝对路径
BASE_DIR = os.path.dirname(os.path.abspath(__file__))
sys.path.append(BASE_DIR)
print(BASE_DIR)
from test_poium_encapsulate import LoginTest

# 跳过测试类
@seldom.skip()
class BeforeApplyCommonTest(seldom.TestCase):

    os.chdir("E:\\rcm_seldom\\test_dir")

    # 读取配置文件中的url
    config = ConfigParser()
    # 传入读取文件的地址,encoding文件编码格式,中文必须
    with codecs.open('beta.conf', 'r', encoding='utf-8') as f:
        config.read_file(f)
    # 返回所有信息
    #secs = config.sections()
    #beta = config.items("beta", "beta")
    url = config.get("beta", "beta_url")
    print(url)
    before_temp_url = config.get("beta", "beforeApplyCommon_add")
    # audit_username
    audit_username =config.get("beta", "audit_username")
    password = config.get("beta", "password")
    beta_apply_list_temp = config.get("beta", "beforeApplyCommon_list")
    before_url = url + before_temp_url
    beta_apply_list = url + beta_apply_list_temp
    print(before_url)
    print(beta_apply_list)


    def start(self):
        #登录
        
        # login =LoginTest().login
        # login()
        cookie_beta = self.get_cookie('yy')
        print(cookie_beta)


    def common_before_contract(self):
        """设置事前申请信息,填写所有提交审核,为合同输入数据"""
        # 事前申请添加输入信息随机参数
        localTime = time.strftime("%Y%m%d%H%M%S", time.localtime())
        salt = ''.join(random.sample(string.ascii_letters + string.digits, 8))
        provider_name = salt + localTime
        # num = ''.join(random.sample(string.digits, 8))
        # reveive_code = num + localTime
        

        fake = Faker(locale='zh_CN')
        # provider_code = fake.random_number(digits=7, fix_len=False)
        apply_amount_temp = fake.pyfloat(left_digits=3, right_digits=2, positive=True)
        apply_amount = str(apply_amount_temp)
        print(apply_amount)
        
        # provider_remarks = fake.sentences()

        # login =LoginTest().login
        # login()
        sign_login = LoginTest()
        sign_login.login()
        # 切换主题
        sign_login.default_change_theme()
        
        page = BeforeApplyCommonPage(Seldom.driver)
        
        # 打开url
        self.get(self.before_url)
        self.sleep(3)
        
        # 点击预算指标信息按钮
        page.before_budget_target_button.click()
        self.sleep(3)
        # 进入收款方frame框架
        self.switch_to_frame(xpath="//iframe[@id='layui-layer-iframe1']")
        # 选中预算指标
        page.before_budget_target_selected.click()
        # 退出frame
        self.switch_to_frame_out()
        self.sleep(1)
        
        page.before_budget_target_confirm.click()
        self.sleep(1)

        # 是否签订合同-是
        page.before_budget_sign_is.click()

        # 申请理由
        page.before_budget_remarks = provider_name
        # 申请金额
        page.before_budget_amount = apply_amount

        # #事前申请附件点击按钮信息
        # page.before_budget_file_button.click()
        # # 事前申请附件添加按钮
        # page.before_budget_file_submit.click()
        # # 事前申请附件上传操作
        # os.system("E:\\rcm_seldom\\test_dir\\upload1.exe")
        # self.sleep(3)

        # # 附件预览
        # page.before_budget_preview.click()

        # # 切换到第一个窗口
        # advance_apply_list = self.window_handles
        # print(advance_apply_list)
        # self.switch_to_window('advance_apply_list[0]')

        # --------------------附件上传第二种方式----------
        # filePath = r'C:\Users\admin\Postman\files\发票模块说明文档.doc'
        # self.type(xpath='', text=filePath)
        # 提交事前申请
        page.before_budget_submit.click()
        self.sleep(5)
        # 事前申请断言
        page.before_budget_shrink_button.click()
        page.before_budget_apply_reason = provider_name
        page.before_budget_save.click()
        self.sleep(8)
        self.assertText(provider_name)

        return provider_name, apply_amount

    # 跳过测试类
    # @seldom.skip()
    def test_common_save(self):

        """设置事前申请信息,填写所有仅保存"""
        # 事前申请添加输入信息随机参数
        localTime = time.strftime("%Y%m%d%H%M%S", time.localtime())
        salt = ''.join(random.sample(string.ascii_letters + string.digits, 8))
        provider_name = salt + localTime
        # num = ''.join(random.sample(string.digits, 8))
        # reveive_code = num + localTime
        

        fake = Faker(locale='zh_CN')
        # provider_code = fake.random_number(digits=7, fix_len=False)
        apply_amount_temp = fake.pyfloat(left_digits=3, right_digits=2, positive=True)
        apply_amount = str(apply_amount_temp)
        print(apply_amount)
        
        # provider_remarks = fake.sentences()

        # login =LoginTest().login
        # login()
        sign_login = LoginTest()
        sign_login.login()
        # 切换主题
        sign_login.default_change_theme()
        
        page = BeforeApplyCommonPage(Seldom.driver)
        
        # 打开url
        self.get(self.before_url)
        self.sleep(3)
        
        # 点击预算指标信息按钮
        page.before_budget_target_button.click()
        self.sleep(1)
        # 进入收款方frame框架
        self.switch_to_frame(xpath="//iframe[@id='layui-layer-iframe1']")
        # 选中预算指标
        page.before_budget_target_selected.click()
        # 退出frame
        self.switch_to_frame_out()
        self.sleep(1)
        page.before_budget_target_confirm.click()
        self.sleep(1)

        # 是否签订合同-否
        page.before_budget_sign_no.click()

        # 申请理由
        page.before_budget_remarks = provider_name
        # 申请金额
        page.before_budget_amount = apply_amount

        # """事前申请附件上传暂时无用,原因未知"""
        # #事前申请附件点击按钮信息
        # page.before_budget_file_button.click()
        # # 事前申请附件添加按钮
        # page.before_budget_file_submit.click()
        # # 事前申请附件上传操作
        # os.system("E:\\rcm_seldom\\test_dir\\upload1.exe")
        # self.sleep(3)

        # 保存事前申请
        page.before_budget_save.click()
        self.sleep(8)
        # 事前申请断言
        page.before_budget_shrink_button.click()
        page.before_budget_apply_reason = provider_name
        page.before_budget_save.click()
        self.sleep(8)
        self.assertText(provider_name)

        # 返回reviev_code 
        return provider_name, apply_amount


    # 跳过测试类
    # @seldom.skip()
    def test_common_submit(self):
        """设置事前申请信息,填写所有提交审核"""
        # 事前申请添加输入信息随机参数
        localTime = time.strftime("%Y%m%d%H%M%S", time.localtime())
        salt = ''.join(random.sample(string.ascii_letters + string.digits, 8))
        provider_name = salt + localTime
        # num = ''.join(random.sample(string.digits, 8))
        # reveive_code = num + localTime
        

        fake = Faker(locale='zh_CN')
        # provider_code = fake.random_number(digits=7, fix_len=False)
        apply_amount_temp = fake.pyfloat(left_digits=3, right_digits=2, positive=True)
        apply_amount = str(apply_amount_temp)
        print(apply_amount)
        
        # provider_remarks = fake.sentences()

        login =LoginTest().login
        login()
        
        page = BeforeApplyCommonPage(Seldom.driver)
        
        # 打开url
        self.get(self.before_url)
        self.sleep(3)
        
        # 点击预算指标信息按钮
        page.before_budget_target_button.click()
        self.sleep(1)
        # 进入收款方frame框架
        self.switch_to_frame(xpath="//iframe[@id='layui-layer-iframe1']")
        # 选中预算指标
        page.before_budget_target_selected.click()
        # 退出frame
        self.switch_to_frame_out()
        self.sleep(1)
        page.before_budget_target_confirm.click()
        self.sleep(3)

        # 是否签订合同-否
        page.before_budget_sign_no.click()

        # 申请理由
        page.before_budget_remarks = provider_name
        # 申请金额
        page.before_budget_amount = apply_amount

        # #事前申请附件点击按钮信息
        # page.before_budget_file_button.click()
        # # 事前申请附件添加按钮
        # page.before_budget_file_submit.click()
        # # 事前申请附件上传操作
        # os.system("E:\\rcm_seldom\\test_dir\\upload1.exe")
        # self.sleep(3)

        # # 附件预览
        # page.before_budget_preview.click()

        # # 切换到第一个窗口
        # advance_apply_list = self.window_handles
        # print(advance_apply_list)
        # self.switch_to_window('advance_apply_list[0]')
        # 提交事前申请
        page.before_budget_submit.click()
        self.sleep(8)
        # 事前申请断言
        page.before_budget_shrink_button.click()
        page.before_budget_apply_reason = provider_name
        page.before_budget_save.click()
        self.sleep(8)
        self.assertText(provider_name)

        return provider_name, apply_amount

    # 跳过测试类
    # @seldom.skip()
    def test_common_modify(self):

        """修改事前申请信息"""

        # 事前申请添加输入信息随机参数
        localTime = time.strftime("%Y%m%d%H%M%S", time.localtime())
        salt = ''.join(random.sample(string.ascii_letters + string.digits, 8))
        provider_name = salt + localTime
        # num = ''.join(random.sample(string.digits, 8))
        # reveive_code = num + localTime
        

        fake = Faker(locale='zh_CN')
        # provider_code = fake.random_number(digits=7, fix_len=False)
        apply_amount_temp = fake.pyfloat(left_digits=3, right_digits=2, positive=True)
        apply_amount = str(apply_amount_temp)
        print(apply_amount)

        """"添加事前申请信息"""
        self.test_common_save()
        self.sleep(3)
        page = BeforeApplyCommonPage(Seldom.driver)

        
        """修改事前申请"""
        page.before_budget_modify_button.click()
        # 修改事前申请
        page.before_budget_remarks.clear()
        page.before_budget_remarks = provider_name
        # 申请金额
        
        # page.before_budget_amount.clear()
        self.clear(xpath="//input[@id='applyAmount0']")
        
        
        page.before_budget_amount = apply_amount

        # 保存事前申请
        page.before_budget_save.click()
        self.sleep(10)
        # 事前申请断言
        page.before_budget_shrink_button.click()
        page.before_budget_apply_reason = provider_name
        page.before_budget_save.click()
        self.sleep(9)
        self.assertText(provider_name)


    # 跳过测试类
    # @seldom.skip()
    def test_common_del(self):
        """删除事前申请操作"""

        # 添加事前申请信息
        apply_reason, apply_amount = self.test_common_save()
        print("apply_reason是:"+ apply_reason)
        print("apply_amount是:"+ apply_amount)
        page = BeforeApplyCommonPage(Seldom.driver)

        # 删除事前申请
        # page.before_budget_shrink_button.click()
        # page.before_budget_apply_reason = apply_reason
        # page.before_budget_save.click()
        self.sleep(8)
        page.before_budget_del_button.click()
        page.before_budget_del_confirm.click()
        self.sleep(8)
        self.assertText(apply_reason)

    # 跳过测试类
    # @seldom.skip()    
    def test_common_audit(self):

        """事前申请审核操作"""

        # 添加事前申请
        apply_reason, apply_amount = self.test_common_submit()
        print(type(apply_reason))
        print("apply_reason是:"+ apply_reason)
        print(apply_amount)
        page = BeforeApplyCommonPage(Seldom.driver)

        # 退出当前账号登录
        logout = LoginTest().logout
        logout()

        # 审核账号登录
        login =LoginTest()
        login.account_login(self.audit_username, self.password)
        # login()
        # LoginTest().account_login(self.audit_username, self.password)
        
        # 打开url
        self.get(self.beta_apply_list)
        self.sleep(5)

        #审核操作,查询该申请单
        page.before_budget_shrink_button.click()
        page.before_budget_apply_reason = apply_reason
        page.before_budget_save.click()
        self.sleep(5)
        # 点击审核按钮
        page.before_budget_audit_button.click()
        self.sleep(6)
        page.before_budget_save.click()
        self.sleep(6)
        page.before_budget_del_confirm.click()
        self.sleep(6)
        page.before_budget_shrink_button.click()
        page.before_budget_apply_reason = apply_reason
        page.before_budget_save.click()
        self.sleep(6)
        self.assertText(apply_reason)
        
        return apply_reason, apply_amount


    # 跳过测试类
    # @seldom.skip()
    def test_common_contract_audit(self):
        """事前申请审核操作-签订合同"""

        # 添加事前申请
        apply_reason, apply_amount = self.common_before_contract()
        print(type(apply_reason))
        print("apply_reason是:"+ apply_reason)
        print(apply_amount)
        page = BeforeApplyCommonPage(Seldom.driver)

        # 退出当前账号登录
        logout = LoginTest().logout
        logout()

        # 审核账号登录
        login =LoginTest()
        login.account_login(self.audit_username, self.password)
        # login()
        # LoginTest().account_login(self.audit_username, self.password)
        
        # 打开url
        self.get(self.beta_apply_list)
        self.sleep(5)

        #审核操作,查询该申请单
        page.before_budget_shrink_button.click()
        page.before_budget_apply_reason = apply_reason
        page.before_budget_save.click()
        self.sleep(6)
        # 点击审核按钮
        page.before_budget_audit_button.click()
        page.before_budget_save.click()
        self.sleep(6)
        page.before_budget_del_confirm.click()
        self.sleep(6)
        page.before_budget_shrink_button.click()
        page.before_budget_apply_reason = apply_reason
        page.before_budget_save.click()
        self.sleep(6)
        self.assertText(apply_reason)
        
        return apply_reason, apply_amount

    def end(self):
        #退出
        logout = LoginTest().logout
        logout()


if __name__ == '__main__':
    # seldom.main("test_before_apply_common.py", rerun=0)
    seldom.main()


  1. 其他通常代码完成后可能需要调试,seldom也支持单独运行某个测试用例进行代码调试,整体测试通过后seldom还可以生成一份HTML的测试报告,我们可以在代码中将报告及时发送给需要实时追踪的项目干系人,以便及时掌握项目的最新进展。

这里可以看一下最终生成的报告展示:

image-20210908144359133

  1. 如果项目足够庞大,还是建议做好文件夹分模块,这样便于后期维护。

总体下来,目前已使用seldom完成项目常用模块的自动化回归操作,项目常用代码已全部上传gitee上。以上就是该项目所有自动化的实战。整体下来,最初难以抉择的还是自动化工具的选型,一旦自动化工具确定后,余下的就是为了实现此目标。

关于自动化工具的选择

这里稍微提下关于自动化工具的选型:

我们进行自动化操作最主要的一点是当前项目是否适用自动化,项目需求以及页面是否经常变动,这是考虑自动化成本的一个非常重要的一点,不过对于一些固化不变的模块,我们也可以适当考虑部分自动化,毕竟能减少我们的工作量,降低线上问题概率就解决了实际问题img

另外还有两点是需要考虑的

  1. 自动化框架的使用广度,出现问题是否可以快速定位并解决
  2. 团队整体的实用性,不管使用任何工具包括RobotFrameWork、python+selenium等的都需要调研当前团队的接受以及学习成本。
posted @ 2021-09-08 14:50  janehost  阅读(749)  评论(0编辑  收藏  举报