UI自动化进销存系统框架整合(三)

框架目录:

        common:存放编公共方法类,获取CSV文件、获取配置文件数据、获取日志文件对象、读取数据工具

        config:存放一些配置文件、比如日志配置文件、数据文件存放路径

        data:存放测试数据

        log:存放系统运行日志

        pages:存放基于页面操作的基类base_page.py和对页面属性和操作的类如login_page.py

        report:存放测试报告

        screenshots:存放测试截图

        test_case:存放测试脚本

        test_run:自动化执行测试脚本,生成测试报告

   前面介绍了UI自动化进销存系统之用户登录(一)UI自动化进销存系统之会员管理(二)

怎么对页面通用元素封装,封装了base_page.py,还有对页面登录login_page.py

和会员管理的添加操作member_manage_page.py。写了测试脚本验证用户登录和添加会员的操作,接下来按照测试框架介绍对于日志的封装,测试数据读取,运行测试脚本生成测试截图和测试报告

        我的理解测试框架是为了更好方便管理维护自动化测试的方式,以进销存系统的web自动化为例,首先我们可以先从page目录写起,写一个basePage类,封装一个通用的页面操作,比如通用的元素定位方法,下拉框的定位方法等。然后再page目录下,针对业务操作,一个页面对应一个Page类,比如登录LoginPage,需要继承basePage。登录的LoginPage就是存放页面操作的类。

        然后我们可以定义一个util目录,存放一些测试工具,定义一个myunit类,定义页面打开,初始化driver和浏览器关闭的方法。在testcases目录下定义一个测试脚本,比如测试登录,的login_test.py,继承myunit,在把LoginPage导入,在里面输入测试数据开始测试。

        开始测试肯定会遇到问题,所以我们集成了logging,在每步操作有一个操作日志,方便我们定位问题。

        在做测试时,我们想测试多组测试数据,如果每组测试数据写一个方法,重复代码冗余且不方便数据管理,所以我们需要在data目录下存放测试数据,以便来做数据驱动,在测试验证时,我们也会需要一些测试截图。

        读logging配置文件,读测试数据,读取截图文件、读取脚本存放目录等我们都需要涉及到路径,如果我们在每次使用的时候都直接写路径,这些路径就很分散不方便管理,所以我们可以使用一个config.yaml存放测试需要的路径、测试url,测试数据库信息等

        所有的准备都做完了,我们就把所有的测试脚本给组织起来,在test_run目录下,创建一个run类,做自动化测试,并把生成的测试报告存放在report目录下  

1、python中读取yaml文件内容

        为了方便一些配置文件、项目url还有数据驱动文件的变动对项目造成影响,在配置文件中写入存放地址,然后再定义一个工具类获取配置文件内容,通过关键字来读取对应的值或者路径

        config/conf.yaml

loggerConfigPath: ../config/logger.conf  #日志配置文件路径
screenshotpath: ../screenshots/          #截图存放路径
login_url: http://192.168.47.15:8080/woniusales/  #项目url
login_data: ../data/login.csv                     #登录数据csv文件
login_json: ../data/logindata.json                #登录数据json文件路径
case_dir: ../test_cases                           #测试脚本存放路径
report_dir: ../report                             #测试报告存放路径

        在Util类中定义了一个类方法读取配置文件内容,使用时导入Util类,直接调用Util.get_jsondata(Util.get_conf()["关键字"]),获取对应的值

common/util.py

import yaml

class Util:

    # 以字典格式返回配置文件的内容
    @classmethod
    def get_conf(cls):
        with open("../config/conf.yaml",'r',encoding='UTF7') as f:
            data = yaml.load(f,Loader=yaml.FullLoader)
            return data
if __name__ == "__main__":
    data = Util.get_jsondata(Util.get_conf()["login_json"])  #获取yaml文件中login_json对应的值
    print(data)

2、python集成logging日志

        项目运行一旦出现问题日志信息就非常重要,日志是定位问题的重要手段,在输出日志内容时,对日志内容进行格式化设置,能方便查看问题位置。另外一个项目中会有很多的日志采集点,而日志的采集点必须结合业务属性来设置。比如在登录代码执行前可以插入“准备登录”日志信息

日志配置文件

        在config目录下新建一个logger.conf,将下面内容复制进去,修改args=('../log/psi.log', 'a')里面日志存放路径为你要保存日志的路径

        config/logger.conf

[loggers]
keys=root,file,fileAndConsole
[handlers]

keys=fileHandler,consoleHandler
[formatters]
keys=simpleFormatter
[logger_root]
level=DEBUG
handlers=consoleHandler
[logger_file]
level=DEBUG
handlers=fileHandler
qualname=file
propagate=1
[logger_fileAndConsole]
level=DEBUG
handlers=fileHandler,consoleHandler
qualname=fileAndConsole
propagate=0
[handler_consoleHandler]
class=StreamHandler
args=(sys.stdout,)
level=DEBUG
formatter=simpleFormatter
[handler_fileHandler]
class=FileHandler
args=('../log/psi.log', 'a')
level=DEBUG
formatter=simpleFormatter
[formatter_simpleFormatter]
format=%(asctime)s %(filename)s[line:%(lineno)d] %(levelname)s %(message)s
datefmt=%Y-%m-%d %H:%M:%S

日志工具类的封装:

        common/util.py

import logging.config

filepath = Util.get_conf()["loggerConfigPath"]  #通过工具类获取logger配置文件路径
logging.config.fileConfig(filepath)
logger = logging.getLogger('fileAndConsole')

日志文件的使用:

        在登录page/login_page.py模块中导入logger,为了让方便问题定位,可以详细的记录每一步的操作,从用户开始登录、到用户输入账号、密码、验证码、点击登录按钮登录

