Python e selenium_project articles_project combate real, otimização de código, refatoração de projeto

No combate real, eu só quero dizer uma coisa: escrever casos de uso que cobrem funções básicas em combinação com o projeto em que você está atualmente. Quando você encontrar um problema, resolver um problema, perseverar, estará feito.
Contexto: o código é o processo de reserva de passagens no Ctrip.com.
(1) Diretório de arquivo, cada código de diretório
(2) Otimização e reconstrução de código, introdução à estrutura de nível de código,
(3) Tratamento de exceções, tratamento de log, espera inteligente

(1) Consulte o código:
Insira a descrição da imagem aqui
function.py da camada de código básica

# coding=utf-8
from datetime import datetime,date,timedelta
from selenium import webdriver
import logging,os,xlrd,xlwt
import urllib3

# 以下为driver设置和打开携程火车票网站
# driver = webdriver.Chrome()
'''
函数return_driver()的功能是返回driver对象
'''
def return_driver():
    return driver
'''
函数open_base_site(url)的功能是打开携程火车票首页面
'''
def open_base_site(url):
    driver.get(url)
'''
函数date_n(n)将返回n天后的日期
'''
def date_n(n):
    return str((date.today() + timedelta(days = +int(n))).strftime("%Y-%m-%d"))
'''
函数id将返回按照id属性来定位元素的语句
'''
def id(element):
    return driver.find_element_by_id(element)
'''
函数css将返回css selector方式来定位元素的语句
'''
def css(element):
    return driver.find_element_by_css_selector(element)
'''
函数xpath将返回xpath方式来定位元素的语句
'''
def xpath(element):
    return driver.find_element_by_xpath(element)
'''
函数js通过selenium来执行javascript语句
'''
def js(element):
    driver.execute_script(f"document.getElementById(f'{element}').removeAttribute('readonly')")
'''
函数log()定义了日志的输出格式
'''
def log(str):
    # 日志基础配置
    logging.basicConfig(
        level=logging.INFO, # 定义了日志的输出级别
        datefmt='%a,%d,%b,%Y,%H:%M:%S', # 定义了日志输出的时间格式
        filename='D:\\ui_date\\log-selenium.log', # 定义了日志输出路径文件
        filemode='a', #日志以追加的形式进入log-selenium.log
        format='%(asctime)s%(filename)s%(levelname)s%(message)s' # 定义了日志的输出形式
    )
    # 定义streamhandler格式的日志
    console = logging.StreamHandler()
    # 设置日志格式
    console.setFormatter(logging.INFO)
    console.setFormatter(logging.Formatter('%(name)-12s:%(levelname)-8s %(message)s'))
    # 给日志添加定义后的handler
    logging.getLogger('').addHandler(console)
    logging.info(str)
'''
函数read_excel是输出第几列的内容,如果不给cloumn的值,默认是以列表的形式输出所有内容
filename:文件路径一直到文件
index:索引值第几页
cloumn:第几列
'''
def read_excel(filename,index,cloumn):
    # 打开excel文件,filename是绝对路径或者相对路径下的文件
    xls = xlrd.open_workbook(filename)
    # 打开第几个sheet页
    sheet = xls.sheet_by_index(index)
    # print(sheet.nrows) 行
    # print(sheet.ncols) 列
    # 内容以字典的形式输出,不给cloum值,默认是输出所有表哥的所有内容
    dic={
    
    }
    for j in range(sheet.ncols):
        date=[]
        for i in range(sheet.nrows):
            date.append(sheet.row_values(i)[j])
        dic[j]=date
    return dic

if __name__ == "__main__":
    logging.log(logging.DEBUG,"我是dbug级别的")
    logging.log(logging.INFO,"我是info级别的")
    logging.log(logging.WARNING,"我是warning级别的")
    logging.log(logging.ERROR,"我是error级别的")
    logging.log(logging.CRITICAL,"我是critical级别的")

Camada de código comercial search_tickets.py

'''
此页面的功能是测试火车票查询的页面元素
'''
from selenium.webdriver.common.action_chains import ActionChains
from functions import date_n,id,css,xpath,js,return_driver,open_base_site
from selenium import webdriver
import time

