IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Python知识库 -> UI自动化框架思路整理(Python+selenium+unittest+html) -> 正文阅读

[Python知识库]UI自动化框架思路整理(Python+selenium+unittest+html)

本文主要以PO思想将页面元素和代码分离,以及执行多用例的UI自动化框架。

下图是整个框架图:

image.png

???????在准备测试一个功能时,我们可以通过手工去测,也可以用UI自动化框架去实现多用例的操作。

????????自动化框架思路:在拿到一个被测业务(功能)时,首先想一下,如果用手工的方式如何去测,需要准备哪些东西,需要哪些步骤,而自动化的过程就是代替人工的实现,所以我们往这个思路上去想不难得出,一个测试业务首先需要测试驱动(也就是浏览器),测试驱动上需要测试元素(也就是测哪些东西,再通俗一点就是所对应的界面或者功能),那如何用代码调用驱动进行实现,测试配置就在此起到了决定性的作用,将所有的配置好之后要进行测试,还需要测试数据和用例的准备,最后加入测试报告的配置用执行器执行就能够形成最终的测试报告了。这段文字主要是梳理思路以及解释上图。还有很多细节以及步骤且听我慢慢道来。

建包:

准备以下七个包:

image.png

在每个包内配置文件:

1.browserdriver(浏览器驱动)

在browserdriver中放置浏览器驱动

2.config(测试配置)

(1)创建config.ini文件里面配置要测试的网址和浏览器驱动

(2)创建read_ini.py:读取配置文件

源码如下:

#封装成别人可以使用的代码
import configparser
import os
print(os.path.dirname(os.path.dirname(__file__)))
class joReadIni():
#初始化 路径
    # 参数1 file_name文件名指定文件名
    # 参数2  node 指定所需要节点名
    def __init__(self,file_name=None,node=None):
        self.file_name=file_name
        self.node=node
        if file_name==None:
            #文件名 加r 防止自动转义
            self.file_name=os.path.dirname(os.path.dirname(__file__))+"/config/config.ini"
        if node==None:
            self.node = "jwconfig"
        self.cf=self.load_ini(self.file_name)

#加载配置文件
    def load_ini(self,file_name):
        #获取解析配置对象
        cf=configparser.ConfigParser()
        cf.read(file_name, encoding='utf-8')
        return  cf
#获取配置文件中的内容===>指定key
    def get_value(self,key):
        return  self.cf.get(self.node,key)

#进行单元测试
if __name__=='__main__':
    aa=joReadIni()
    print(aa.get_value("browser"))

(3)创建jo_driver.py:读取浏览器驱动产生测试webdriver驱动对象(调取浏览器)

源码如下:?


import os
from time import sleep

from selenium import webdriver

from config.read_ini import joReadIni

#工程路径
parent_path=os.path.dirname(os.path.dirname(__file__))
#专门读取配置文件对象
jo=joReadIni()
#获取被测试网址
url=jw.get_value("url")
def get_firefox_driver():
    driver_path=parent_path+"/browserdriver/geckodriver"
    driver=webdriver.Firefox(executable_path=driver_path)
    driver.get(url)
    driver.maximize_window()
    driver.implicitly_wait(3)
    sleep(3)
    return  driver
#进行单元测试
if __name__=='__main__':
    get_firefox_driver()

3.business(测试业务)

利用PO的思想将页面元素和代码分离,因此先在business内创建ini元素文件,再到config包内创建一个py文件进行元素的查询,即使之后界面变了,但是元素是可以复用的,因此将其分离开来方便代码的管理。

(1)创建LocalElement.ini 文件:存放需要自动化操作的控件元素和定位方式

源码如下:

[jologin]
user_login=xpath>//*[@id="__layout"]/div/div[1]/div[1]/div[3]/div[3]/button[1]/span
user_name=xpath>//*[@id="__layout"]/div/div[1]/div[2]/div/div/div[3]/div/div/div[1]/div/input
user_password=xpath>//*[@id="__layout"]/div/div[1]/div[2]/div/div/div[3]/div/div/section/div/div/input
login_button=xpath>//*[@id="__layout"]/div/div[1]/div[2]/div/div/div[3]/div/div/div[2]/button
[joxuanke]
touxiang=xpath>//*[@id="__layout"]/div/div[1]/div[1]/div[3]/div[3]/div/img
xuexizhongxin=xpath>//*[@id="__layout"]/div/div[1]/div[1]/div[3]/div[3]/div/div/ul/li[1]/span
xuankezhongxin=link_text>选课中心
jiagepaixu=xpath>//*[@id="__layout"]/div/div[2]/div/div[2]/div[1]/span[2]
#根据页面倒数第三段  div[2]决定了是第几个元素
secondkecheng=xpath>//*[@id="__layout"]/div/div[2]/div/div[2]/div[2]/div[2]/div[3]/button
kaishixuexi=xpath>//*[@id="__layout"]/div/div[2]/div[1]/div/div[3]/div/div[3]/button
# 看是否有评价决定是否成功
yanzheng=link_text>评价