import time

from selenium.common.exceptions import  TimeoutException
from selenium.webdriver.common.by import By
from common.util import logger,Util

from pages.base_page import BasePage

class LoginPage(BasePage): #定义登录页面的属性和方法

    username = (By.ID,"username")
    password = (By.ID,"password")
    verifycode = (By.ID,"verifycode")
    lgoin_button = (By.XPATH,"//button[contains(@onclick,'doLogin')]")
    flag = (By.XPATH,'//a[contains(text(),"admin")]')

    def user_login(self,us,pw,ve):
        logger.info("=================开始登录================")
        logger.info("输入用户名{}".format(us))
        self.baseFindElement(self.username).send_keys(us)
        logger.info("输入密码{}".format(pw))
        self.baseFindElement(self.password).send_keys(pw)
        logger.info("输入验证码{}".format(ve))
        self.baseFindElement(self.verifycode).send_keys(ve)
        logger.info("==============点击登录按钮================")
        self.baseFindElement(self.lgoin_button).click()
        logger.info("================登录成功==================")

3、给项目添加截图

在工具类common/util.py添加一个截图方法。

    #添加截图
    @classmethod
    def get_screenshot(cls,driver,path):
        driver.get_screenshot_as_file(path)

在做页面操作时调用

  Util.get_screenshot(self.driver,Util.get_conf()["screenshotpath"]+now+".png")

4、执行自动化测试用例

       在所有的测试脚本都写完了,当然就需要有个入口,能全部执行这些测试脚本,

        在conf.yaml配置文件中定义测试脚本和测试报告的位置,unittest.TestLoader().discover(文件路径,匹配文件格式)查找测试脚本,运行测试脚本,使用HTMLTestRunner生成测试报告。

            test_run/run.py

import unittest,time
from HTMLTestRunner_cn import HTMLTestRunner
from common.util import Util

test_dir = Util.get_conf()["case_dir"]  #读取测试脚本的目录
report_dir = Util.get_conf()["report_dir"]  #读取测试报告目录
dis = unittest.TestLoader().discover(test_dir,"*_test.py")  #查找测试脚本下以_test结尾python文件
now = time.strftime("%Y-%m-%d %H %M %S")
report_name = report_dir + '/'+now+'test_report.html'
runner = HTMLTestRunner(
    title="进销存系统的自动化测试报告",
    description="v1.0测试结果",
    stream=open(report_name,'wb'),
    verbosity=2
)
runner.run(dis)

5、使用csv文件存放测试数据

data/login.csv

admin,admin123,0000
admin,,0000
admin,admin123,

Util工具类中读取login.CSV文件
    #读取数据
    @classmethod
    def get_testdata_by_row(cls,csv_file,line): #csv_file文件名称 line行数
        logger.info("开始读取数据")
        with open(csv_file,'r',encoding="utf-8") as f:
            reader = csv.reader(f)
            for index,row in enumerate(reader,1):
                if index == line:
                    return row #返回该行数据

在测试脚本中使用读取的测试数据,test_cases/login_test.py

    def test_login_succcess(self):
        lp = LoginPage(self.driver)
        data = Util.get_testdata_by_row(Util.get_conf()["login_data"],1)
        lp.user_login(data[0],data[1],data[2])
        self.assertTrue(lp.check_login())


    def test_login_failed_without_username(self):
        lp = LoginPage(self.driver)
        data = Util.get_testdata_by_row(Util.get_conf()["login_data"], 2)
        lp.user_login(data[0],data[1],data[2])
        self.assertFalse(lp.check_login())

6、数据驱动

        这一节主要介绍使用parameterized做数据驱动,以登录页面为例,在data目录下创建一个logindata.json文件,存放四组数据,用户名、密码、验证码、是否登录成功。

data/logindata.json

[
  {
    "username": "admin",
    "password": "admin123",
    "verify": "0000",
    "flag": true
  },
    {
    "username": "",
    "password": "admin123",
    "verify": "0000",
    "flag": false
  },
    {
    "username": "admin",
    "password": "",
    "verify": "0000",
    "flag": false
  },
  {
    "username": "admin123",
    "password": "admin123",
    "verify": "0000",
    "flag": false
  }
]

在Util工具类中读取JSON文件,因为@parameterized.expand(data)中存放的数据是[(),(),()]列表嵌套元组,所以这里在把值取出来之后,以元组的形式存在列表list_data中

    @classmethod
    def get_jsondata(cls,jsonname):
        with open(jsonname,"r") as  f:
            datas = json.load(f)
            list_data = []
            for data in datas:
                username = data["username"]
                password = data["password"]
                verify = data["verify"]
                flag = data["flag"]
                list_data.append((username,password,verify,flag))
            return list_data

在test_cases/login_test.py

        这里就是在要做数据驱动的方法前面加上@parameterized.expand(data),该方法上面的参数和data里面每次读取的值一一对应,当flag为True时,说明这组测试数据是正向的测试数据,就断言返回的lp.check_login()返回值是否为True,否则就断言返回的值lp.check_login()是否为False

from common.util import Util
from pages.login_page import LoginPage
from common.myunit import MyUnit
from parameterized import parameterized
import unittest

class LoginTest(MyUnit):

    data = Util.get_jsondata(Util.get_conf()["login_json"])
    @parameterized.expand(data)
    def test_login_param(self,un,pw,ver,flag):
        lp = LoginPage(self.driver)
        lp.user_login(un,pw, ver)
        if flag:
            self.assertTrue(lp.check_login())
        else:
            self.assertFalse(lp.check_login())

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值