'''
函数名:search_tickets
参数:
    from_station:出发站
    to_station:到达站
    n:是一个数字,如1表示选择明天的车票,2表示选择后天的车票
'''
def search_tickets(from_station,to_station,n):
    driver = return_driver()
    open_base_site('https://trains.ctrip.com/')
    driver.maximize_window()
    driver.implicitly_wait(10)

    # from_station = '上海'
    from_station = from_station
    # to_station = '杭州'
    to_station = to_station

    # 以下为tommorrow变量
    tomorrow = date_n(n)
    # 以下为定位出发城市和到达城市的页面元素,设置其值为以上定义值
    css('[placeholder="出发城市"]').send_keys(from_station)
    id("arriveCityName").send_keys(to_station)

    # 移除出发时间的“readonly”属性
    js("date0bj")
    time.sleep(2)

    # 清除出发时间的默认值
    id('dateObj').clear()
    time.sleep(2)

    # 以下定位为搜索车次日期
    id('dateObj').send_keys(tomorrow)

    # 以下步骤是为了解决日期控件弹出框在输入日期后无法消失的问题,以防影响测试的进行,原理是鼠标点击空白处
    ActionChains(driver).move_by_offset(0,0).click().perform()

    # 单击“车次搜索”按钮
    id('searchbtn').click()

# 实例化类,run才有结果
if __name__ == '__main__':
    search_tickets("上海","杭州",1)

Camada de código de teste test_booking_tickets.py

import time
from functions import date_n,id,css,xpath,js,return_driver,open_base_site
from search_tickets import search_tickets

# 搜索网站火车票列表
search_tickets("上海","杭州",1)
driver = return_driver()
time.sleep(2)
# 点击预订按钮
xpath("/html/body/div[7]/div/div[5]/div[3]/div/div[1]/div[6]/div[1]/a").click()
# 输入乘客姓名
css('[placeholder="姓名,请与所持证件上的一致"]').send_keys("小张")

(2) Otimização de código e refatoração
A otimização de código tem 2 pontos:
1. Reduzir a quantidade de código, aumentar a taxa de reutilização, melhorar a robustez (no caso de big data), legibilidade e expansibilidade.
2. Melhorar a legibilidade do código e código pesado estrutura pode ser implementada com uma função definida. Tal como:

# coding=utf-8
from selenium import webdriver
import time
from selenium.webdriver.common.keys import Keys

# 定义函数部分,减少代码量的且提高复用率,如果定义函数的部分必须放在测试代码前面。
def id(element):
    return driver.find_element_by_id(element)
def css(element):
    return driver.find_element_by_css_selector(element)
def xpath(element):
    return driver.find_element_by_xpath(element)
def js(element):
    return driver.execute_script("document.getElementById(" + "'" + element + "'" + ").removeAttribute('readonly')")

driver = webdriver.Chrome()
driver.get("https://www.hao123.com/")
driver.maximize_window()
# 百度网站的id值
id("kw").click()
css([adsads="sdfs"]).click()

Refatoração de código
À medida que o código aumenta, as funções e os códigos de teste são colocados em um arquivo, o que é difícil de expandir e manter.Por isso, adicione variáveis ​​à função de forma adequada e evite a codificação permanente. O objetivo final é tornar o código de teste mais conciso e claro.
O código do projeto é dividido em uma estrutura de três camadas: a estrutura do código e as ideias precisam ser bem planejadas no estágio inicial de automação, e o código se tornará cada vez maior no estágio posterior.
1. Camada de código de teste
2. Camada de código de negócios
3. Camada de código básico

Camada de código básica: encapsula a configuração relacionada de selênio e webdriviver, como o conteúdo de function.py

# coding=utf-8
from selenium import webdriver
import time
from selenium.webdriver.common.keys import Keys

# 定义函数部分,减少代码量的且提高复用率
# coding=utf-8
from selenium import webdriver
import time

# 以下为driver设置和打开测试网站
driver = webdriver.Chrome()

# def return_driver():
#     return driver
# 打开网页
# def open_base_site(url):
#     driver.get(url)

# 定义函数部分,减少代码量的且提高复用率
def id(element):
    return driver.find_element_by_id(element)
def css(element):
    return driver.find_element_by_css_selector(element)
def xpath(element):
    return driver.find_element_by_xpath(element)
def js(element):
    return driver.execute_script("document.getElementById(" + "'" + element + "'" + ").removeAttribute('readonly')")

