Pythonとselenium_projectarticles_project実際の戦闘、コードの最適化、プロジェクトのリファクタリング

実際の戦闘では、1つだけ言いたいことがあります。それは、現在のプロジェクトと組み合わせて、基本的な機能をカバーするユースケースを作成することです。あなたが問題に遭遇したとき、問題を解決し、忍耐強く、あなたは終わります。
背景:コードは、Ctrip.comでチケットを予約するプロセスです。
(1)ファイルディレクトリ、各ディレクトリコード
(2)コードの最適化と再構築、コードレベルのフレームワークの概要、
(3)例外処理、ログ処理、インテリジェントな待機

(1)コードを参照してください:
ここに画像の説明を挿入します
基本的なコードレイヤーfunction.py

# 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级别的")

ビジネスコードレイヤー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)

テストコードレイヤー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)コードの最適化とリファクタリング
コードの最適化には2つのポイントがあります:
1。コードの量を減らし、再利用率を高め、堅牢性(ビッグデータの場合)、可読性、拡張性を
向上させます。2。コードの可読性と重いコードを向上させます構造は、定義された関数で実装できます。といった:

# 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()

コードのリファクタリング
コードが増えると、関数とテストコードが1つのファイルにまとめられ、拡張や保守が困難になります。したがって、関数に変数を適切に追加し、ハードコーディングを避けてください。最終的な目標は、テストコードをより簡潔かつ明確にすることです。
プロジェクトコードは3層構造に分かれています。自動化の初期段階でコード構造とアイデアを適切に計画する必要があり、コードは後の段階でますます大きくなります。
1.テストコードレイヤー
2.ビジネスコードレイヤー
3.基本コードレイヤー

基本コードレイヤー:function.pyのコンテンツなど、セレンとwebdriviverの関連構成をカプセル化します

# 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')")

ビジネスコードレイヤー:

"""
函数名: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()

テストコードレイヤー:

实现了测试用例。

いわゆるリファクタリングと最適化は、プロジェクトが進行するにつれて、テストコードレイヤーをより適切に実行できるように、基本コードレイヤーとビジネスコードレイヤーを変更する必要があることを意味します。

1.例外処理
1.Seleniumの例外処理。インターフェイス自動化の例外処理を参照してください。これは非常に優れています。一般的な例外は次のとおりです。

# 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:一个意外的警告

2、ログモジュールの簡単な紹介

# 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.インテリジェント待機
各測位要素操作の前に待機時間を追加するのは面倒なので、グローバルインテリジェント待機時間を追加します。driver.implicitly_wait(10)
は、すべての測位操作の中で、ブラウザが最も長く10秒以上待機することを意味します。 10秒でエラーが報告されます

# 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)

おすすめ

転載: blog.csdn.net/weixin_45451320/article/details/112585768