(2) 再到config包内配置查找元素的py包(注意是config包内创建!)

创建jw_findelement.py 文件 (工具类:直接复制,不做修改即可!)封装了各种selenium查找元素的各种方式

源码如下:


import os
from time import sleep

from config.jo_driver import get_firefox_driver
from config.read_ini import joReadIni


class joFindElement():
    def __init__(self,driver):
        self.driver=driver
#获取元素
    def get_element(self,file=None,node=None,key=None):
        if file==None:
            file=os.path.dirname(os.path.dirname(__file__))+"/business/LocalElement.ini"

        if node==None:
            node="jologin"

        read_ini=joReadIni(file,node)
        data=read_ini.get_value(key)
        #得出定位方式 文件中是以  > 方式切割
        by=data.split('>')[0]
        value=data.split('>')[1]
        try:
            if by=='id':
                return self.driver.find_element_by_id(value)
            elif  by=='name':
                return self.driver.find_element_by_name(value)
            elif by=='className':
                return self.driver.find_element_by_class_name(value)
            elif by=='link_text':
                return self.driver.find_element_by_link_text(value)
            elif by=='xpath':
                return self.driver.find_element_by_xpath(value)
        except:
            return None

    def gundongdaodibu(self):
        self.driver.set_window_size(600, 600)
        sleep(2)
        # 通过JS设置浏览器窗口的滚动条位置
        # 横向滚动100
        # 纵向  滚动 450
        js1 = "window.scrollTo(0, 600);"
        self.driver.execute_script(js1)


if __name__=="__main__":
    parent_path = os.path.dirname(os.path.dirname(__file__))
    driver=get_firefox_driver()
    aa=joFindElement(driver)
     #测试是否可以在get_element 找到登录链接
    print(aa.get_element(parent_path+"/business/LocalElement.ini","jologin","user_login"))

?一定要自测一下能不能找到该元素,能找到之后下一步就是测试功能是否能正常操作。(模拟手工测试)

(3)创建xuanke_bus.py:这个文件存放被测试的业务(核心模块)

源码如下:

from time import sleep

from selenium.webdriver import ActionChains

from config.jo_driver import get_firefox_driver
from config.jo_findelement import joFindElement
from config.read_ini import joReadIni

def  jo_xuanke(username,password,kechenghao):
    jo = joReadIni()

    driver = get_firefox_driver()
    # jw2 专门查找元素
    jo2 = joFindElement(driver)

    try:
        # 登录
        jo2.get_element(node="jologin",key="user_login").click()
        jo2.get_element(node="jologin",key="user_name").send_keys(username)
        jo2.get_element(node="jologin",key="user_password").send_keys(password)
        jo2.get_element(node="jologin", key="login_button").click()
        sleep(2)
        #点击选课中心
        jw2.get_element(node="joxuanke", key="xuankezhongxin").click()

        #将浏览器滚动到底部------》然后开始点击排序
        #jw2.gundongdaodibu()

        # 按价格排序(点击两下--确保降序)---确保测试是免费课程
        # //*[@id="__layout"]/div/div[2]/div/div[2]/div[1]/span[2]
        # 点击第一下
        sleep(3)
        jw2.get_element(node="joxuanke", key="jiagepaixu").click()
        sleep(3)
        # 点击第二下
        jw2.get_element(node="joxuanke", key="jiagepaixu").click()
        sleep(3)
        # 这里的封装导致无法改变课程
        #jw2.get_element(node="joxuanke", key="secondkecheng").click()
        kecheng_xpath="//
[@id='__layout']/div/div[2]/div/div[2]/div[2]/div["+str(kechenghao)+"]/div[3]/button"
        #选择的课程xpath
        driver.find_element_by_xpath(kecheng_xpath).click()
        sleep(2)

        #点击开始学习()
        jw2.get_element(node="joxuanke", key="kaishixuexi").click()
        #验证是否有评价信息
        sleep(2)
        result = jw2.get_element(node="joxuanke",key="yanzheng")
        sleep(2)
        print("找回复是否有评价的结果是", result)
        if result == None:
            return False
        else:
            return True
    except Exception as e:
        print("JO",e)
        print("流程异常,都认为选课失败")
        # 发帖子过程出异常
        return False
    finally:
        driver.quit()#没有这个测试过程中会打开三个浏览器

if __name__=="__main__":

    jw_xuanke("19999999999","a123456",3)

接下来就是准备数据和用例开始执行了。

4.test_data(测试数据)

(1)创建xuanke.csv文件:用来存放测试数据

(2) 创建jotestdata.py 文件:读取准备的测试数据 (工具类:直接复制,不做修改即可!)

源码如下:

import csv

# 设计函数专门读取 csv文件
def get_csv_data(csv_file,line):
        jo_csv_file= open(csv_file, 'r', encoding='utf-8-sig')
        reader = csv.reader(jo_csv_file)
        # 参数2 :决定了下标位置的开始计数方式
        for index, row in enumerate(reader, 1):
            if index == line:
                print(row)
                return row