Camada de código comercial:

"""
函数名:lang
参数:
    a是url
    b是用户名
    c是密码
"""
def land(a,b,c):
    driver = webdriver.Chrome()
    driver.get(f"{a}")
    driver.find_element_by_id("kw").send_keys(f"{b}")
    driver.find_element_by_id('mn').send_keys(f"{c}")
    driver.find_element_by_id('submit').click()
    time.sleep(1)
    driver.maximize_window()

Camada de código de teste:

实现了测试用例。

A chamada refatoração e otimização significa que conforme o projeto avança, precisamos alterar a camada de código básico e a camada de código de negócios para que nossa camada de código de teste possa ser melhor executada.

1. Tratamento de exceções 1. Tratamento de
exceções de selênio, consulte o tratamento de exceções da automação da interface, que é muito bom, as exceções comuns são as seguintes:

# coding=utf-8
import selenium
import logging

# 操作数据库的方法
class OperationDbInterface(object):
    # 初始化数据库连接
    def __int__(self, a):
        try:
            if 0 == 0:
                pass
            else:
                print("i")
            # 打开游标
            print("ok")
        except error as e:
            print('创建数据库失败|Mysql Error %d: %s' % (e.args[0], e.args[1]))
            # 配置日志格式
            logging.basicConfig(filename=config.src_path + 'E:/log/syserror.log', level=logging.DEBUG,
                                format='%(asctime)s %(filename)s[line:%(lineno)d]%(levelname)s %(message)s')
            # 获取日志
            logger = logging.getLogger(__name__)
            # 输出日志
            logger.exception(e)
            
# selenium常见的9种异常。
# (1)NoSuchElementException:选择器返回元素失败时,抛出异常
# (2)ElementNotVisibleException:定位的元素在DOM中存在,在页面不显示,不能交互时
# (3)ElementNotSelectableException:选择了不可选的元素
# (4)NoSuchFrameException:要切换的frmae不存在
# (5)NoSuchWindowException:要切换的新窗口不存在
# (6)TimeoutException:当代码执行时间超出时
# (7)NoSuchAttributeException:元素的属性找不到
# (8)UnexpectedTagNameException:当支持类没有获得预期的web元素时
# (9)NoAlertPresentException:一个意外的警告

Dois, uma breve introdução ao módulo de log

# coding=utf-8
import logging
'''
函数log()定义了日志的基础配置
'''
def log(str):
    # 日志基础配置
    logging.basicConfig(
        level=logging.INFO, # 定义了日志的输出级别
        datefmt='%a,%d,%b,%Y,%H:%M:%S', # 定义了日志输出的时间格式
        filename='D:\\ui_date\\log-selenium.log', # 定义了日志输出路径文件
        filemode='a', #日志以追加的形式进入log-selenium.log
        format='%(asctime)s%(filename)s%(levelname)s%(message)s' # 定义了日志的输出形式
    )
    # 定义streamhandler格式的日志
    console = logging.StreamHandler()
    # 设置日志格式
    console.setFormatter(logging.INFO)
    console.setFormatter(logging.Formatter('%(name)-12s:%(levelname)-8s %(message)s'))
    # 给日志添加定义后的handler
    logging.getLogger('').addHandler(console)
    logging.info(str)

if __name__ == "__main__":
    logging.log(logging.DEBUG,"我是dbug级别的")
    logging.log(logging.INFO,"我是info级别的")
    logging.log(logging.WARNING,"我是warning级别的")
    logging.log(logging.ERROR,"我是error级别的")
    logging.log(logging.CRITICAL,"我是critical级别的")

3. Espera inteligente
Porque é muito problemático adicionar tempo de espera antes de cada operação de elemento de posicionamento, então adicione o tempo de espera inteligente global: driver.implicitly_wait (10)
significa: entre todas as operações de posicionamento, o navegador espera mais de 10 segundos, mais de 10 segundos reportarão um erro

# coding=utf-8
from selenium import webdriver
import time
from selenium.common import exceptions as ex

driver = webdriver.Chrome()
driver.get("https://www.hao123.com/")
driver.maximize_window()
driver.implicitly_wait(10)

Acho que você gosta

Origin blog.csdn.net/weixin_45451320/article/details/112585768
Recomendado
Clasificación