前言
今天呢笔者想和大家来聊聊selenium自动化+ pytest测试框架,在这篇文章里你需要知道一定的python基础——至少明白类与对象,封装继承;一定的selenium基础。这篇文章不会selenium,不会的可以自己去看selenium中文翻译网哟。
一、测试框架简介
测试框架有什么优点呢:
-
- 代码复用率高,如果不使用框架的话,代码会很冗余
- 可以组装日志、报告、邮件等一些高级功能
- 提高元素等数据的可维护性,元素发生变化时,只需要更新一下配置文件
- 使用更灵活的PageObject设计模式
- 测试框架的整体目录
- 目录/文件说明是否为python包common这个包中存放的是常见的通用的类,如读取配置文件是config配置文件目录是logs日志目录page对selenium的方放进行深度的封装是page_element页面元素存放目录page_object页面对象POM设计模式,TestCase所有的测试用例集是utils工具类是script脚本文件conftest.pypytest胶水文件pytest.inipytest配置文件,这样一个简单的框架结构就清晰了。
知道了以上这些我们就开始吧!
我们在项目中先按照上面的框架指引,建好每一项目录。
注意:python包为是的,都需要添加一个__init__.py文件以标识此目录为一个python包。
二、管理时间
首先呢,因为我们很多的模块会用到时间戳,或者日期等等字符串,所以我们先单独把时间封装成一个模块。
然后让其他模块来调用即可。在utils目录新建times.py模块
#!/usr/bin/env python3
# -*- coding:utf-8 -*-
import time
import datetime
from functools import wrapsdef timestamp():"""时间戳"""return time.time()def dt_strftime(fmt="%Y%m"):"""datetime格式化时间:param fmt "%Y%m%d %H%M%S"""return datetime.datetime.now().strftime(fmt)def sleep(seconds=1.0):"""睡眠时间"""time.sleep(seconds)def running_time(func):"""函数运行时间"""@wraps(func)def wrapper(*args, **kwargs):start = timestamp()res = func(*args, **kwargs)print("校验元素done!用时%.3f秒!" % (timestamp() - start))return resreturn wrapperif __name__ == '__main__':print(dt_strftime("%Y%m%d%H%M%S"))
现在我也找了很多测试的朋友,做了一个分享技术的交流群,共享了很多我们收集的技术文档和视频教程。
如果你不想再体验自学时找不到资源,没人解答问题,坚持几天便放弃的感受
可以加入我们一起交流。而且还有很多在自动化,性能,安全,测试开发等等方面有一定建树的技术大牛
分享他们的经验,还会分享很多直播讲座和技术沙龙
可以免费学习!划重点!开源的!!!
qq群号:691998057【暗号:csdn999】
三、添加配置文件
配置文件是项目中必不可少的部分!
将固定不变的信息集中在固定的文件中
3.1conf.py
项目中都应该有一个文件对整体的目录进行管理,我也在这个python项目中设置了此文件。
在项目config目录创建conf.py文件,所有的目录配置信息写在这个文件里面。
#!/usr/bin/env python3
# -*- coding:utf-8 -*-
import os
from selenium.webdriver.common.by import By
from utils.times import dt_strftimeclass ConfigManager(object):# 项目目录BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))# 页面元素目录ELEMENT_PATH = os.path.join(BASE_DIR, 'page_element')# 报告文件REPORT_FILE = os.path.join(BASE_DIR, 'report.html')# 元素定位的类型LOCATE_MODE = {'css': By.CSS_SELECTOR,'xpath': By.XPATH,'name': By.NAME,'id': By.ID,'class': By.CLASS_NAME}# 邮件信息EMAIL_INFO = {'username': '1234567890@qq.com', # 切换成你自己的地址'password': 'QQ邮箱授权码','smtp_host': 'smtp.qq.com','smtp_port': 123}# 收件人ADDRESSEE = ['1234567890@qq.com',]@propertydef log_file(self):"""日志目录"""log_dir = os.path.join(self.BASE_DIR, 'logs')if not os.path.exists(log_dir):os.makedirs(log_dir)return os.path.join(log_dir, '{}.log'.format(dt_strftime()))@propertydef ini_file(self):"""配置文件"""ini_file = os.path.join(self.BASE_DIR, 'config', 'config.ini')if not os.path.exists(ini_file):raise FileNotFoundError("配置文件%s不存在!" % ini_file)return ini_filecm = ConfigManager()
if __name__ == '__main__':print(cm.BASE_DIR)
注意:QQ邮箱授权码怎么生成自己去百度
这个conf文件我模仿了Django的settings.py文件的设置风格,但是又有些许差异。
在这个文件中我们可以设置自己的各个目录,也可以查看自己当前的目录。
遵循了约定:不变的常量名全部大写,函数名小写。看起来整体美观。
3.2config.ini
在项目config目录新建一个config.ini文件,里面暂时先放入我们的需要测试的URL
[HOST]
HOST = https://www.baidu.com
四、读取配置文件
配置文件创建好了,接下来我们需要读取这个配置文件以及使用里面的信息。
我们在common目录中新建一个readconfig.py文件
#!/usr/bin/env python3
# -*- coding:utf-8 -*-
import configparser
from config.conf import cmHOST = 'HOST'class ReadConfig(object):"""配置文件"""def __init__(self):self.config = configparser.RawConfigParser() # 当有%的符号时请使用Raw读取self.config.read(cm.ini_file, encoding='utf-8')def _get(self, section, option):"""获取"""return self.config.get(section, option)def _set(self, section, option, value):"""更新"""self.config.set(section, option, value)with open(cm.ini_file, 'w') as f:self.config.write(f)@propertydef url(self):return self._get(HOST, HOST)ini = ReadConfig()if __name__ == '__main__':print(ini.url)
可以看到我们用python内置的configparser模块对config.ini文件进行了读取。
对于url值的提取,我使用了高阶语法@property属性值,写法更简单。
五、记录操作日志
日志,大家应该都很熟悉这个名词,就是记录代码中的动作。
在utils目录中新建logger.py文件。
这个文件就是我们用来在自动化测试过程中记录一些操作步骤的。
#!/usr/bin/env python3
# -*- coding:utf-8 -*-
import logging
from config.conf import cmclass Log:def __init__(self):self.logger = logging.getLogger()if not self.logger.handlers:self.logger.setLevel(logging.DEBUG)# 创建一个handle写入文件fh = logging.FileHandler(cm.log_file, encoding='utf-8')fh.setLevel(logging.INFO)# 创建一个handle输出到控制台ch = logging.StreamHandler()ch.setLevel(logging.INFO)# 定义输出的格式formatter = logging.Formatter(self.fmt)fh.setFormatter(formatter)ch.setFormatter(formatter)# 添加到handleself.logger.addHandler(fh)self.logger.addHandler(ch)@propertydef fmt(self):return '%(levelname)s\t%(asctime)s\t[%(filename)s:%(lineno)d]\t%(message)s'log = Log().loggerif __name__ == '__main__':log.info('hello world')
在终端中运行该文件,就看到命令行打印出了:
INFO 2022-06-15 16:00:05,467 [logger.py:38] hello world
然后在项目logs目录下生成了当月的日志文件。
六、简单理解POM模型
由于下面要讲元素相关的,所以首先理解一下POM模型
Page Object模式具有以下几个优点。
该观点来自 《Selenium自动化测试——基于Python语言》
- 抽象出对象可以最大程度地降低开发人员修改页面代码对测试的影响, 所以, 你仅需要对页
面对象进行调整, 而对测试没有影响; - 可以在多个测试用例中复用一部分测试代码;
- 测试代码变得更易读、 灵活、 可维护
Page Object模式图
- basepage ——selenium的基类,对selenium的方法进行封装
- pageelements——页面元素,把页面元素单独提取出来,放入一个文件中
- searchpage ——页面对象类,把selenium方法和页面元素进行整合
- testcase ——使用pytest对整合的searchpage进行测试用例编写
通过上图我们可以看出,通过POM模型思想,我们把:
- selenium方法
- 页面元素
- 页面对象
- 测试用例
以上四种代码主体进行了拆分,虽然在用例很少的情况下做会增加代码,但是当用例多的时候意义很大,代码量会在用例增加的时候显著减少。我们维护代码变得更加直观明显,代码可读性也变得比工厂模式强很多,代码复用率也极大的得到了提高。
这篇文章暂时到这里哟,后面会接着讲的哟。
下面是配套资料,对于做【软件测试】的朋友来说应该是最全面最完整的备战仓库,这个仓库也陪伴我走过了最艰难的路程,希望也能帮助到你!
最后: 可以在公众号:程序员小濠 ! 免费领取一份216页软件测试工程师面试宝典文档资料。以及相对应的视频学习教程免费分享!,其中包括了有基础知识、Linux必备、Shell、互联网程序原理、Mysql数据库、抓包工具专题、接口测试工具、测试进阶-Python编程、Web自动化测试、APP自动化测试、接口自动化测试、测试高级持续集成、测试架构开发测试框架、性能测试、安全测试等。
如果我的博客对你有帮助、如果你喜欢我的博客内容,请 “点赞” “评论” “收藏” 一键三连哦!