Commit b296d423 authored by 17322369953's avatar 17322369953
Browse files

框架,登录案例推送

parent efe92e0d
# author:qinguanglei
# ddate:2023/11/13 11:03
# author:qinguanglei
# ddate:2023/11/10 16:07
url: http://scdev.cmic.com.cn:8088/beta/
account: bj_qgl
password: Gyxc12345
\ No newline at end of file
from test_login.page_login import PageLogin
from selenium.webdriver.remote.webdriver import By
class PagePurchaseOP(PageLogin):
# 采购管理元素
_purchase_management_locator = (By.XPATH, '//div[@class="menuNavItem" and @sysname="采购管理"]')
# 采购元素
_purchase_locator = (By.XPATH, '//div[@class="sec-menu" and @navname="采购"]')
# 采退元素
_return_locator = (By.XPATH, '//div[@class="sec-menu" and @navname="采退"]')
# 采购订单op
_purchase_op_locator = (By.XPATH, '//div[@class="third-menu" and @navname="采购订单(OP)"]')
# 采购iframe
_iframe_purchase_locator = (
By.XPATH, '//iframe[@class="metro-main-frame" and contains(@src,"purchases")]')
# 新建按钮
_new_locator = (By.XPATH, '//span[text() = "新建"]')
# 对话框iframe,填写订单信息需要
_sub_iframe_dialog_locator = (By.XPATH, '//iframe[contains(@name,"dialog-iframe")]')
# 请求查询公司信息按钮元素
_company_request_locator = (By.XPATH, '//input[starts-with(@id,"el-id-") and contains(@id,"-106")]/../span/span/i')
# 公司信息输入元素
_company_input_locator = (By.XPATH, '//input[@placeholder = "模糊检索:公司名称,公司编码"]')
# 公司信息搜索元素
_company_search_locator = (By.XPATH, '//input[@placeholder = "模糊检索:公司名称,公司编码"]/../span/span/i')
# 公司表dialog body
_company_dialog_locator = (
By.XPATH, '//div[starts-with(@id,"el-id-") and contains(@id,"-21") and @class="el-dialog__body"]')
# 公司表-----这个只能找绝对路径了,开发太狠了
# _company_table_locator = (
# By.XPATH, '/html/body/div[6]/div/div/div/div[1]/div[2]/div[1]/div/div/div/div[1]/div[3]/div/div[1]/div/table')
_company_table_locator = (By.CLASS_NAME, "el-table__body")
# 公司确定按钮
_company_table_ensure_locator = (By.XPATH, '//span[@class="ensureBtn"]/button/span[text() = "确定"]')
# 仓库信息
_ware_info_locator = (By.ID, 'tab-a58f571e-7488-4c22-bec0-67428972871d')
# 主体信息
_main_info_locator = (By.ID, 'tab-7667cf55-c391-4f2c-a5ba-c0f6d27b6d3a')
# 请求查询仓库元素
_ware_request_locator = (By.XPATH, '//input[starts-with(@id,"el-id-") and contains(@id,"-107")]/../span/span/i')
# 仓库输入元素
_ware_input_locator = (By.XPATH, '//input[@placeholder = "模糊检索:仓库名称,仓库编码"]')
# 仓库搜索元素
_ware_search_locator = (By.XPATH, '//input[@placeholder = "模糊检索:仓库名称,仓库编码"]/../span/span/i')
# 仓库表-----这个只能找绝对路径了,开发太狠了
# _ware_table_locator = (
# By.XPATH, '/html/body/div[8]/div/div/div/div[1]/div[2]/div[1]/div/div/div/div[1]/div[3]/div/div[1]/div/table')
# 仓库表,通过dialog定位
# _ware_table_locator = (By.XPATH, '//div[@role = "dialog" and @aria-label = "选择仓库"]/*/table[@class = "el-table__body"]')
_ware_dialog_locator = (
By.XPATH, '//div[starts-with(@id,"el-id-") and contains(@id,"-26") and @class="el-dialog__body"]')
_ware_table_locator = 'By.XPATH, "//table[@class = "el-table__body""'
# 仓库表确认元素---这中确定看着可以统一
_ware_table_ensure_locator = (By.XPATH, '//span[@class="ensureBtn"]/button/span[text() = "确定"]')
# 查询供应商请求元素
_supplier_request_locator = (By.XPATH, '//input[starts-with(@id,"el-id-") and contains(@id,"-108")]/../span/span/i')
# 供应商输入信息
_supplier_input_locator = (By.XPATH, '//input[@placeholder = "模糊检索:供应商名称,供应商编码"]')
# 供应商搜索元素
_supplier_search_locator = (By.XPATH, '//input[@placeholder = "模糊检索:供应商名称,供应商编码"]/../span/span/i')
# 供应商表元素-----这个只能找绝对路径了,开发太狠了
_supplier_table_locator = (
By.XPATH, '/html/body/div[10]/div/div/div/div[1]/div[2]/div[1]/div/div/div/div[1]/div[3]/div/div[1]/div/table')
# 供应商dialog
_supplier_dialog_locator = (
By.XPATH, '//div[starts-with(@id,"el-id-") and contains(@id,"-31") and @class="el-dialog__body"]')
# 供应商表确定元素---这中确定看着可以统一
_supplier_table_ensure_locator = (By.XPATH, './span[@class="ensureBtn"]/button/span[text() = "确定"]')
_dialog_ensure_locator = './*/span[@class="ensureBtn"]/button/span[text() = "确定"]'
# 协议请求元素
_protocol_request_locator = (By.XPATH, '//input[starts-with(@id,"el-id-") and contains(@id,"-109")]/../span/span/i')
# 协议输入元素
_protocol_input_locator = (By.XPATH,
'//input[@placeholder = "模糊检索:合同/协议号,合同号,项目编码,项目名称,业态编码,对方编码,产品线编码"]')
# 协议搜索元素
_protocol_search_locator = (By.XPATH,
'//input[@placeholder = "模糊检索:合同/协议号,合同号,项目编码,项目名称,业态编码,对方编码,产品线编码"]/../span/span/i')
# 协议dialog元素
_protocol_dialog_locator = (
By.XPATH, '//div[starts-with(@id,"el-id-") and contains(@id,"-36") and @class="el-dialog__body"]')
# 业务员请求元素
_businessman_request_locator = (
By.XPATH, '//input[starts-with(@id,"el-id-") and contains(@id,"-110")]/../span/span/i')
# 业务员输入元素
_businessman_input_locator = (By.XPATH, '//input[@placeholder="模糊检索:业务员编码,业务员名称,部门编码,部门名称"]')
# 业务员搜索元素
_businessman_search_locator = (
By.XPATH, '//input[@placeholder="模糊检索:业务员编码,业务员名称,部门编码,部门名称"]/../span/span/i')
# 业务员dialog元素
_businessman_dialog_locator = (
By.XPATH, '//div[starts-with(@id,"el-id-") and contains(@id,"-41") and @class="el-dialog__body"]')
# 商品录入按钮
_merchandise_locator = (By.XPATH, '//span[text()="商品录入"]')
# 商品dialog
_merchandise_dialog_locator = (
By.XPATH, '//div[starts-with(@id,"el-id-") and contains(@id,"-124") and @class="el-dialog__body"]')
# 商品输入元素
_merchandise_input_locator = (By.XPATH, '//input[@placeholder="模糊检索:商品编码,商品名称,规格型号,厂家物料编码"]')
# 商品搜索元素
_merchandise_search_locator = (
By.XPATH, '//input[@placeholder="模糊检索:商品编码,商品名称,规格型号,厂家物料编码"]/../span/span/i')
# dialog中的输入元素
_dialog_input_locator = './*/input[@class="el-input__inner" and @placeholder="模糊检索:商品编码,商品名称,规格型号,厂家物料编码"]'
# dialog中的搜索元素
_dialog_search_locator = './*/span[@class="el-input__prefix-inner"]/i'
"""表格中输入元素"""
_input_in_table_locator = 'input'
# 保存按钮
# _save_locator = (By.XPATH, '//*[@id="process-toolbar"]/button[4]/span/text()')
_save_locator = (By.XPATH, '//*[@id="process-toolbar"]/*/span[text()="保存"]')
# 订单号
_order_no_locator = (By.XPATH, '//*[@id="0b83dfe6-67bc-46bf-b271-5e768a59e415"]/div/div[2]/span')
# 商品明细表
_detail_table = (
By.XPATH, '//*[@id="a55ef0dd-0262-4caa-b701-684a33007ac5"]/div/div[2]/div/div/div[2]/div[2]/div[1]/div[2]/table')
# _detail_table = (
# By.XPATH, '//*[@id="a55ef0dd-0262-4caa-b701-684a33007ac5"]/*/table[@class="vxe-table--body"]')
'''获取采购管理元素'''
def get_purchase_management(self):
return self.get_element_wait_presence(self._purchase_management_locator)
'''获取采购元素'''
def get_purchase(self):
return self.get_element_wait_presence(self._purchase_locator)
'''获取采退元素'''
def get_return(self):
return self.get_element_wait_presence(self._return_locator)
'''获取采购订单op元素'''
def get_purchase_op(self):
return self.get_element_wait_presence(self._purchase_op_locator)
'''获取采购iframe元素'''
def get_iframe_purchase(self):
return self.get_element_wait_presence(self._iframe_purchase_locator)
'''获取新建按钮元素'''
def get_new(self):
return self.get_element_wait_presence(self._new_locator)
'''获取对话框iframe元素'''
def get_sub_iframe_dialog(self):
return self.get_element_wait_presence(self._sub_iframe_dialog_locator)
'''获取查询公司请求按钮'''
def get_company_request(self):
return self.get_element_wait_presence(self._company_request_locator)
'''获取公司输入信息元素'''
def get_company_input(self):
return self.get_element_wait_presence(self._company_input_locator)
'''获取公司搜索按钮元素'''
def get_company_search(self):
return self.get_element_wait_presence(self._company_search_locator)
'''获取公司表元素'''
def get_company_table(self):
# return self.get_element_wait_presence(self._company_table_locator)
# 首先获取公司dialog
company_dialog = self.get_company_dialog()
'''再从公司dialog中获取公司表'''
return self.get_table_from_dialog(company_dialog)
'''获取公司表确定按钮'''
def get_company_table_ensure(self):
return self.get_element_wait_presence(self._company_table_ensure_locator)
'''获取仓库信息'''
def get_ware_info(self):
return self.get_element_wait_presence(self._ware_info_locator)
'''获取主体信息'''
def get_main_info(self):
return self.get_element_wait_presence(self._main_info_locator)
'''获取请求查询仓库元素'''
def get_ware_request(self):
return self.get_element_wait_presence(self._ware_request_locator)
'''获取仓库输入元素'''
def get_ware_input(self):
return self.get_element_wait_presence(self._ware_input_locator)
'''获取仓库搜索元素'''
def get_ware_search(self):
return self.get_element_wait_presence(self._ware_search_locator)
'''获取仓库dialog'''
def get_ware_dialog(self):
return self.get_element_wait_presence(self._ware_dialog_locator)
'''获取仓库表元素'''
def get_ware_table(self):
ware_dialog = self.get_ware_dialog()
return self.get_table_from_dialog(ware_dialog)
'''获取仓库表确定按钮'''
def get_ware_table_ensure(self):
ware_dialog = self.get_ware_dialog()
return ware_dialog.find_element(By.XPATH, '//span[@class="ensureBtn"]/button/span[text() = "确定"]')
# return self.get_child(ware_dialog, self._ware_table_ensure_locator)
'''获取供应商dialog元素'''
def get_supplier_dialog(self):
return self.get_element_wait_presence(self._supplier_dialog_locator)
'''从dialog中获取输入元素'''
def get_input_from_dialog(self, dialog_element):
result = dialog_element.find_element(By.XPATH, self._dialog_input_locator)
self.wait_seconds(self.time_seconds)
return result
'''从dialog中获取搜索元素'''
def get_search_from_dialog(self, dialog_element):
search = dialog_element.find_element(By.XPATH, self._dialog_search_locator)
self.wait_seconds(self.time_seconds)
return search
'''从dialog中获取表信息'''
def get_table_from_dialog(self, dialog_element):
tables = dialog_element.find_elements(By.TAG_NAME, "table")
self.wait_seconds(self.time_seconds)
return tables[1]
'''从dialog中获取确定按钮'''
def get_ensure_from_dialog(self, dialog_element):
ensure = dialog_element.find_element(By.XPATH, self._dialog_ensure_locator)
return ensure
"""从表格中的一个栏位中获取输入元素"""
def get_input_from_table_field(self, field):
element = field.find_element(By.XPATH, self._input_in_table_locator)
return element
'''获取供应商请求元素'''
def get_supplier_request(self):
return self.get_element_wait_presence(self._supplier_request_locator)
'''获取供应商输入元素'''
def get_supplier_input(self):
return self.get_element_wait_presence(self._supplier_input_locator)
'''获取供应商搜索元素'''
def get_supplier_search(self):
return self.get_element_wait_presence(self._supplier_search_locator)
'''获取供应商表元素'''
def get_supplier_table(self):
return self.get_element_wait_presence(self._supplier_table_locator)
'''获取供应商表确定元素'''
def get_supplier_table_ensure(self):
return self.get_element_wait_presence(self._supplier_table_ensure_locator)
'''获取公司dialog'''
def get_company_dialog(self):
return self.get_element_wait_presence(self._company_dialog_locator)
'''获取协议请求元素'''
def get_protocol_request(self):
return self.get_element_wait_presence(self._protocol_request_locator)
'''获取协议输入元素'''
def get_protocol_input(self):
return self.get_element_wait_presence(self._protocol_input_locator)
'''获取协议搜索元素'''
def get_protocol_search(self):
return self.get_element_wait_presence(self._protocol_search_locator)
'''获取协议dialog'''
def get_protocol_dialog(self):
return self.get_element_wait_presence(self._protocol_dialog_locator)
'''获取业务员请求元素'''
def get_businessman_request(self):
return self.get_element_wait_presence(self._businessman_request_locator)
'''获取业务员输入元素'''
def get_businessman_input(self):
return self.get_element_wait_presence(self._businessman_input_locator)
'''获取业务员搜索元素'''
def get_businessman_search(self):
return self.get_element_wait_presence(self._businessman_search_locator)
'''获取业务员dialog'''
def get_businessman_dialog(self):
return self.get_element_wait_presence(self._businessman_dialog_locator)
'''商品录入按钮'''
def get_merchandise(self):
return self.get_element_wait_presence(self._merchandise_locator)
'''商品dialog按钮'''
def get_merchandise_dialog(self):
return self.get_element_wait_presence(self._merchandise_dialog_locator)
'''商品输入元素'''
def get_merchandise_input(self):
return self.get_element_wait_presence(self._merchandise_input_locator)
'''商品搜索元素'''
def get_merchandise_search(self):
return self.get_element_wait_presence(self._merchandise_search_locator)
'''保存按钮元素'''
def get_save(self):
return self.get_element_wait_presence(self._save_locator)
'''订单号'''
def get_order_no(self):
return self.get_element_wait_presence(self._order_no_locator)
'''商品明细表'''
def get_detail_table(self):
return self.get_element_wait_presence(self._detail_table)
# author:qinguanglei
# ddate:2023/11/14 16:47
# 购买多个序列号商品
import os
import time
from pip._internal.commands import inspect
from selenium import webdriver
from selenium.webdriver import Keys
from selenium.webdriver.common.by import By
from guke.common.logger import log
from guke.common.read_yaml import get_value_by_filed_from_yaml
def test_buy_nonseq_commodities():
option = webdriver.ChromeOptions()
# option.add_experimental_option("detach", True) # 设置不要自动关闭浏览器
# 获取驱动器
driver = webdriver.Chrome(options=option)
# 最大化页面
driver.maximize_window()
driver.get("http://scdev.cmic.com.cn:8088/beta/")
driver.implicitly_wait(10)
# 获取公共信息,注意公共信息的内容在案例的同级目录下
# 获取本案例的绝对路径,绝对路径的目录就是该案例的同级目录
# 需要知道哪个文件名
direction = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'data.yaml')
# 取文件中的user栏位
account = get_value_by_filed_from_yaml(direction, 'account')
# 取文件中的password栏位
password = get_value_by_filed_from_yaml(direction, 'password')
log.info('获取的密码为%s', password)
root_dir = os.path.abspath(os.sep)
print(root_dir)
# BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
# user =
driver.find_element(By.ID, 'input1').clear()
driver.find_element(By.ID, 'input1').send_keys(account)
driver.find_element(By.ID, 'input2').clear()
driver.find_element(By.ID, 'input2').send_keys(password)
driver.find_element(By.ID, 'input2').send_keys(Keys.ENTER)
time.sleep(1)
# author:qinguanglei
# ddate:2023/11/14 16:47
# 购买一个非序列号商品
\ No newline at end of file
# author:qinguanglei
# ddate:2023/11/14 16:47
# 购买1个序列号商品
\ No newline at end of file
# author:qinguanglei
# ddate:2023/11/14 16:47
# 购买多个序列号商品
\ No newline at end of file
# author:qinguanglei
# ddate:2023/11/13 15:32
# 登录验证码错误
VERIFY_CODE_ERROR = "验证码错误!!"
# 登录用户名或者密码错误
USER_PASSWORD_ERROR = "用户名或密码错误"
# 登录成功
LOGIN_SUCCESS = "欢迎来到国药器械"
# 登录不输入用户名或者密码
NO_USER_OR_PASSWORD = "不适当的用户名或口令,请重新确认"
# 登录不输入验证码
NO_VERIFY_CODE = "请输入验证码后再登录!!"
"""公司id与名字"""
COMPANY_ID_NAME = {"00122": "国药集团四川省医疗器械有限公司", "00132": "国药集团重庆医疗器械有限公司",
"00103": "国药集团北京医疗器械有限公司"}
"""保存成功"""
SAVE_SUCCESS = "保存成功"
"""提交成功"""
SUBMITTED_SUCCESS = "已提交"
import pymysql
from dbutils.pooled_db import PooledDB
pool = PooledDB(
creator=pymysql,
# 连接池允许的最大链接数,0和None表示不限制连接数
maxconnections=6,
# 初始化时,连接池中最少创建的空闲链接,0表示不创建
mincached=2,
# 连接池中最多闲置的链接,0和None表示不限制连接数
maxcached=5,
# 链接池中最多的共享链接数量,0和None表示全部共享,
# PS: 无用,因为pymysql和MySQLdb等模块的 threadsafety都为1,所有值无论设置为多少,_maxcached永远为0,所以永远是所有链接都共享。
maxshared=0,
# 连接池中如果没有可用的链接后,是否阻塞等待。True:等待;False:不等待然后报错。
blocking=True,
# 一个链接最多被重复使用的次数,None表示无限制
maxusage=None,
# 开始会话前执行的命令列表,如:["set datestyle to ...", "set time zone ..."]
setsession=[],
# ping MySQL服务端,检查是否服务可用。# 如:0 = None = never, 1 = default = whenever it is requested,
# 2 = when a cursor is created, 4 = when a query is executed, 7 = always
ping=0,
# 数据库ip
host='127.0.0.1',
port=3306,
user='root',
password='123456',
database='autotest',
charset='utf8'
)
class SQLHelper(object):
@staticmethod
def open():
connection = pool.connection()
cursor = connection.cursor(cursor=pymysql.cursors.DictCursor)
return connection, cursor
@staticmethod
def close(connection, cursor):
connection.commit()
cursor.close()
connection.close()
@classmethod
def fetch_one(cls, sql, args):
conn, cursor = cls.open()
cursor.execute(sql, args)
obj = cursor.fetchone()
cls.close(conn, cursor)
return obj
@classmethod
def fetch_all(cls, sql, args):
conn, cursor = cls.open()
cursor.execute(sql, args)
obj = cursor.fetchall()
cls.close(conn, cursor)
return obj
@classmethod
def fetch_many(cls, sql, args, num):
conn, cursor = cls.open()
cursor.execute(sql, args)
obj = cursor.fetchmany(num)
cls.close(conn, cursor)
return obj
@classmethod
def insert_one(cls, sql, args):
conn, cursor = cls.open()
cursor.execute(sql, args)
cls.close(conn, cursor)
@classmethod
def update_one(cls, sql, args):
conn, cursor = cls.open()
cursor.execute(sql, args)
cls.close(conn, cursor)
"""
日志生成步骤:
1,设置存放日志的目录,不存在则创建。
2,设置日志的级别’DE_BUG‘,’INFO‘,’WARING‘,’ERROR‘,CRITICAL’.
3,设置写入日志的格式‘[%(asctime)s][%(threadName)s][line:%(lineno)d] %(levelname)s: %(message)s’
4,设置控制台输出
5,设置日志文件名
6,确保每日生成不同的日志文件,且能够区分生成时间,可用logging.handlers.TimeRotatingFileHandler进行处理,使用之前先进行导入
7,将日志对象添加到logger里
8,进行调用即可get_logger(name="test")
9,日期文件全部进去根目录的autotest_sc_log目录下,将日志文件与项目分离,后续可以使用filebet进行日志采集,进入日志云查询日志
"""
import logging
import os
import time
from logging.handlers import TimedRotatingFileHandler
class Log(object):
def __init__(self):
# 获取日志器
self.logger = logging.getLogger()
# 先设置日志的的基础显示等级
self.logger.setLevel(logging.INFO)
# 设置日志的格式‘[%(asctime)s][%(threadName)s][line:%(lineno)d] %(levelname)s: %(message)s’
formatter = '[%(asctime)s] [proc:%(process)d] [%(threadName)s:%(thread)d] [%(filename)s::%(funcName)s:line_%(lineno)d] %(levelname)s: %(message)s'
log_formatter = logging.Formatter(formatter)
# 设置存放日志的目录,不存在则创建。
# 此时目录结构不要随便更改,因为直接与路径挂钩
# 直接拼接目录
abs_path = os.path.abspath(__file__)
# 往上一级到common
common_dir = os.path.dirname(abs_path)
# 往上一级到项目目录
project_dir = os.path.dirname(common_dir)
# 开始拼接日志目录
log_dir = os.path.join(project_dir, 'log')
# 若该目录不存在则创建该目录
if not os.path.exists(log_dir):
os.mkdir(log_dir)
# 设置日志文件名
log_file_name = time.strftime('%Y-%m-%d', time.localtime(time.time())) + '.log'
'''
实例化TimedRotatingFileHandler
filename:日志文件名。
when:日志文件按什么切分。'S'-秒;'M'-分钟;'H'-小时;'D'-天;'W'-周
这里需要注意,如果选择D-天,那么这个不是严格意义上的‘天’,是从你项目启动开始,过了24小时,才会重新创建一个新的日志文件,如果
项目重启,这个时间就会重置。选择‘MIDNIGHT’是指过了凌晨12点就会创建新的日志。
interval:时间间隔
backupCount:是保留日志的个数。默认是0,不会自动删除,如何超过这个数就会自动删除
'''
# 创建文件日志与控制台日志处理器
file_handler = TimedRotatingFileHandler(filename=os.path.join(log_dir, log_file_name),
when='MIDNIGHT',
interval=1,
backupCount=3,
encoding='utf-8')
console_handler = logging.StreamHandler()
# 设置文件日志与控制台日志格式
file_handler.setFormatter(log_formatter)
console_handler.setFormatter(log_formatter)
# 设置文件日志与控制台日志基础等级
# 设置日志的级别’DE_BUG‘,’INFO‘,’WARING‘,’ERROR‘,CRITICAL’.
file_handler.setLevel(logging.INFO)
console_handler.setLevel(logging.INFO)
# 添加日志处理器,文件日志与控制台日志
self.logger.addHandler(file_handler)
self.logger.addHandler(console_handler)
# 实例化,后面直接引入使用
log = Log().logger
# author:qinguanglei
# ddate:2023/11/14 16:14
# 该功能为读取yaml数据功能
import yaml
import os
from common.logger import log
def read_yaml(yaml_path):
'''读取yaml文件内容
参数path: 相对路径,起始路径:项目的根目录
realPath: 文件的真实路径,绝对路径地址 '''
if not os.path.isfile(yaml_path):
log.error("文件路径不存在,请检查路径是否正确:%s" % yaml_path)
raise FileNotFoundError("文件路径不存在,请检查路径是否正确:%s" % yaml_path)
# open方法打开直接读出来
f = open(yaml_path, 'r', encoding='utf-8')
cfg = f.read() # 读取出来是yaml文件格式
d = yaml.load(cfg, Loader=yaml.FullLoader) # 因此我们用load方法转字典
return d
def get_filed_from_yaml(module, file, field):
# 指定module,文件名file, 栏位field,获取对应的值
# 此时目录结构不要随便更改,因为直接与路径挂钩
# 直接拼接目录
abs_path = os.path.abspath(__file__)
# 往上一级到common
common_dir = os.path.dirname(abs_path)
# 往上一级到项目目录
project_dir = os.path.dirname(common_dir)
# 开始拼接目录
yaml_path = project_dir + os.sep + "data" + os.sep + module + os.sep + file + ".yaml"
log.info(f'当前的yaml文件路径:{yaml_path}')
# 获取读取的结果,为字典形式
dictionary = read_yaml(yaml_path)
log.info(f'文件{file}中字段{field}值为{dictionary[field]}')
# 专门返回指定的栏位
return dictionary[field]
# author:qinguanglei
# ddate:2023/11/20 14:51
import os
from common.logger import log
class ScreenShot(object):
def __init__(self, driver, module, seq):
self.driver = driver
self.module = module
self.seq = str(seq)
def screen_shot(self):
# 设置截图的目录,不存在则创建。
# 此时目录结构不要随便更改,因为直接与路径挂钩
# 直接拼接目录
abs_path = os.path.abspath(__file__)
# 往上一级到common
common_dir = os.path.dirname(abs_path)
# 往上一级到项目目录
project_dir = os.path.dirname(common_dir)
# 开始拼接日志目录
screen_shot = project_dir + os.sep + 'screen_shot' + os.sep + self.module
# 若该目录不存在则创建该目录
if not os.path.exists(screen_shot):
os.mkdir(screen_shot)
# 页面截图
# 截图文件文件名
screen_shot_path = os.path.join(screen_shot, self.seq + '.png')
# 截图
self.driver.save_screenshot(screen_shot_path)
import os
from email.message import EmailMessage
from common.logger import log
import smtplib
import ssl
import zipfile
from datetime import datetime
import time
class Mail(object):
def __init__(self):
# 邮箱服务器
self.mail_host = 'smtp.qq.com'
# 邮件发送者x1
self.mail_sender = '381713747@qq.com'
# 发送者授权码
self.mail_authorization = 'insqahzqxxacbjhd'
# 邮件接受者
self.mail_receivers = 'qinguanglei@sinopharm.com'
def send(self):
context = ssl.create_default_context()
# 发送的信息实例
message = EmailMessage()
# 邮件主题
subject = '自动化测试结果,自动发送,请勿回复。'
message['subject'] = subject
# 邮件发送者
message['From'] = self.mail_sender
# 邮件接受者
message['To'] = self.mail_receivers
# 邮件内容
message.set_content("邮件内容")
try:
# 获取一个smtp对象
smtp_obj = smtplib.SMTP_SSL(self.mail_host, 465, context=context)
smtp_obj.login(self.mail_sender, self.mail_authorization)
smtp_obj.send_message(message)
smtp_obj.quit()
log.info('邮件发送成功')
except smtplib.SMTPException as e:
log.error('邮件发送失败%s' % e)
def zip_dir(self):
# 获取当前日期时间
current_time = time.strftime('%Y-%m-%d_%H:%M:%S', time.localtime(time.time()))
# 获取压缩文件主名字,直接未压缩文件目录
zip_main_name = ReadConfig().get('REPORT-FILE', 'REPORT_DIR')
# 拼接压缩文件名字
zip_name = ''.join([zip_main_name, current_time, '.zip'])
log.info(zip_name)
zip_obj = zipfile.ZipFile(zip_name, 'w', zipfile.ZIP_DEFLATED)
for root, dir_names, file_names in os.walk(zip_main_name):
fpath = root.replace(zip_main_name, '')
for file_name in file_names:
zip_obj.write(os.path.join(zip_name, file_name), os.path.join(fpath, file_name))
zip_obj.close()
log.debug('压缩成功')
import os
from pytesseract import image_to_string
from PIL import Image, ImageEnhance
from common.logger import log
def gen_text_from_picture(element_screenshot_path):
log.info('开始解析验证码')
# 打开图片,将图片转换为obj
image = Image.open(element_screenshot_path)
# 图片2直化
image = image.convert('L')
# 灰度化处理
image = ImageEnhance.Contrast(image)
image = image.enhance(3)
image2 = Image.new('RGB', (150, 60), (255, 255, 255))
image2.paste(image.copy(), (25, 10))
# 识别图中的文字
verify_code_text = image_to_string(image2)
# 针对平台,去掉最后一个字符“\n”,不同的平台最后一个字符可能不一样
verify_code_text_no_wrap = verify_code_text.replace('\n', '')
log.info("当前验证码的文字为:" + verify_code_text_no_wrap)
# 使用完成后关闭
image.close()
# 返回验证码
return verify_code_text_no_wrap
class VerifyCode(object):
def __init__(self, web_element, driver):
self.web_element = web_element
self.driver = driver
def indentify_verify_image(self):
# 先刷新验证码
self.web_element.click()
# 在首页展开后,对整个页面进行截图,截图直接保存在根目录autotest_sc_screenshot中
root_dir = os.path.abspath(os.sep)
# 截图目录
shot_dir = os.path.join(root_dir, 'autotest_sc_screenshot')
# 若该目录不存在则创建该目录
if not os.path.exists(shot_dir):
os.mkdir(shot_dir)
# 设置截图文件名, 页面截图为page.png,元素截图为element.png
page_screenshot_path = os.path.join(shot_dir, 'page.png')
element_screenshot_path = os.path.join(shot_dir, 'element.png')
# 页面截图
self.driver.save_screenshot(page_screenshot_path)
# 转换图片为Image对象
page_shot_obj = Image.open(page_screenshot_path)
# 获取验证码元素图片的位置
location = self.web_element.location
log.debug("验证码元素图片位置:%s" % location)
# 获取验证码元素图片的大小
size = self.web_element.size
log.debug("验证码元素图片大小:%s" % size)
# 获取图片的四个坐标点
left = location['x']
bottom = location['y']
right = left + size['width']
top = bottom + size['height']
log.debug("图片的四个位置。左:%s右:%s上:%s下:%s" % (left, right, top, bottom))
# 开始按照位置截图
crop_image_obj = page_shot_obj.crop((left, bottom, right, top))
# 将切割好的图片保存
crop_image_obj.save(element_screenshot_path)
# 识别验证码中的字符
verify_code_text = gen_text_from_picture(element_screenshot_path)
log.debug("当前验证码的文字为:%s" % verify_code_text)
return verify_code_text
# author:qinguanglei
# ddate:2023/11/16 10:44
# 使用注入方式,直接将driver注入到进程中,后面直接使用driver
import pytest
from selenium import webdriver
driver = None
# 配置全局的driver驱动
@pytest.fixture(scope='session', autouse=True)
def driver_fixture():
global driver
option = webdriver.ChromeOptions()
# option.add_experimental_option("detach", True) # 设置不要自动关闭浏览器
# 获取驱动器
driver = webdriver.Chrome(options=option)
# 最大化页面
driver.maximize_window()
return driver
url: http://scdev.cmic.com.cn:8088/beta/
account: bj_qgl
password: Gyxc12345
supplier: '1003207'
\ No newline at end of file
url: http://scdev.cmic.com.cn:8088/beta/
account: bj_qgl
password: Gyxc12345
# author:qinguanglei
# ddate:2023/11/16 10:44
# 使用注入方式,直接将driver注入到程序中,后面直接使用driver
import pytest
from selenium import webdriver
driver = None
# 将driver注入到程序后,后面直接使用driver就可以,无需再次定义
@pytest.fixture(scope='session', autouse=True)
def driver():
global driver
option = webdriver.ChromeOptions()
# option.add_experimental_option("detach", True) # 设置不要自动关闭浏览器
# 获取驱动器
driver = webdriver.Chrome(options=option)
# 最大化页面
driver.maximize_window()
return driver
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment