1. 从 GitHub 上获取源代码并用 Pycharm 打开
项目地址: https://github.com/tonglei100/sweetest.git
将两个 sweetest 都设置为 Sources Root, 不然导包处会出现红线
start
设置为 Sources Root
2. 开始阅读
1. 初始化自动化实例
找到 start.py, 可以发现第 24 行应该是程序入口
sweet = Autotest(plan_name, sheet_name, desired_caps, server_url)
使用 ctrl + 鼠标左键跳转至 Autotest 类
1.1 创建日志文件夹的方式
第 29 行:
- # 发现 Autotest 类中使用如下方式创建日志存放文件夹
- for p in ('JUnit', 'report', 'snapshot'):
- mkdir(p)
- # 跳转至 mkdir 处, 此处使用 Python 标准库之 pathlib
- from pathlib import Path
- def mkdir(p):
- path = Path(p)
- if not path.is_dir():
- path.mkdir()
Python 标准库之 pathlib
https://www.cnblogs.com/juneman/p/8974505.html
导入
from pathlib import Paht
初始化
- p = Path() # 当前目录
- p = Path('a','b','c/d') # 当前目录下的 a/b/c/d(相对路径)
- p = Path('/etc') # /etc 目录 (绝对路径)
路径拼接和分解
拼接操作符: /
分解: parts
- # 拼接
- p = Path()
- # p -> PosixPath('.')
- p = p / 'a'
- # p -> PosixPath('a')
- p1 = 'b' / p
- # p1 -> PosixPath('b/a')
- p2 = Path('c')
- p3 = p2/p1
- # p3 -> PosixPath('c/b/a')
- # 分解
- p3.parts
- # ('c', 'b', 'a')
is_dir() 是否是目录
创建目录
path 对象的 mkdir 方法:
def mkdir(self, mode=0o777, parents=False, exist_ok=False):
parents: 是否创建父目录, True 等同 mkdir -p;False 时, 父目录不存在, 则抛出 FileNotFoundError
exist_ok: 在 3.5 版本加入. False 时, 路径存在, 抛出 FileExistsError;True 时, FileExistsError 被忽略
1.2 导入实例化对象
第 32 行:
g.plan_name = file_name.split('-')[0]
使用 ctrl 点击 g 进行跳转至 sweetest/sweetest/globals.py
发现导入的是 g = Global() 的实例化对象 g
找到导包的语句 from sweetest.globals import g 所以应该是在导入的时候触发的实例化操作
1.3 规定内容常量化
第 33 行 - 35 行, 38 行:
self.testcase_file = str(Path('testcase') / (file_name + '-' + _testcase + '.xlsx'))
拼接 testcase_file 文件路径使用_testcase 来自
- from sweetest.config import _testcase, _elements, _report
- # 文件名后缀
- _testcase = 'TestCase' # '测试用例'
- _elements = 'Elements' # '页面元素表'
- _report = 'Report' # '测试结果'
这样就可以规定读取文件 / 输出报告的格式
1.4 Excel 操作再次封装
第 36,37,39 行:
导入语句: from sweetest.utility import Excel
点击 Excel 跳转, 由于现有的 Excel 操作库分为读取 Excel 信息和将信息写入 Excel 所以定义了 class 将二者封装在一起
- import xlrd
- import xlsxwriter
通过 def __init__(self, file_name, mode='r'): 可以看出, 实例化时需要指定操作模式, 读取的操作相对简单不进行介绍
写的操作用于报告的输出, 所以写的过程中增加了报告通过状态的判断, 不同状态有不同的样式例如:
- red = self.workbook.add_format({'bg_color': 'red', 'color': 'white'})
- if str(data[i][j]) == 'Fail':
- sheet.write(i, j, str(data[i][j]), red)
2. 执行自动化测试
start.py 中 sweet.plan() 开始执行测试, 点击 plan 进行跳转
可以发现第 70 行 self.run(sheet_name) 正式开始执行用例
2.1 使用 init 函数设置类中属性
使用类似于__init__的函数来修改类中的属性
2.2 元素等待 / 页面刷新超时时间
可以在打开实例化浏览器的时候设置元素等待 / 页面刷新超时时间
时间可以存放在一个文件中方便后续修改
- # 等待元素超时时间
- self.driver.implicitly_wait(element_wait_timeout) # seconds
- # 页面刷新超时时间
- self.driver.set_page_load_timeout(page_flash_timeout) # seconds
2.3 开始执行用例
第 117 行 ts.run()
进入函数后首先是执行 self.testsuite_start() 计数器 + 1 并记录开始时间
第 136 行 result = self.setup(testcase, case) 进入函数 def setup(self, testcase, case):
在函数内部定义了一个函数 def run_setup(testcase): 函数中
- tc = TestCase(testcase)
- tc.run()
此处真正开始执行用例
getattr(web, step['keyword'].lower())(step)
sweetest/sweetest/keywords/Web.py 处可以定义相关页面操作关键字
- getattr
- getattr(object, name[, default])
object -- 对象.
name -- 字符串, 对象属性.
default -- 默认返回值, 如果不提供该参数, 在没有对应属性时, 将触发 AttributeError.
以 open 关键字为例, 其中值得学习的内容:
2.3.1 清理缓存 / cookies
- if step['data'].get('清理缓存', '') or step['data'].get('cookie',''):
- g.driver.delete_all_cookies()
初次打开页面
获取当前窗口 handle:
handle = g.driver.current_window_handle
注册窗口名称和 handle:
self.register(step, handle)
2.3.2 打开新窗口后将其加入窗口列表里
- #value -> 'https://www.baidu.com/'
- JS = "window.open('%s')" % value
- g.driver.execute_script(JS)
- # 判断是否打开了新的窗口, 并将新窗口添加到所有窗口列表里
- all_handles = g.driver.window_handles
- for handle in all_handles:
- if handle not in w.Windows.values():
- w.register(step, handle)
register 的逻辑:
如果有提供新窗口名字, 则使用该名字, 否则使用默认名字: HOME
如果存在同名窗口:
1. 清除同名旧窗口绑定的页面
2. 切换到同名旧窗口去关闭它
3. 从窗口资源池 g.Windows 里剔除
切回当前窗口, 添加到窗口资源池 g.Windows, 把当前窗口名字改为新窗口名称
来源: http://www.jianshu.com/p/cd29bb79842c