if __name__=="__main__":
    get_csv_data("./xuanke.csv",1)
    get_csv_data("./xuanke.csv", 2)
    get_csv_data("./xuanke.csv", 3)

?5.test_case(测试用例)

创建test_xuanke.py 文件:使用unittest实现测试用例

?源码如下:

import os
import unittest
import warnings
import sys

from business.xuanke_bus import jo_xuanke

sys.path.append('..')

from test_data.jotestdata import get_csv_data

class TestXUANKE(unittest.TestCase):
    csv_file = os.path.abspath(os.path.dirname(os.getcwd())) + "/test_data/xuanke.csv"
    def setUp(self):
        print("开始测试~")
        # 这句话的作用是用来忽略 ResourceWaring 异常警告的
        warnings.simplefilter("ignore", ResourceWarning)


    def tearDown(self):
        print("结束测试~")


    def test_xuanke_111(self):
        print("第一条选课用例测试~")
        print(self.csv_file)
        data = get_csv_data(self.csv_file, 1)#获取csv文件中的第一行数据
        # 预期失败用例(获取第一列和第二列数据)交给 登录
        self.assertTrue(jo_xuanke(data[0], data[1],data[2]))


    def test_xuanke_222(self):#获取csv文件中的第二行数据
        print("第二条选课用例测试~")
        data = get_csv_data(self.csv_file, 2)
        # 预期失败用例
        self.assertTrue(jo_xuanke(data[0], data[1],data[2]))


    def test_xuanke_333(self):
        print("第三条选课用例测试~")#获取csv文件中的第三行数据
        data = get_csv_data(self.csv_file, 3)
        # 预期失败用例
        self.assertFalse(jo_xuanke(data[0], data[1],data[2]))


if __name__ == '__main__':
    unittest.main()

6.test_run(测试执行器)

(1)拖入BSTestRunner.py 开源插件文件到test_run

(2)建立jwrun.py 文件:最终执行

?源码如下:

import sys
#声明包查找的路径
path=r'文件名or绝对路径'
sys.path.append(path)

from test_run.BSTestRunner import BSTestRunner
import unittest
import time
#指定测试用例和测试报告的路径
test_dir = '../test_case'
report_dir = '../joreports'
#匹配测试多条用例
discover = unittest.defaultTestLoader.discover(test_dir, pattern='test_*.py')
#定义报告的文件格式
now = time.strftime("%Y-%m-%d-%H_%M_%S")
report_name = report_dir + '/' + now + 'test_report.html'
#运行用例并生成测试报告
with open(report_name, 'wb') as f:
    runner = BSTestRunner(stream=f, title="我的选课功能测试报告", description="我的选课功能测试报告")
    runner.run(discover)

扩展:UI一键封装步骤(双击执行)

(1)用vi joUI.sh建立脚本

(2)用i修改sh脚本,注意路径,此外jorun.py文件内的路径也相对应地一定要用文件的绝对路径

3.按esc再:wq保存并退出后,修改权限,使用chmod 777 joUI.sh

4.用./jo.sh命令行执行,如果能跑通证明双击sh文件也能跑通,这就是UI一键封装。?

7.joreports(测试报告)

?自动生成在joreports包内了,可以将文件拖入浏览器查看报告。


分割线,终于写完啦!记得在刚听到老师讲的时候,里面有些代码的细节,听得有点蒙,基础还是不够扎实,也缺乏写代码的思想,容易死磕,从中跳出来再去看代码就会更容易了,其实代码和今天学习的框架的思想是差不多的,都是层层封装一步套一步。

之前也学习过appium的自动化,那时候单纯觉得牛逼,没有去细想其中的内涵,直到今天才差不多懂了些皮毛。在听到老师说UI自动化框架就到这里时,我的心还狂跳不止,那种心情是奇妙的,因为前几天一直想着说要学习UI自动化框架,但是真的到这一步时,遇到困难,我暂时地放弃然后又继续学习,学完后感觉这东西太牛了,居然一点一点地慢慢听懂了,这是准备转行以来对这个东西最强烈地一次心动了。心想着说一定要将这个东西操作一遍,再改改,在改的过程中将其思想再记录下来不失为一件特别棒的事情。

耗时差不多两个半小时,这便是心动的代价吧。

?

  Python知识库 最新文章
Python中String模块
【Python】 14-CVS文件操作
python的panda库读写文件
使用Nordic的nrf52840实现蓝牙DFU过程
【Python学习记录】numpy数组用法整理
Python学习笔记
python字符串和列表
python如何从txt文件中解析出有效的数据
Python编程从入门到实践自学/3.1-3.2
python变量
上一篇文章      下一篇文章      查看所有文章
加:2021-11-27 09:51:35  更:2021-11-27 09:53:20 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/16 2:25:21-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码