https://blog.csdn.net/weixin_45912307/article/details/108955085
1.配置虚拟环境, 请参考之前一篇文章:https://blog.csdn.net/weixin_45912307/article/details/108347547
2. 创建项目虚拟环境
mkvirtualenv -p python3 虚拟环境名称
1. 点击 new project
2. 先找到刚刚创建好的虚拟环境目录
4. 选择好虚拟环境,选择好工程目录,点击创建
5. 创建好的工程目录架构
2.1 base_page.py
页面公共函数
# —— coding :utf-8 ——
# @time: 2020/10/7 20:58
# @IDE: webTest_frmewok_v2.0
# @Author: jsonLiu
# @Email: [email protected]
# @File: base_page.py
import logging
import datetime
from selenium.webdriver import ActionChains
from selenium.webdriver.common.keys import Keys
from Common.file_path import screenshots_path
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
import time
import win32gui
import win32con
# pip install pywin32
class BasePage:
def __init__(self, driver):
self.driver = driver
# 1. 等待元素可见
def wait_eleVisible(self, locator, timeout=20, poll_frequency=0.5, doc=""):
"""
:param locator: 元素定位,元组形式。 (元素类型,元素定位方式)
:param timeout:
:param poll_frequency:
:param doc: 模块名称_页面名称_操作名称
:return:
"""
logging.info('等待元素可见:{}可见'.format(locator))
try:
# 开始等待时间
start_time = datetime.datetime.now()
WebDriverWait(self.driver, timeout, poll_frequency).until(EC.visibility_of_element_located(locator))
# 结束等待时间
end_time = datetime.datetime.now()
# 等待时长,转换为s
wait_times = (end_time - start_time).seconds
logging.info(
"{0}:元素:{1}已可见,等待起始时间:{2},等待结束时间:{3},等待时间:{4}".format(doc, locator, start_time, end_time, wait_times))
except:
# 铺获异常到日志中
# 截图--保存到指定目录
logging.exception('等待元素可见失败!')
self.save_screenshot(doc)
raise
# 2. 判断元素是否存在
def ele_isExist(self, locator, timeout=10, doc=""):
logging.info("{}中是否存在元素:{}".format(doc, locator))
try:
WebDriverWait(self.driver, timeout).until(EC.visibility_of_element_located(locator))
logging.info("{0}秒内页面{1}存在中存在元素:{2}".format(timeout, doc, locator))
return True
except:
logging.exception("{0}秒内页面{1}存在中不存在元素:{2}".format(timeout, doc, locator))
return False
# 3. 查找元素
def find_element(self, locator, doc=""):
logging.info('{0}查找元素:{1}'.format(doc, locator))
try:
return self.driver.find_element(*locator)
except:
logging.exception('查找元素失败')
self.save_screenshot(doc)
raise
# 3. 判断元素是否存在
# 4. 点击操作
def click_element(self, locator, doc):
ele = self.find_element(locator, doc)
logging.info('{0}点击元素:{1}'.format(doc, locator))
try:
ele.click()
logging.info('{0}点击元素:{1}成功'.format(doc, locator))
except:
logging.exception('元素点击操作失败!')
self.save_screenshot(doc)
raise
# 5. 输入操作
def input_text(self, locator, content, doc=""):
ele = self.find_element(locator, doc)
logging.info('{0}元素:{1}输入文本'.format(doc, locator))
try:
logging.info('{0}元素:{1},输入内容为:{2}'.format(doc, locator, content))
ele.send_keys(content)
except:
logging.exception('{0}元素:{1}输入失败'.format(doc, locator))
self.save_screenshot(doc)
raise
# 6. 获取元素文本
def get_element_text(self, locator, text, doc=""):
ele = self.find_element(locator, doc)
logging.info('{0}获取元素:{1}的文本内容'.format(doc, locator))
try:
text = ele.text
logging.info('{0}获取元素:{1}的文本内容为:{2}'.format(doc, locator, text))
return text
except:
logging.exception('获取元素:{}文本内容失败'.format(locator))
self.save_screenshot(doc)
raise
# 7. 获取元素属性
def get_element_attribute(self, locator, attr, doc=""):
ele = self.find_element(locator, doc)
logging.info('{0}获取元素:{1}的属性:{2}'.format(doc, locator, attr))
try:
ele_attr = ele.get_attribute(attr)
logging.info('{0}元素:{1}的属性:{2}值为:{3}'.format(doc, locator, attr, ele_attr))
return ele_attr
except:
logging.exception('{}获取元素:{}的属性失败'.format(doc, locator))
self.save_screenshot(doc)
raise
# 8. alert处理
def switch_to_alert(self, timeout=30, poll_frequency=0.5, action='accept', doc=""):
logging.info('{0}_切换alert弹框'.format(doc))
try:
WebDriverWait(self.driver, timeout, poll_frequency).until(EC.alert_is_present())
alert = self.driver.switch_to.alert
value = alert.text
logging.info('{0}当前弹框内容为:{1}'.format(doc, value))
if action == 'accept':
alert.accept()
elif action == 'dismiss':
alert.dismiss()
return value
except:
logging.exception('{}弹框操作失败!'.format(doc))
self.save_screenshot(doc)
raise
# 9. 保存截图
def save_screenshot(self, doc):
# 图片名称:模块名_页面名称_操作名称_年-月-日_时分秒.png
# filePath = "截图路径" + "{0}".format(time.strftime("%Y%m%d%H%M%S"))
filePath = screenshots_path + "{0}_{1}.png".format(doc, time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()))
try:
self.driver.save_screenshot(filePath)
logging.info("截取网页成功,文件路径为:{}".format(filePath))
except:
logging.exception('保存网页失败!')
raise
# 10. 滚动条处理
def scrollbal_handle(self,url,mode='foot',doc=""):
global js
logging.info('{}进行滚动条操作'.format(doc))
try:
self.driver.get(url)
if mode=='top':
# 滚动到顶部
js = "window.scrollTo(0,0)"
self.driver.execute_script(js)
else:
# 滚动到底部
js = "window.scrollTo(0,document.body.scrollHeight)"
self.driver.execute_script(js)
logging.info('{}滚动成功'.format(doc))
except:
logging.exception('{}滚动操作失败'.format(doc))
self.save_screenshot(doc)
raise
# 11. 上传操作
def upload_file(self, UpfilePath,doc=""):
logging.info('{}进行文件上传'.format(doc))
try:
dialog = win32gui.FindWindow('#32770', '打开') # 一级
# 二级窗口
ComBoxEx32 = win32gui.FindWindowEx(dialog, 0, 'ComBoxEx32', None)
# 三级窗口
ComboBox = win32gui.FindWindowEx(ComBoxEx32, 0, 'ComboBox', None)
# 四级窗口
edit = win32gui.FindWindowEx(ComboBox, 0, 'Edit', None)
button = win32gui.FindWindowEx(dialog, 0, 'Button', "打开(&0)")
# 操作
# 输入文件地址
win32gui.SendMessage(edit, win32con.WM_SETTEXT, None, UpfilePath) # 发送文件路径
# 打开文件按钮
win32gui.SendMessage(dialog, win32con.WM_COMMAND, 1, button) # 点击打开按钮
logging.info('{}文件上传成功'.format(doc))
except:
logging.exception('{}文件上传操作失败'.format(doc))
self.save_screenshot(doc)
raise
# 12. iframe切换
def switch_to_frame(self,locator,doc=""):
ele = self.find_element(locator)
logging.info('{}表单切换'.format(doc))
try:
self.driver.switch_to.frame(ele)
logging.info('{}切换表单成功'.format(doc))
except:
logging.exception('{}切换表单失败!'.format(doc))
self.save_screenshot(doc)
raise
# 13. 窗口切换
def switch_to_window(self, window_reference, timeout=30, poll_frequency=0.5, window_handles=None, doc=""):
logging.info("{0}_切换窗口".format(doc))
try:
if window_reference == "new":
if window_handles:
WebDriverWait(timeout, poll_frequency).until(EC.new_window_is_opened(window_handles))
current_window_handles = self.driver.window_handles
self.driver.switch_to.window(current_window_handles[-1])
else:
logging.exception("打开新窗口时,请传入window_handles参数")
raise ("打开新窗口时,请传入window_handles参数")
elif window_reference == "default":
self.driver.switch_to.default_content()
else:
self.driver.switch_to.window(window_reference)
logging.info("{0}_切换窗口成功".format(doc))
except:
logging.exception("{0}_切换窗口失败".format(doc))
self.save_screenshot(doc)
raise
# 14. 执行js
def execute_script(self, js_str, element_info=None,doc=""):
logging.info('{}执行js'.format(doc))
try:
if element_info:
self.driver.execute_script(js_str)
else:
self.driver.execute_script(js_str, None)
logging.info('{}执行js成功'.format(doc))
except:
logging.exception('{}执行js操作失败'.format(doc))
self.save_screenshot(doc)
raise
# 15. 鼠标事件
# 元素鼠标操作:右击-测试OK
def context_click(self, locator):
mouse = ActionChains(self.driver)
ele = self.find_element(self,locator)
logging.info('{}元素进行右击操作'.format(locator))
mouse.context_click(ele).perform()
# 元素鼠标操作:移动到该元素上--测试OK
def move_to_element_by_mouse(self, locator):
ele = self.find_element(locator)
mouse = ActionChains(self.driver)
logging.info('将鼠标移动到{}元素上'.format(locator))
mouse.move_to_element(ele).perform()
# 长按元素
def long_press_element(self, locator, seconds):
ele = self.find_element(locator)
logging.info('将鼠标长按到{}元素上后松开'.format(locator))
mouse = ActionChains(self.driver)
mouse.click_and_hold(ele).pause(seconds).release(ele)
def scrollIntoView(self, locator):
ele = self.find_element(locator)
logging.info('将滚动条滚动至{}元素可见'.format(locator))
self.driver.execute_script('arguments[0].scrollIntoView();', ele)
time.sleep(1)
# 16. 键盘事件
# 删除内容-测试OK
def back_space(self, locator):
ele = self.find_element(locator)
logging.info('{0}元素操作back_space'.format(locator))
ele.send_keys(Keys.BACK_SPACE)
# 清空内容--测试OK
def clear_input(self,locator):
ele = self.find_element(locator)
logging.info('{}元素输入框操作清空'.format(locator))
ele.clear()
# 按回车--测试OK
def enter(self, locator):
ele = self.find_element(locator)
logging.info('{}元素进行回车键操作'.format(logging))
ele.send_keys(Keys.ENTER)
# 全选 Ctrl+a--测试OK
def ctrl_a(self,locator):
ele = self.find_element(locator)
logging.info('{}元素输入框内容进行全选操作'.format(locator))
ele.send_keys(Keys.CONTROL, 'a')
# 粘贴 Ctrl +x--测试OK
def ctrl_x(self,locator):
ele = self.find_element(locator)
logging.info('{}元素输入框内容进行剪切操作'.format(locator))
ele.send_keys(Keys.CONTROL, 'x')
# 粘贴 Ctrl +v--测试OK
def ctrl_v(self, locator):
ele = self.find_element(locator)
logging.info('{}元素输入框内容进行粘贴操作'.format(locator))
ele.send_keys(Keys.CONTROL, 'v')
# 17. 等待操作
def implicitly_wait(self, seconds=30):
self.driver.implicitly_wait(seconds)
def wait(self, seconds=20):
time.sleep(seconds)
# 18.浏览器操作
def open_url(self, url):
self.driver.get(url)
logging.info('打开URL地址%s;' % url)
def set_browser_max(self):
self.driver.maximize_window()
logging.info("设置浏览器的最大化")
def close_tab(self):
self.driver.close()
logging.info('关闭当前的tab页签')
def set_browser_min(self):
self.driver.minimize_window()
logging.info("设置浏览器的最小化")
def browser_refresh(self):
self.driver.refresh()
logging.info("浏览器的刷新操作")
def get_title(self):
value = self.driver.title
logging.info("获取网页的标题为:%s" % value)
return value
def quit_browser(self):
self.driver.quit()
logging.info("关闭浏览器")
2.2 file_path.py
路径文件
# —— coding :utf-8 ——
# @time: 2020/10/7 20:58
# @IDE: webTest_frmewok_v2.0
# @Author: jsonLiu
# @Email: [email protected]
# @File: file_path.py
import os
# base_path = os.path.split(os.path.split(os.path.realpath(__file__))[0])[0] 二选1
base_path = os.path.split(os.path.split(os.path.abspath(__file__))[0])[0]
# 测试数据路径
TestDatas_path = os.path.join(base_path, 'TestDatas')
# 测试用例路径
TestCases_path = os.path.join(base_path, 'TestCases')
# 报告路径
reports_path = os.path.join(base_path, r'Outputs\reports')
allure_reports_path = os.path.join(base_path,r'Outputs\allure_reports')
# 截图路径
screenshots_path = os.path.join(base_path, r'Outputs\screenshots')
# 日志路径
logs_path = os.path.join(base_path, r'Outputs\logs')
# config_dir = os.path.join(base_path,'Config')
if __name__ == '__main__':
print(logs_path)
2.3 my_log.py
自定义日志配置文件
import logging
from logging.handlers import RotatingFileHandler
import time
from Common import file_dir
fmt = " %(asctime)s %(levelname)s %(filename)s %(funcName)s [ line:%(lineno)d ] %(message)s"
datefmt = '%a, %d %b %Y %H:%M:%S'
handler_1 = logging.StreamHandler()
curTime = time.strftime("%Y-%m-%d %H%M", time.localtime())
handler_2 = RotatingFileHandler(file_dir.logs_path + "/Web_Autotest_{0}.log".format(curTime), backupCount=20, encoding='utf-8')
#设置rootlogger 的输出内容形式,输出渠道
logging.basicConfig(format=fmt,datefmt=datefmt,level=logging.INFO,handlers=[handler_1,handler_2])
2.4 send_email.py
发送邮件文件
# —— coding :utf-8 ——
# @time: 2020/10/7 20:59
# @IDE: webTest_frmewok_v2.0
# @Author: jsonLiu
# @Email: [email protected]
# @File: send_email.py
"""
使用一个邮箱向另一个邮箱发送测试报告的html文件,这里需要对发送邮件的邮箱进行设置,获取邮箱授权码。
username=“发送邮件的邮箱”, password=“邮箱授权码”
这里要特别注意password不是邮箱密码而是邮箱授权码。
mail_server = "发送邮箱的服务器地址"
这里常用的有 qq邮箱——"stmp.qq.com", 163邮箱——"stmp.163.com"
其他邮箱服务器地址可自行百度
"""
import os
import smtplib
from email.mime.text import MIMEText
from email.header import Header
import time
# 自动发送邮件
class SendEmail():
def send_email(self, new_report):
# 读取测试报告中的内容作为邮件的内容
with open(new_report, 'r', encoding='utf8') as f:
mail_body = f.read()
# 发件人地址
send_addr = '[email protected]'
# 收件人地址
reciver_addr = '[email protected]'
# 发送邮箱的服务器地址 qq邮箱是'smtp.qq.com', 163邮箱是'smtp.163.com'
mail_server = 'smtp.qq.com'
now = time.strftime("%Y-%m-%d %H:%M:%S")
# 邮件标题
subject = '接口自动化测试报告' + now
# 发件人的邮箱及邮箱授权码
username = '[email protected]'
password = 'moasmyxgojcgbbch' # 注意这里是邮箱的授权码而不是邮箱密码
# 邮箱的内容和标题
message = MIMEText(mail_body, 'html', 'utf8') # MIMEText(邮箱主体内容,内容类型,字符集)
message['Subject'] = Header(subject, charset='utf8')
# 发送邮件,使用的使smtp协议
smtp = smtplib.SMTP()
smtp.connect(mail_server)
smtp.login(username, password)
smtp.sendmail(send_addr, reciver_addr.split(','), message.as_string())
smtp.quit()
# 获取最新的测试报告地址
def acquire_report_address(self, reports_address):
# 测试报告文件夹中的所有文件加入到列表
test_reports_list = os.listdir(reports_address)
# 按照升序排序生成新的列表
new_test_reports_list = sorted(test_reports_list)
# 获取最新的测试报告
the_last_report = new_test_reports_list[-1]
# 最新的测试报告地址
the_last_report_address = os.path.join(reports_address, the_last_report)
return the_last_report_address
if __name__ == '__main__':
# 测试报告存放位置
test_reports_address = '../test_result/html_report'
# 查找最新生成的测试报告地址
new_report_addr = SendEmail().acquire_report_address(test_reports_address)
# 自动发送邮件
SendEmail().send_email(new_report_addr)
此前已经解析,不再重复
4.1 indexpage_locators.py
首页元素定位文件
from selenium.webdriver.common.by import By
# 用户名
user_link = (By.XPATH,'//a[@href="/Member/index.html"]')
# 投标按钮
bid_button = (By.XPATH,'//*[text()="抢投标"]') #//a[@class="btn btn-special"]
4.2 investpage_locators.py
投资页面元素定位文件
# —— coding :utf-8 ——
# @time: 2020/10/7 20:59
# @IDE: webTest_frmewok_v2.0
# @Author: jsonLiu
# @Email: [email protected]
# @File: investpage_locators.py
from selenium.webdriver.common.by import By
# 投资输入框
money_input = (By.XPATH,'//input[contains(@class,"invest-unit-investinput")]')
#投标点击按钮
invest_button = (By.XPATH,'//div[@class="body"]//button')
# 投资成功弹窗的查看并激活按钮
active_button_on_success_pop = (By.XPATH,'//div[@class="layui-layer-content"]//button')
# 投标按钮上的错误信息
errorMsg_from_investButton = (By.XPATH,'//div[@class="layui-layer-content"]')
# 页面中间的错误提示信息
errorMsg_from_pageCenter = (By.XPATH,'//div/button[@class="btn btn-special height_style"]/text()')
4.3 loginpage_locators.py
登录页元素定位文件
4.4 其他页面元素定位根据需求自行创建封装
5.1 index_page.py
# —— coding :utf-8 ——
# @time: 2020/10/7 21:00
# @IDE: webTest_frmewok_v2.0
# @Author: jsonLiu
# @Email: [email protected]
# @File: index_page.py
import random
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By
from PageLocators import indexpage_locators as loc
class IndexPage:
def __init__(self,driver):
self.driver = driver
def isExist_logout_ele(self):
# 等待5s,元素没有出现 //a[@href="/Index/logout.html"]
# 如果存在返回True,如果不存在,返回False
try:
WebDriverWait(self.driver, 5).until(EC.visibility_of_element_located((By.XPATH, '//a[@href="/Index/logout.html"]')))
return True
except:
return False
# 选标操作 --默认选第一个 = 元素定位的时候,过滤掉不可以投的标
def click_first_bid(self):
WebDriverWait(self.driver,10).until(EC.visibility_of_element_located(loc.bid_button))
self.driver.find_element(*loc.bid_button).click()
# 随机选一个标 //*[text()="抢投标"]
def click_bid_by_random(self):
# 找到所有符合的标
WebDriverWait(self.driver, 10).until(EC.visibility_of_element_located(loc.bid_button))
eles = self.driver.find_elements(*loc.bid_button)
# 随机数
index = random.randint(0,len(eles)-1)
eles[index].click()
5.2 login_page.py
# —— coding :utf-8 ——
# @time: 2020/10/7 21:01
# @IDE: webTest_frmewok_v2.0
# @Author: jsonLiu
# @Email: [email protected]
# @File: login_page.py
from PageLocators.loginpage_locators import LoginPageLocator as loc
from Common.base_page import BasePage
class LoginPage(BasePage):
'''登录页面类'''
# 登录操作
def login(self, username, password, remember_user=True):
# 输入用户名
# 输入密码
# 点击登录
doc = "登录页面_登录功能"
self.wait_eleVisible(loc.user_input,doc=doc)
self.input_text(loc.user_input,username,doc)
self.input_text(loc.pwd_input,password,doc)
# 判断remember_user的值,决定是否勾选
self.click_element(loc.login_but,doc)
# 获取错误提示信息 ----登录区域
def get_errorMsg_from_loginArea(self):
doc = "登录页面_获取登录区域错误提示信息"
self.wait_eleVisible(loc.get_errorMsg_from_login,doc=doc)
return self.get_element_text(loc.get_errorMsg_from_login,doc)
# 获取错误提示信息---中间区域
def get_login_wrongPwd_noRegArea(self):
doc = "登录页面_获取中间区域错误提示信息"
self.wait_eleVisible(loc.get_login_wrongPwd_noReg,poll_frequency=0.2,doc=doc) # 错误的密码和没有注册提示信息在中间区域显示
return self.get_element_text(loc.get_login_wrongPwd_noReg,doc)
5.3 其他页面元素对象操作方法根据需求自行创建函数封装
6.1 conftest.py
前后置操作文件,如打开浏览器、关闭浏览器、浏览器最大化、刷新页面等
# —— coding :utf-8 ——
# @time: 2020/10/7 21:01
# @IDE: webTest_frmewok_v2.0
# @Author: jsonLiu
# @Email: [email protected]
# @File: conftest.py
from selenium import webdriver
from TestDatas import Common_datas as CD
from PageObjects.login_page import LoginPage
import pytest
driver = None
# 声明是一个fixture
@pytest.fixture(scope="class")
def access_web():
global driver
# 前置操作
print("所有用例执行之前,setup整个测试类执行一次")
driver = webdriver.Chrome()
driver.get(CD.web_login_url)
lg = LoginPage(driver)
yield (driver, lg) # 分割线:返回值
# 后置操作
print("所有用例执行完成,tearDown整个测试类执行一次")
driver.quit()
@pytest.fixture
def refresh_page():
global driver
driver = webdriver.Chrome()
# 前置操作
yield
# 后置操作
driver.refresh()
6.2 test_login.py
# —— coding :utf-8 ——
# @time: 2020/10/7 21:02
# @IDE: webTest_frmewok_v2.0
# @Author: jsonLiu
# @Email: [email protected]
# @File: test_login.py
import unittest
from selenium import webdriver
from PageObjects.login_page import LoginPage
from PageObjects.index_page import IndexPage
import ddt
from TestDatas import Common_datas as CD
from TestDatas import login_datas as LD
import pytest
@pytest.mark.usefixtures("access_web")
@pytest.mark.usefixtures("refresh_page")
class TestLogin():
# TestCase中不能写__init__
# @classmethod
# def setUpClass(cls):
# #通过excel读取本功能当中需要的所有测试数
# cls.driver = webdriver.Chrome()
# cls.driver.maximize_window()
# cls.driver.get(CD.web_login_url)
# cls.lg = LoginPage(cls.driver)
#
# @classmethod
# def tearDownClass(cls):
# cls.driver.quit()
# # def setUp(self):
# # pass
# def tearDown(self):
# '''后置'''
# # 正常用例 -登录成功
# self.driver.refresh()
# 异常用例 - 错误的手机号格式(大于11位、小于11位、为空、不在号码段) ddt
@pytest.mark.parametrize("data", LD.phone_data) # 参数化,把LD.phone_data的测试数据交给自定义参数名为data的参数
def test_login_0_user_wrongFormat(self, data, access_web):
# 步骤 输入用户名:xxx,密码:xxx,点击登录
access_web[1].login(data["user"], data["password"])
# 断言 登录页面 提示:请输入正确手机号
# 对别文件内容与期望值是否相等
assert (access_web[0].get_errorMsg_from_loginArea(), data["check"])
# 手机号没有注册
@pytest.mark.parametrize("caseData", LD.wrongPwd_noReg_data)
def test_login_1_wrongPwd_noReg(self, caseData,access_web ):
# 步骤:输入用户名:xxx, 密码:xxx 点击登录
access_web["user"].login(caseData["user"],caseData["password"])
# 断言: 登录页面 页面中间提示:此账号没有经过授权,请联系管理员! / 密码错误
# 登录页面中, --获取提示框文本内容
# 对比文本内容与期望值是否相等
assert (access_web[0].get_errorMsg_from_loginArea(), caseData["check"])
# fixture的函数名称用来接收它的返回值
@pytest.mark.smoke
def test_login_2_normal(self, access_web):
# 步骤 输入用户名:xxx,密码:xxx,点击登录
access_web[1].login(LD.success_data["user"], LD.success_data["password"])
# 断言 首页当中能找到“我的帐户”或“退出"关键字
assert IndexPage(access_web[0]).isExist_logout_ele()
if __name__ == '__main__':
pass
7.1 Common_datas.py
# 全局 --系统访问地址 --登录链接
web_login_url = "http://path_url/Index/login.html"
web_invest_url = "http://path_url/loan/loan_detail/Id/25750.html"
7.2 login_datas.py
# 正常用例 -登录成功
success_data = {"user":"13457681358","password":"123456"}
# 异常用例 - 错误的手机号格式(大于11位、小于11位、为空、不在号码段)
phone_data = [
{"user":"1345768135","password":"123456","check":"请输入正确的手机号"}, # 小于11位
{"user":"134576813588","password":"123456","check":"请输入正确的手机号"}, #大于11位
{"user":"","password":"123456","check":"请输入手机号"}, # 手机号为空
{"user":"13457681358","password":"123456","check":"请输入正确的手机号"} # 不在手机号段
]
wrongPwd_noReg_data = [
{"user":"13457681358","password":"12345","check":"帐号或密码错误!"}, # 密码错误
{"user":"13457681357","password":"123456","check":"此账号没有经过授权,请联系管理员!"}, # 账号没有授权
]
7.3 其他测试数据文件根据项目需要自行创建
web自动化测试基本框架
-Common
-Outputs
-PageLocators
-PageObjects
-TestCases
-TestDatas
-run.py
常用命令:
创建虚拟环境 mkvirtualenv -p python3 虚拟环境名字
查看虚拟环境 workon
切换虚拟环境 workon 虚拟环境名字`
退出当前虚拟环境 deactivate
删除虚拟环境 rmvirtualenv 虚拟环境名字`
导入requirements.txt工具包命令: pip install -r requirements.txt
导入requirements.txt工具包命令: pip freeze > requirements.txt
安装命令: pip install 包名
移除命令: pip uninstall 包名
查看已安装: pip list
atomicwrites==1.4.0
attrs==20.2.0
colorama==0.4.3
ddt==1.4.1
iniconfig==1.0.1
more-itertools==8.5.0
packaging==20.4
pluggy==0.13.1
py==1.9.0
pyparsing==2.4.7
pytest==6.0.2
pytest-html==2.1.1
pytest-metadata==1.10.0
pytest-rerunfailures==9.1
pywin32==228
selenium==3.141.0
six==1.15.0
toml==0.10.1
urllib3==1.25.10
import HTMLTestRunner
from Common.file_path import *
import unittest
# 实例化套件对象
s = unittest.TestSuite()
# 1.实例化TestLoader对象
# 2. 使用discover找到一个目录下所有测试用例
# 使用s
loader = unittest.TestLoader()
s.addTests(loader.discover(testcases_dir))
# # 运行
# runner = unittest.TextTestRunner()
# runner.run()
fp = open(htmlreport_dir+'/autoTest_report.html','wb')
runner = HTMLTestRunner.HTMLTestRunner(
stream=fp,
title="单元测试报告",
description="单元测试报告"
)
runner.run(s)
关于allure报告与Jenkins集成